Errors
All errors come back as a structured JSON envelope with a stable
machine-readable code, a human message, an
optional details object, and a request_id you
can include in a support email.
Envelope
{
"error": {
"code": "rate_limited",
"message": "Too many requests",
"details": { "retry_after_ms": 1850, "limit_rps": 10 },
"request_id": "9fee35c719fa0380-BEG"
}
} Codes
Code Status Meaning
-
validation_failed400 Request shape doesn't match the schema (missing query, bad enum, etc.). `details.issues` lists the failures. -
unauthorized401 Missing, invalid, or revoked API key. -
payment_required402 Project's subscription cycle has expired. Renew in the dashboard. -
forbidden403 Key not authorised for the required scope. -
origin_not_allowed403 Browser Origin header isn't in the key's allowlist. -
suspended403 Project is suspended (billing dispute, ToS, etc.). -
not_found404 Token / resource doesn't exist or we haven't indexed it yet. -
rate_limited429 Hit your per-key requests-per-minute cap. `details.retry_after_ms` says when to retry. -
quota_exhausted429 Hit your monthly credit limit on a hard-capped plan. Upgrade or wait for cycle reset. -
internal_error500 Something on our side broke. `request_id` is logged — include it if you contact support.
Retry guidance
- 429 rate_limited — back off using
details.retry_after_ms. Use jittered exponential backoff if you're hammering. - 429 quota_exhausted — do not retry; raise your plan or wait for next cycle.
- 5xx — retry up to 3 times with backoff. Past that, alert and surface to the user.
- 4xx (other) — fix the request; retrying won't help.