Error reference
Error response shape
Section titled “Error response shape”Every error response is JSON:
{ "error": "machine_readable_code", "message": "Human-readable description.", "code": 1003}| Field | Type | Notes |
|---|---|---|
error | string | Stable machine-readable code — safe to switch on |
message | string | English description — may change, do not parse |
code | integer | Numeric code — present on some errors, omit on others |
HTTP status codes
Section titled “HTTP status codes”400 Bad Request
Section titled “400 Bad Request”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:
typefield missing or unrecognisedreferred_tomissing onreferralsessionscustom_questionsexceeds 10 sections / 250 questions / 256 KB- Malformed JSON body
401 Unauthorized
Section titled “401 Unauthorized”Missing or invalid API key.
{ "error": "Unauthorized" }Do not retry. Check your Authorization: Bearer sn_live_… header.
403 Forbidden
Section titled “403 Forbidden”Authenticated but not permitted to access this resource (e.g., cross-tenant read attempt).
{ "error": "Forbidden" }Do not retry.
404 Not Found
Section titled “404 Not Found”Resource doesn’t exist or belongs to a different tenant.
{ "error": "Session not found" }Do not retry.
409 Conflict
Section titled “409 Conflict”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" }410 Gone
Section titled “410 Gone”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.
413 Payload Too Large
Section titled “413 Payload Too Large”Upload size exceeds the 50 MB per-file limit.
{ "error": "size_bytes must be 1..52428800" }429 Too Many Requests
Section titled “429 Too Many Requests”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}500 Internal Server Error
Section titled “500 Internal Server Error”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.
502 / 503 / 504
Section titled “502 / 503 / 504”Gateway or upstream timeout. Treat the same as 500 — retry with backoff.
Retry guidance
Section titled “Retry guidance”| Status | Retry? | How |
|---|---|---|
| 400 | No | Fix the request |
| 401 | No | Fix the API key |
| 403 | No | Check permissions |
| 404 | No | Resource doesn’t exist |
| 409 | No | New key for new request |
| 410 | No | Create a new session |
| 413 | No | Reduce file size |
| 429 | Yes | Wait for Retry-After header |
| 500 | Yes | Exponential backoff: 1s → 5s → 30s → give up |
| 502/503/504 | Yes | Same 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 happens | What it means | |
|---|---|---|
| 5xx on POST /v1/sessions | At request time | Session was not created. Retry the POST. |
session.failed webhook | After creation, during processing | Session 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. |
Documents API — accepted types
Section titled “Documents API — accepted types”POST /v1/documents/upload-url accepts:
| MIME type | Format |
|---|---|
application/pdf | PDF (typed or scanned) |
image/jpeg | JPEG / JPG |
image/png | PNG |
image/webp | WebP |
image/heic | HEIC (iPhone photos) |
image/tiff | TIFF |
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.