Getting started
Errors
Error envelope, status codes, and retry guidance.
Errors return JSON with a detail message; some carry an additional machine
code:
{
"detail": "rate limited",
"code": "rate_limited"
}Validation failures (422) use a structured detail array instead, with the
offending location and message per field:
{
"detail": [
{
"loc": ["body", "items"],
"msg": "Field required",
"type": "missing"
}
]
}Status codes
| Status | Meaning | Retry? |
|---|---|---|
400 | Malformed request. | No — fix the request. |
401 | Missing or invalid API key. | No — check the key. |
402 | Monthly quota exhausted. | No — upgrade or wait for the cycle reset. |
403 | Authenticated but not permitted. | No. |
404 | Not found — including namespaces outside your key's scope. | No. |
405 | Wrong HTTP method for the path. | No. |
409 | Conflict — e.g. retrying an operation that is not dead-lettered. | No — check state first. |
410 | Resource gone. | No. |
413 | Upload too large. | No — reduce the file size. |
422 | Body failed validation. | No — fix the fields in detail. |
429 | Rate limited. | Yes — honor Retry-After. |
503 | Overloaded; request shed. | Yes — retry with backoff. |
Retry guidance
Only 429 and 503 are retryable, and both include a Retry-After header.
Use exponential backoff with jitter and cap total attempts. Retain is
idempotent per content batch — a duplicate in-flight retain collapses onto
the existing operation — so retrying a timed-out retain is safe.
Asynchronous failures
Retain processes asynchronously. A 200 from retain means the work was
accepted; extraction failures surface on the
operations API. A retain that exhausts its
retries dead-letters: list failed work with state=failed, read the terminal
error on the status route, and re-run it with the
retry endpoint.