Errors
On this page
Every error has one shape and a stable error.code. Messages are static. Branch on the code.
- 400 invalid_schema
- The schema is not a usable JSON Schema object, or another request field failed validation.
- 400 document_too_large
- Over the size or page cap. See limits.
- 400 unsupported_document
- Not a document Velrim can parse, or an upload_key that does not resolve to a staged object on your account.
- 401 invalid_api_key
- Missing or malformed Authorization header, or an inactive key.
- 402 insufficient_balance
- Wallet below the job cost. The body carries top_up_url.
- 404 not_found
- No such resource. Job lookups never disclose other accounts’ jobs.
- 409 idempotency_key_conflict
- Same idempotency key with a different body, or while the first request is still running. See idempotency.
- 422 extraction_failed
- The pipeline could not produce a result. Not billed.
- 429 rate_limited
- Per-account limit. The Retry-After header and error.retry_after say when.
- 500 internal_error
- Unexpected failure on our side. Safe to retry; report it with the request_id.
- 503 provider_unavailable
- Upstream model or storage outage past retries. Safe to retry.
| Status | Code | When |
|---|---|---|
| 400 | invalid_schema | The schema is not a usable JSON Schema object, or another request field failed validation. |
| 400 | document_too_large | Over the size or page cap. See limits. |
| 400 | unsupported_document | Not a document Velrim can parse, or an upload_key that does not resolve to a staged object on your account. |
| 401 | invalid_api_key | Missing or malformed Authorization header, or an inactive key. |
| 402 | insufficient_balance | Wallet below the job cost. The body carries top_up_url. |
| 404 | not_found | No such resource. Job lookups never disclose other accounts’ jobs. |
| 409 | idempotency_key_conflict | Same idempotency key with a different body, or while the first request is still running. See idempotency. |
| 422 | extraction_failed | The pipeline could not produce a result. Not billed. |
| 429 | rate_limited | Per-account limit. The Retry-After header and error.retry_after say when. |
| 500 | internal_error | Unexpected failure on our side. Safe to retry; report it with the request_id. |
| 503 | provider_unavailable | Upstream model or storage outage past retries. Safe to retry. |
A field that cannot be extracted is not a request error: it comes back state:"missing" with a reason inside a 200. See Read the response.
Request ids
Every response carries an x-request-id header. The same id appears as error.request_id in error bodies and meta.request_id in results; for an async job, the 202 body, the result meta and the webhook delivery all carry the one id minted at admission. Include it in support requests.
Versioning
Every response carries a velrim-version header naming the contract version it was served under; the current version is 2026-08-10. Additions are not breaking: ignore unknown fields, unknown enum values and unknown webhook event types (the SDKs already do). The full promise is on Versioning and deprecation.
Service health
Unauthenticated. Returns { "ok": true, "version": "…", "calibrator_version": "…" }, where version is the deployed build id. Live status for the API, MCP server and dashboard is at /status.