Events
Handle SDK lifecycle events and per-frame state via callbacks.
The SDK is headless — all UI state flows through callbacks set on the constructor. This page covers the lifecycle and per-frame events; see Configuration for the full callback reference.
Callback API
Register callbacks when creating the SDK instance. They remain active for all measureVitals() calls on that instance.
import { CircadifySDK } from '@circadify/web-sdk';
const sdk = new CircadifySDK({
apiKey: 'ck_live_your_key_here',
onProgress: (e) => console.log(`${e.phase}: ${e.percent}%`),
onQualityState: (q) => updateQualityMeters(q),
onQualityWarning: (w) => showToast(w.message),
onLandmarks: (lm) => renderFaceMesh(lm),
onCameraReady: ({ stream }) => mirrorStream(stream),
});typescriptTo stop receiving events, call sdk.destroy(). There is no per-callback unsubscribe mechanism — callbacks are tied to the SDK instance lifecycle.
Progress Events
The onProgress callback fires as the measurement moves through each phase. Use it to update progress bars, status text, or step indicators.
interface ProgressEvent {
phase: 'initializing' | 'readiness' | 'capturing' | 'uploading' | 'processing';
percent: number; // 0–100
elapsed: number;
remaining?: number;
}typescript| Phase | Description | Typical Duration |
|---|---|---|
initializing | Preparing SDK runtime and session state | Varies |
readiness | Waiting for face detection and quality checks to pass | User-dependent |
capturing | Capturing the measurement | Scan-duration dependent |
uploading | Uploading the measurement payload | Network dependent |
processing | Waiting for cloud processing | Network and service dependent |
Quality State Events
The onQualityState callback fires every frame during readiness and capture with the full quality picture. Use it to drive live quality meters or pills.
interface QualityState {
lighting: { brightness: number; stability: number; isOk: boolean; /* … */ };
motion: { motionMagnitude: number; isStill: boolean };
pose: { yaw: number; pitch: number; isFacingForward: boolean };
isReady: boolean;
messages: string[];
}typescriptconst sdk = new CircadifySDK({
apiKey: 'ck_live_your_key_here',
onQualityState: (q) => {
setLightingPill(q.lighting.isOk ? 'good' : 'warn');
setMotionPill(q.motion.isStill ? 'good' : 'warn');
setPosePill(q.pose.isFacingForward ? 'good' : 'warn');
setReady(q.isReady);
},
});typescriptQuality Warning Events
The onQualityWarning callback fires on transient quality drops. Use it for short-lived toasts; use onQualityState for sustained UI state.
interface QualityWarning {
type: 'lighting' | 'motion' | 'face_position' | 'occlusion';
severity: 'low' | 'medium' | 'high';
message: string;
}typescript| Warning Type | Trigger | Example Message |
|---|---|---|
lighting | Scene is too dark, too bright, or has flickering light | "Improve lighting conditions for a better scan" |
motion | Excessive head or body movement detected | "Hold still during the scan" |
face_position | Head is turned, tilted, or too far from camera | "Center your face in the frame" |
occlusion | Part of the face is blocked (hand, mask, etc.) | "Make sure your face is fully visible" |
Severity Levels
| Severity | Meaning |
|---|---|
low | Minor degradation; measurement can still proceed |
medium | Noticeable impact on accuracy; user should correct |
high | Measurement quality is severely compromised; prompt the user immediately |
Landmark Events
The onLandmarks callback emits normalized face landmarks during measurement. Use it to render a custom face overlay:
const sdk = new CircadifySDK({
apiKey: 'ck_live_your_key_here',
onLandmarks: (landmarks) => {
canvasRenderer.drawOverlay(landmarks); // 2D canvas; or use CircadifyScanView for a ready-made glow overlay
},
});typescriptPrefer the bundled CircadifyScanView from the Web SDK's React bindings over building one from this callback. For a custom overlay, use a 2D <canvas> in immediate mode (Custom UI → Face overlay) and clear it on empty-landmark frames. Don't hand-roll a three.js / @react-three/fiber overlay; if you must, see Advanced: a 3D (r3f) overlay. Landmarks are normalized [0,1] and not mirrored.
Error Handling During Measurement
Errors during measureVitals() are thrown as CircadifyError exceptions, not delivered via callbacks. Wrap your measurement call in a try/catch block to handle failures.
import { CircadifySDK, CircadifyError, CircadifyErrorCode } from '@circadify/web-sdk';
try {
const result = await sdk.measureVitals({ videoElement: myVideoEl });
} catch (error) {
if (error instanceof CircadifyError) {
if (error.isRetryable) {
showRetryPrompt(error.message);
} else {
showError(error.message);
}
}
}typescriptSee Error Codes for the full list of error codes and recovery strategies.
Next Steps
- Configuration — All SDK options including the full callback reference
- Error Codes — Complete error code reference
- Methods — SDK method reference