API Errors
API

Errors

On this page

Every error has one shape and a stable error.code. Messages are static. Branch on the code.

error shape
{
"error": {
"code": "insufficient_balance",
"message": "Wallet balance is below the job cost.",
"top_up_url": "…",
"request_id": "…"
}
}
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.
StatusCodeWhen
400invalid_schemaThe schema is not a usable JSON Schema object, or another request field failed validation.
400document_too_largeOver the size or page cap. See limits.
400unsupported_documentNot a document Velrim can parse, or an upload_key that does not resolve to a staged object on your account.
401invalid_api_keyMissing or malformed Authorization header, or an inactive key.
402insufficient_balanceWallet below the job cost. The body carries top_up_url.
404not_foundNo such resource. Job lookups never disclose other accounts’ jobs.
409idempotency_key_conflictSame idempotency key with a different body, or while the first request is still running. See idempotency.
422extraction_failedThe pipeline could not produce a result. Not billed.
429rate_limitedPer-account limit. The Retry-After header and error.retry_after say when.
500internal_errorUnexpected failure on our side. Safe to retry; report it with the request_id.
503provider_unavailableUpstream 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

GET /v1/health GA

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.