Errors

The error shape, the full catalogue of error codes with what each means and what to do, and which status codes are safe to retry.

Last updated 12 September 2026

Errors

Every error is JSON with a stable machine-readable code and a sentence a person can act on:

{
  "error": {
    "code": "invalid_request",
    "message": "the request body does not match the Attest schema",
    "issues": [
      { "path": "evidence", "message": "provide either evidence or a batchId" }
    ]
  }
}

issues appears on invalid_request, one entry per failing field. remaining and needed appear on credits_exhausted. cap and resetsAt appear on monthly_cap_reached. failed appears on no_files_parsed, naming each file and why it failed. A refused or failed request never charges credits and carries no credit headers.

Branch on code, not on message: messages are for people and may be reworded.

Bulk calls report failures per claim

POST /attest/v1/attest/bulk answers 200 whenever the request itself was well formed, even if every claim failed. Read each result's ok first: a slot with ok: false carries an error with a code from the table below (or indeterminate, meaning Attest could not measure that claim) and no verdict, so a failure can never be mistaken for a finding.

The catalogue

| Status | Code | Meaning | What to do | | --- | --- | --- | --- | | 400 | invalid_request | The body or query does not match the schema. issues names each failing field. | Fix the named field. | | 400 | invalid_upload | The multipart body is malformed, uses an unexpected field, or a file could not be read. | Send the documented parts only, and check the file opens. | | 400 | batch_not_supported | A JSON-RPC batch was sent to the MCP surface. | Send one JSON-RPC message per request. | | 401 | unauthorized | The credential is missing, not recognised, revoked, or the wrong kind for this route. | Check the Authorization header and the key on the API keys page. | | 401 | playground_token_expired | The documentation playground's token has expired. | Reload the documentation page. | | 402 | payment_required | The workspace has no active API subscription or credits yet. | Claim starting credits, buy a pack or take a plan on the Billing page. | | 402 | credits_exhausted | The balance cannot cover this request. remaining and needed say by how much. | Add credits or take a plan. | | 403 | insufficient_scope | The key is not scoped to this service. | Create a key that includes it. | | 403 | url_not_allowed | Kerf was asked for an address it does not fetch: a private or loopback address, or a redirect leading to one. | Send a public http or https address. | | 403 | robots_disallowed | You asked for followRobots and the site's robots.txt disallows the page. | Fetch a page the site allows, or leave followRobots off for a page you name yourself. | | 403 | playground_not_allowed | The documentation playground tried to reach the MCP surface. | Connect an MCP client with your Quorum account, or use an API key. | | 404 | not_found | No such route. | Check the path against the reference. | | 404 | batch_not_found | The batchId names no loaded batch. Batches expire after six hours. | Upload the documents again. | | 404 | draft_not_found | The draftId names no uploaded draft. | Upload the draft again. | | 404 | job_not_found | The jobId names no review job or extraction. Finished results are kept for a while, and a job belongs to the workspace that started it. | Start the review or the fetch again. | | 410 | inputs_deleted | The draft or the batch was deleted while the review ran. | Upload again and start a new review. | | 413 | batch_too_large | The batch exceeds what the service holds in memory. | Send fewer or smaller documents, or split the batch. | | 413 | draft_too_large | The draft's text is longer than 500,000 characters. | Review it in parts. | | 413 | file_too_large | A draft file over 2 MB, or an evidence file over 25 MB. | Send a smaller file. | | 422 | no_files_parsed | No uploaded file could be parsed. failed says why for each. | Check the formats: PDF, Word, PowerPoint, plain text or Markdown. | | 429 | rate_limited | Over the requests-per-minute limit. | Wait Retry-After. | | 429 | claims_rate_limited | Over the claims-per-minute ceiling. | Wait Retry-After, or send fewer claims at once. | | 429 | claim_budget_exhausted | The day's claims are spent. | Wait for midnight UTC, or raise the key's limit. | | 429 | protocol_rate_limited | Too many MCP protocol messages. | Wait Retry-After. | | 429 | monthly_cap_reached | The month's credit cap is reached. cap and resetsAt say which and when. | Raise the cap on the Billing page, or wait. | | 429 | busy | Kerf's fetching fleet has no room in its queue. | Wait Retry-After; it clears in seconds. | | 429 | too_many_running | No room for another draft review right now. | Wait Retry-After. | | 502 | provider_error | The model provider behind Attest failed. | Retry with backoff. | | 502 | site_refused | The site answered 401, 403, 407, 429 or 451 and would not serve the page. Nothing is charged. | If you hold the document itself, extract the file instead. | | 502 | load_failed | The page could not be loaded. Nothing is charged. | Retry once; check the address opens in a browser. | | 502 | upstream_unavailable | The service behind the route could not be reached. | Retry with backoff. | | 502 | upstream_refused_gateway | A deployment fault between the gateway and the service, never your credential. | Retry later. If it persists, contact support. | | 503 | not_configured | The evaluator is not configured on this deployment. | Contact support. | | 503 | extraction_failed | No part of the draft could be read. | Check the draft's text, or upload it in another format. | | 503 | no_edge_available | No part of Kerf's fetching fleet is answering. | Retry shortly. | | 503 | credits_unavailable | The balance could not be confirmed. | Retry in a moment. | | 503 | ownership_unavailable | Which workspace a review or an extraction belongs to could not be confirmed. | Retry in a moment. | | 503 | review_not_recorded | A review started but could not be recorded against your workspace, so it could never be collected. | Start the review again. | | 503 | (verdict INDETERMINATE) | Attest could not measure the claim. A server-side failure, never a finding. | Retry. Never read it as a verdict. | | 504 | upstream_timeout | The service did not answer in time. | Retry. For a long review, let it answer 202 and poll. | | 500 | internal_error | Something failed on the server. | Retry once, then contact support with the time and route. |

What is safe to retry

Retry 429 (after Retry-After), 502, 503 and 504 with exponential backoff and jitter. Do not retry 400, 401, 402, 403, 404, 410, 413 or 422 without changing the request: they fail the same way every time. Claim checks are idempotent but cost a credit each time they succeed, so wait for an answer rather than sending the same check twice.

Getting help

Every dashboard page has Quincy, the support assistant, in the corner. It can read the documentation, explain a status code from your recent requests, and open a ticket. Include the route, the time, the status and the code when you write in.

Still need help?

Ask Quincy in the chat bubble below, or write to support@quorumtech.ch and we will help you directly.