Sessions
Sessions represent a single vital signs measurement workflow. A session is created, receives an upload of the preprocessed RGB tensor, runs through the inference engine, and returns calibrated vital signs in the response. Nothing health-related is stored on our side.
Session Lifecycle
Section titled “Session Lifecycle”-
Create a session via
POST /sdk/session/start— returns a session ID, secure upload URL, and fallback config. -
Upload the preprocessed tensor to the upload URL via a
PUTrequest. -
Notify the backend via
POST /sdk/session/upload-complete— triggers inference and returns the vital signs synchronously in the response. The tensor and the result are not retained on our side after the response is sent.
Create a Session
Section titled “Create a Session”POST /sdk/session/startHeaders:
X-API-Key: ck_live_your_key_hereContent-Type: application/jsonRequest body (optional):
{ "demographics": { "age": 35, "sex": "M", "fitzpatrick": 3 }}Demographics are optional but improve measurement accuracy when provided.
Response 200 OK:
{ "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "expires_at": 1712001800, "upload_url": "https://upload.circadify.com/uploads/a1b2c3.../video.webm?signature=...", "fallback_config": { "heart_rate": { "min": 62, "max": 98 }, "hrv": { "min": 25, "max": 70 }, "respiratory_rate": { "min": 13, "max": 19 }, "spo2": { "min": 96, "max": 99 }, "systolic_bp": { "min": 109, "max": 134 }, "diastolic_bp_offset": { "min": 51, "max": 66 }, "confidence": 0.0 }}Response headers:
X-RateLimit-Limit: 300X-RateLimit-Remaining: 299X-RateLimit-Reset: 1712005400X-Usage-Current: 42X-Usage-Limit: 500X-Usage-Remaining: 458| Field | Type | Description |
|---|---|---|
session_id | string | Unique session identifier (UUID) |
expires_at | number | Unix timestamp when the session expires |
upload_url | string | Presigned URL for uploading the preprocessed tensor |
fallback_config | object | Ranges for generating fallback vitals if inference fails |
Upload Tensor Data
Section titled “Upload Tensor Data”Upload the preprocessed tensor directly to the upload_url returned from session creation:
curl -X PUT "$UPLOAD_URL" \ -H "Content-Type: video/webm" \ --data-binary @tensor.binThe upload goes directly to secure cloud storage — it does not pass through the API layer. The Content-Type is video/webm for compatibility, but the payload is the binary tensor produced by the SDK’s preprocessing pipeline.
See Data Flow for the exact tensor binary format.
Notify Upload Complete
Section titled “Notify Upload Complete”POST /sdk/session/upload-completeHeaders:
X-API-Key: ck_live_your_key_hereContent-Type: application/jsonRequest body:
{ "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}Response 200 OK:
{ "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "vitals": { "heart_rate": 72, "respiratory_rate": 16, "hrv": 45.2, "spo2": 98.1, "systolic_bp": 122, "diastolic_bp": 78, "confidence": 0.87 }, "processing_time_ms": 74200}This endpoint triggers inference and returns results synchronously when processing completes. Vital sign results are included directly in the response body. The response always has status completed — if inference fails, fallback vitals with confidence: 0.0 are returned instead of an error.
No health data is stored on our side after this response is delivered. The uploaded tensor is discarded and the result is not retained. The only artifact persisted from a scan is a usage record (one scan credit consumed) for billing and quota.
| Field | Type | Description |
|---|---|---|
session_id | string | Session identifier |
status | string | Always completed |
vitals | object | Vital signs measurement results |
processing_time_ms | number | Processing time in milliseconds (present on successful inference) |
Session Statuses
Section titled “Session Statuses”| Status | Description |
|---|---|
created | Session initialized, awaiting upload |
uploading | Upload in progress |
processing | Inference running on backend |
completed | Results available |
failed | Processing failed (fallback vitals may be provided) |
expired | Session timed out before completion |
Errors
Section titled “Errors”| Status | Error Code | Description |
|---|---|---|
400 | INVALID_REQUEST | Missing session_id or invalid parameters |
401 | API_KEY_INVALID | Invalid, revoked, or missing API key |
403 | FORBIDDEN | Session does not belong to this developer |
404 | SESSION_NOT_FOUND | Session ID does not exist |
429 | RATE_LIMIT_EXCEEDED | Hourly rate limit exceeded |
See Errors for the full error reference.
Next Steps
Section titled “Next Steps”- Results — Interpret vital signs data
- Rate Limits — Understand rate and quota limits
- Data Flow — Full pipeline walkthrough