Skip to content

Sessions

Sessions represent a single vital signs measurement workflow. A session is created, receives an upload of preprocessed tensor data, processes it through the inference engine, and returns calibrated vital signs.

  1. Create a session via POST /sdk/session/start — returns a session ID, secure upload URL, and fallback config.

  2. Upload the preprocessed tensor to the upload URL via a PUT request.

  3. Notify the backend via POST /sdk/session/upload-complete — triggers inference processing and returns results directly in the response.

  4. Retrieve results via GET /sdk/session/result/{sessionId} — only needed when PERSIST_VITALS=true is configured for async/polling workflows.

POST /sdk/session/start

Headers:

X-API-Key: ck_test_your_key_here
Content-Type: application/json

Request 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: 300
X-RateLimit-Remaining: 299
X-RateLimit-Reset: 1712005400
X-Usage-Current: 42
X-Usage-Limit: 500
X-Usage-Remaining: 458
FieldTypeDescription
session_idstringUnique session identifier (UUID)
expires_atnumberUnix timestamp when the session expires
upload_urlstringPresigned URL for uploading the preprocessed tensor
fallback_configobjectRanges for generating fallback vitals if inference fails

Upload the preprocessed tensor directly to the upload_url returned from session creation:

Terminal window
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/webm" \
--data-binary @tensor.bin

The 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.

POST /sdk/session/upload-complete

Headers:

X-API-Key: ck_test_your_key_here
Content-Type: application/json

Request 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 backend 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.

By default (PERSIST_VITALS=false), no health data is stored server-side after this response is delivered. Session metadata is cleaned up immediately. When PERSIST_VITALS=true is configured, results are also cached for retrieval via the polling endpoint.

FieldTypeDescription
session_idstringSession identifier
statusstringAlways completed
vitalsobjectVital signs measurement results
processing_time_msnumberProcessing time in milliseconds (present on successful inference)
GET /sdk/session/result/{sessionId}

Headers:

X-API-Key: ck_test_your_key_here

Response 200 OK (completed):

{
"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
},
"completed_at": 1712001900
}

Response 200 OK (still processing):

{
"session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "processing"
}

When polling, check the status field:

  • processing — Inference is still running. Poll again in 2 seconds.
  • completed — Vitals are available in the vitals field.
  • failed — Processing failed. Fallback vitals with confidence: 0.0 may be present.
StatusDescription
createdSession initialized, awaiting upload
uploadingUpload in progress
processingInference running on backend
completedResults available
failedProcessing failed (fallback vitals may be provided)
expiredSession timed out before completion
StatusError CodeDescription
400INVALID_REQUESTMissing session_id or invalid parameters
401API_KEY_INVALIDInvalid, revoked, or missing API key
403FORBIDDENSession does not belong to this developer
404SESSION_NOT_FOUNDSession ID does not exist
429RATE_LIMIT_EXCEEDEDHourly rate limit exceeded
429QUOTA_EXCEEDEDMonthly scan quota exceeded

See Errors for the full error reference.