Skip to content

Error reference

Every error response is JSON:

{
"error": "machine_readable_code",
"message": "Human-readable description.",
"code": 1003
}
FieldTypeNotes
errorstringStable machine-readable code — safe to switch on
messagestringEnglish description — may change, do not parse
codeintegerNumeric code — present on some errors, omit on others

Invalid request shape or missing required field.

{ "error": "type must be one of: pre-consult, clinical-note, ..." }

Do not retry. Fix the request before re-sending.

Common causes:

  • type field missing or unrecognised
  • referred_to missing on referral sessions
  • custom_questions exceeds 10 sections / 250 questions / 256 KB
  • Malformed JSON body

Missing or invalid API key.

{ "error": "Unauthorized" }

Do not retry. Check your Authorization: Bearer sn_live_… header.

Authenticated but not permitted to access this resource (e.g., cross-tenant read attempt).

{ "error": "Forbidden" }

Do not retry.

Resource doesn’t exist or belongs to a different tenant.

{ "error": "Session not found" }

Do not retry.

Idempotency body mismatch. You sent a second request with the same Idempotency-Key but a different body.

{ "error": "idempotency_conflict", "message": "Request body does not match the original for this Idempotency-Key." }

Do not retry with the same key. Generate a new Idempotency-Key for the new request.

Also returned when a session token is submitted more than once:

{ "error": "Already submitted" }

Session token has expired. The patient link is no longer valid.

{ "error": "Session link has expired" }

Create a new session with a fresh expires_in_minutes if needed.

Upload size exceeds the 50 MB per-file limit.

{ "error": "size_bytes must be 1..52428800" }

Two variants:

Daily quota exhausted:

{ "code": "daily_quota_exceeded", "limit": 1000, "used": 1000 }

Headers: Retry-After: <seconds-to-next-utc-midnight>, X-Quota-Reset: <seconds>

Per-minute rate limit:

{ "code": 1003 }

Headers: Retry-After: <seconds>, X-RateLimit-Reset: <unix>

Retry after the Retry-After interval. Idempotent replays (same Idempotency-Key) do not consume quota.

Trial quota exhausted:

{
"error": "trial_quota_exceeded",
"message": "You've used your 7-day trial limit (70/70). Try again later or upgrade.",
"used": 70,
"limit": 70,
"windowDays": 7
}

Unexpected server error.

{ "error": "Internal server error" }

Retry with exponential backoff — 500s are not cached by idempotency. Safe to retry with the same Idempotency-Key.

Gateway or upstream timeout. Treat the same as 500 — retry with backoff.


StatusRetry?How
400NoFix the request
401NoFix the API key
403NoCheck permissions
404NoResource doesn’t exist
409NoNew key for new request
410NoCreate a new session
413NoReduce file size
429YesWait for Retry-After header
500YesExponential backoff: 1s → 5s → 30s → give up
502/503/504YesSame as 500

Always pass Idempotency-Key on POST requests. On retry, reuse the same key — if the original request succeeded before the network error, you’ll get the original response back (with X-Idempotent-Replay: true) rather than creating a duplicate.


Difference between session.failed webhook and a 5xx on POST

Section titled “Difference between session.failed webhook and a 5xx on POST”
When it happensWhat it means
5xx on POST /v1/sessionsAt request timeSession was not created. Retry the POST.
session.failed webhookAfter creation, during processingSession was created and queued, but the worker failed to produce a summary. Do not re-POST — the session exists. You may inspect the session via GET /v1/sessions/:id for the error reason.

POST /v1/documents/upload-url accepts:

MIME typeFormat
application/pdfPDF (typed or scanned)
image/jpegJPEG / JPG
image/pngPNG
image/webpWebP
image/heicHEIC (iPhone photos)
image/tiffTIFF

Max file size: 50 MB per file. Max files per session: no hard limit, but map-reduce kicks in for ≥ 3 documents (processing time increases).

Processing stages: OCR (L1 rules → L2 NLP → L3 LLM) → structured extraction → available as uploaded_files context in the summary worker.