Errors
What each status code means, and which failures are worth retrying.
The API uses conventional HTTP status codes, with two exceptions that matter enough to lead with: some endpoints return 500 for input you got wrong, and GET /generate/{_id} returns 500 for an ID that simply does not exist. Neither is a server fault you should retry.
Status codes
200
Success. For async submissions this means accepted, not finished
—
201
Created — returned by POST /generate
—
202
Accepted — returned by POST /extract for a multi-extraction (documentTypes) request
—
400
The request body is missing or invalid
No — fix the request
401
Missing, invalid, expired or revoked API key
No — fix the credential
404
No record with that ID
No
500
Usually a genuine server error — but see below
Sometimes
Success codes vary with the request, not only with the endpoint — POST /extract answers 200 for a single document and 202 for a multi-extraction. Accept any 2xx rather than testing for one value.
The 500 responses that are not server errors
Four endpoints return 500 where 400 belongs, when the request body is missing or malformed:
POST /extractPOST /extract/syncPOST /classifyPOST /classify/sync
Their bulk counterparts (/extract/bulk, /classify/bulk) and both generation endpoints correctly return 400 for the same mistake.
GET /generate/{_id} returns 500 for every input
Not only for unknown IDs. Tested with the exact generationId returned by POST /generate, a hyphen-stripped form, a prefixed form and a nil UUID — all four return:
There is no ID format that succeeds, so the endpoint is currently unusable. The comparable GET /document-extractions/{id} and GET /classifications/{id} both work and return a correct 404 for an unknown ID.
To collect a generated document, use POST /generate/sync — which returns the file directly — or set webhookUrl on the async request and take downloadUrl from the completion payload. See Generate a document.
The practical consequence: you cannot treat 5xx as "transient, safe to retry" on this API. A retry loop that assumes otherwise will hammer the endpoint with a request that can never succeed. Validate your payload locally, and on a 500 inspect the body before deciding to retry.
These are known defects and have been raised. They are documented here because they are the current behaviour, not because they are intended.
Error bodies
Authentication failures return a flat object:
Validation failures return a JSON array of Pydantic validation errors, not an object:
Parse defensively. A handler that assumes every error body is an object with a message key will throw on validation errors, which are an array. The two shapes are genuinely different.
The most useful fields are loc — the path to the offending property — and msg.
A job that fails is not a request that failed
Asynchronous work has two independent outcomes, and conflating them is a common mistake.
HTTP status
Whether the API accepted your call
documentStatus / status
Whether the document processed successfully
POST /extract returning 200 means the job is queued. The document can still end at Failed. Always check the job status when you retrieve the record — see Conventions for the lifecycle and the envelope trap that goes with it.
Retry guidance
401
Stop. Check the key's expiry and revocation state
400, or a 500 from one of the four endpoints above
Stop. Fix the payload
404
Stop, unless you are racing a just-submitted job
500 elsewhere, or a network timeout
Retry with exponential backoff, and cap the attempts
Job status Failed
Do not resubmit blindly — inspect the record first; a document that cannot be read will fail again
For webhook delivery retries, which follow different rules, see Webhook payloads.
What the spec says about errors
The OpenAPI document describes only 200/201 and 400. It documents no 401 — despite that being reachable on thirteen of fourteen operations — no 404, and no 5xx. POST /generate/sync has no documented responses at all.
The table at the top of this page comes from testing every operation against the live API, not from the spec.
Related pages
Authentication — the cause of most
401s.Conventions — envelopes, the status lifecycle, and the unenforced request rules that cause
400s.Webhook payloads — delivery retries and their own backoff schedule.
Last updated

