Configuration
Configure the Circadify Web SDK with all available options.
The SDK accepts a configuration object when you create a new CircadifySDK instance. Only apiKey is required.
Basic Configuration
import { CircadifySDK } from '@circadify/web-sdk';
const sdk = new CircadifySDK({
apiKey: 'ck_live_your_key_here',
});typescriptFull Configuration
const sdk = new CircadifySDK({
apiKey: 'ck_live_your_key_here',
baseUrl: 'https://api.circadify.com',
measurementDuration: 30, // accepted but currently a no-op — see the table below
debug: false,
onDeviceOnly: true,
allowFallbackVitals: false, // default — keep off; see "Fallback Vitals" below
// Per-frame callbacks for rendering custom UI:
onProgress: (e) => { /* phase + percent */ },
onQualityState: (q) => { /* full per-frame quality */ },
onQualityWarning: (w) => { /* transient warnings */ },
onLandmarks: (lm) => { /* normalized face landmarks */ },
onCameraReady: ({ stream, video }) => { /* mirror stream */ },
});typescriptConfiguration Reference
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Required. Your API key (ck_test_* or ck_live_*). |
baseUrl | string | 'https://api.circadify.com' | Custom API base URL. |
measurementDuration | number | 30 | Currently a no-op. Accepted for backward compatibility, but the 4.x capture pipeline does not consume it — capture length is fixed by the frame budget (720 frames, ≈24 s at 30 fps). Setting a different value does not change scan duration. |
debug | boolean | false | Enable debug logging to the browser console. |
onDeviceOnly | boolean | true | Requests the standard local capture and measurement payload preparation path. This does not mean results are computed fully on-device. |
allowFallbackVitals | boolean | false | Opt-in; keep off in health-adjacent products. When true, transient infrastructure failures resolve with synthetic placeholder vitals (isFallback: true, confidence: 0) instead of throwing. See Fallback Vitals. |
onProgress | (e: ProgressEvent) => void | — | Phase + percent updates throughout measurement. |
onQualityState | (q: QualityState) => void | — | Full per-frame quality state (lighting, motion, pose, readiness). Use for live quality meters. |
onQualityWarning | (w: QualityWarning) => void | — | Fires on transient warnings (lighting, motion, face_position — occlusion is declared in the type but never emitted). |
onLandmarks | (lm: Landmark[]) => void | — | Normalized face landmarks. Use to render your own face overlay. |
onCameraReady | ({ stream, video }) => void | — | Fires once after the camera is acquired. Useful for mirroring the SDK-owned video into custom UI. |
wasmConfig | WasmConfig | — | Override CDN URLs for approved self-hosted runtime assets. |
CircadifyConfig Interface
interface CircadifyConfig {
apiKey: string;
baseUrl?: string;
measurementDuration?: number;
debug?: boolean;
onDeviceOnly?: boolean;
allowFallbackVitals?: boolean;
onProgress?: (event: ProgressEvent) => void;
onQualityState?: (state: QualityState) => void;
onQualityWarning?: (warning: QualityWarning) => void;
onLandmarks?: (landmarks: Landmark[]) => void;
onCameraReady?: (info: { stream: MediaStream; video: HTMLVideoElement }) => void;
wasmConfig?: WasmConfig;
}typescriptProgress Callback
The onProgress callback fires throughout measurement with a ProgressEvent object:
interface ProgressEvent {
percent: number; // 0-100
phase: 'initializing' | 'readiness' | 'capturing' | 'uploading' | 'processing';
elapsed: number; // Seconds since measurement started
remaining?: number; // Estimated seconds remaining (when available)
captureProgress?: number; // 0–1 frame-buffer fill; only while phase === 'capturing'
}typescript| Phase | Progress | What's happening |
|---|---|---|
initializing | 0–5% | Creating session and preparing the SDK runtime |
readiness | 5–10% | Opening camera, waiting for quality checks to pass |
capturing | 10–60% | Capturing the measurement |
uploading | 60–80% | Uploading the measurement payload |
processing | 80–100% | Waiting for cloud processing |
Quality State Callback
The onQualityState callback fires every frame during readiness and capture with the full quality picture. Use it to drive live quality meters or pills.
Frames where no face is detected are skipped — the callback does not fire on them, so meters driven by this event freeze at their last values rather than degrade when the user leaves the frame. Watch onLandmarks (which fires with empty landmarks) to detect face loss.
interface QualityState {
lighting: { brightness: number; stability: number; isTooDark: boolean; isTooBright: boolean; isUnstable: boolean; isOk: boolean };
motion: { motionMagnitude: number; isStill: boolean };
pose: { yaw: number; pitch: number; isFacingForward: boolean };
isReady: boolean;
messages: string[];
}typescriptQuality Warning Callback
The onQualityWarning callback fires on transient quality drops:
interface QualityWarning {
type: 'lighting' | 'motion' | 'face_position' | 'occlusion';
message: string;
severity: 'low' | 'medium' | 'high';
}typescriptUse this for short-lived toasts ("Hold still", "Move to better lighting"). For sustained UI state, prefer onQualityState. Note that occlusion and severity 'low' exist in the type union but are never emitted by 4.x.
Landmarks Callback
The onLandmarks callback emits normalized face landmarks during measurement. Use it to render your own face overlay.
interface Landmark {
x: number; // 0-1 normalized, NOT mirrored
y: number; // 0-1 normalized, NOT mirrored
z: number; // depth (relative)
}typescriptYou usually shouldn't build one from this callback. Drop in CircadifyScanView from the Web SDK's React bindings for a ready-made glow overlay. If you need a custom one, prefer a 2D <canvas> in immediate mode — see Custom UI → Face overlay. Avoid a hand-rolled three.js / @react-three/fiber overlay (a known freeze bug from creating BufferGeometry in useMemo); if you must, follow Advanced: a 3D (r3f) overlay.
Camera Ready Callback
When you don't pass a videoElement to measureVitals(), the SDK creates an off-DOM <video> and reads from it directly. onCameraReady fires once with the live stream so you can mirror it into your own UI:
const sdk = new CircadifySDK({
apiKey: 'ck_live_your_key_here',
onCameraReady: ({ stream, video }) => {
myPreviewVideo.srcObject = stream;
},
});typescriptFallback Vitals (allowFallbackVitals)
Default: false — and we recommend leaving it off. By default, every failed measurement throws a CircadifyError; the SDK never substitutes values for a failed scan.
When you opt in with allowFallbackVitals: true, exactly three transient infrastructure failures — UPLOAD_FAILED, NETWORK_ERROR, and TIMEOUT — stop throwing when they occur during the upload/processing phase. Instead, measureVitals() resolves with a synthetic placeholder result:
isFallback: true— the marker that this is not a measurementconfidence: 0— always, so a fallback can never score as trustworthy- Vitals values that are randomized, not measured: when the session supplied a server fallback configuration (the usual case), the result carries a full set of vitals — heart rate, HRV, respiratory rate, SpO₂, and blood pressure — each drawn at random within server-supplied ranges. Only when no fallback configuration is available does the result reduce to a fixed
heartRate: 72with the other fields absent.
All other errors — quota, authentication, session, capture quality, processing failures, cancellation — always throw, regardless of this setting. So do the same three codes when they arise outside the upload/processing phase: a TIMEOUT from the 60-second capture watchdog (the scan gathered too few frames) and a NETWORK_ERROR from session start always throw.
Fallback vitals are fabricated placeholders. They are not derived from the user's face, camera, or any physiological signal. Because a fallback result usually carries a full, plausible-looking set of vitals — randomized within nominal ranges, not an obviously-degenerate placeholder — branching on isFallback is the only way to tell it apart from a real measurement. If you enable this option, your integration must check isFallback on every result and clearly present fallback results to end users as unavailable/placeholder data — never as a measured vital. Rendering a fallback heartRate as if it were real misleads the person being scanned.
When (not) to use it. This option exists for non-clinical demo surfaces where an unbroken UI flow matters more than the reading (e.g. a trade-show kiosk that must not dead-end on venue Wi-Fi). Do not enable it in any health, wellness, or care-adjacent context: Circadify provides general-wellness measurements, is not a medical device, and is not FDA-cleared — surfacing fabricated values as readings is precisely the failure mode to avoid. For development and UI testing, prefer a ck_test_ sandbox key instead, which returns deterministic simulated vitals through the real API flow.
Note: the React bindings' <CircadifyProvider> does not expose this option — fallback vitals are only reachable when you construct CircadifySDK directly. The mobile SDKs (iOS, Android) have no equivalent; they always throw on failure.
Self-Hosting Runtime Assets
For air-gapped or regulated environments, host required SDK runtime assets on your own infrastructure:
interface WasmConfig {
visionWasmUrl?: string;
visionModelUrl?: string;
geometryEngineUrl?: string;
}typescriptconst sdk = new CircadifySDK({
apiKey: 'ck_live_your_key_here',
wasmConfig: {
visionWasmUrl: 'https://your-cdn.example.com/runtime/',
visionModelUrl: 'https://your-cdn.example.com/runtime/',
geometryEngineUrl: 'https://your-cdn.example.com/runtime/geometry.js',
},
});typescriptContact support@circadify.com for approved self-hosting instructions.
Runtime assets are lazy-loaded on first measurement and cached by the browser. Subsequent measurements skip the download when the cache is valid.
Next Steps
- Methods — SDK method reference
- Events — Event handling and callbacks
- Error Codes — Error handling reference