Error codes
Every error returns the same envelope: an HTTP status, a stable machine code, and a human message. Branch on error.code, not the message text.
{
"error": {
"code": "invalid_api_key",
"message": "The API key provided is invalid or has been revoked."
}
}The seven codes you'll meet
Bad Request
What it means — The request was malformed or a parameter failed validation — a wrong date format, an out-of-range latitude, an unknown spread name.
How to handle it — Read the detail field: it names the offending parameter and the expected shape. Validate client-side before retrying.
Example body
{
"error": {
"code": "validation_error",
"message": "latitude must be between -90 and 90",
"param": "latitude"
}
}Unauthorized
What it means — The X-API-Key header is missing, malformed, or the key was revoked. The request never reached the engine.
How to handle it — Check the header spelling (X-API-Key), confirm the key is active in Dashboard → API Keys, and rotate if it may have leaked.
Example body
{
"error": {
"code": "invalid_api_key",
"message": "The API key provided is invalid or has been revoked."
}
}Payment Required
What it means — Your key is valid but the credit balance can't cover this call. Nothing was computed and nothing was charged.
How to handle it — Top up from Dashboard → Billing, then retry. Credits never expire and failed calls never deduct.
Example body
{
"error": {
"code": "insufficient_credits",
"message": "This call needs 1 credit but your balance is 0.",
"credits_needed": 1,
"credits_balance": 0
}
}Not Found
What it means — The path doesn't exist — a typo'd endpoint, or a resource id (like a reading_id) that isn't yours or never existed.
How to handle it — Double-check the path against the reference. For resource ids, confirm the id came from a successful call with the same key.
Example body
{
"error": {
"code": "not_found",
"message": "No reading found with id 9f2a1c4e-…"
}
}Too Many Requests
What it means — You exceeded 60 requests per minute on this key. The Retry-After header tells you exactly how long to wait.
How to handle it — Back off for Retry-After seconds, then retry. Add client-side pacing or request batching if you hit this often.
Example body
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Retry in 12 seconds.",
"retry_after_seconds": 12
}
}Internal Server Error
What it means — Something broke on our side after your request passed validation. These are rare and always logged with a request id.
How to handle it — Retry with exponential backoff. If it persists, send us the x-request-id response header and we'll investigate.
Example body
{
"error": {
"code": "internal_error",
"message": "An unexpected error occurred.",
"request_id": "req_8f3ka2m9"
}
}Service Unavailable
What it means — A backing engine or model isn't ready yet — for example, interpretation content still loading after a deploy.
How to handle it — Treat like a 500: back off and retry. Deterministic computation endpoints are unaffected.
Example body
{
"error": {
"code": "engine_unavailable",
"message": "The interpretation engine is warming up. Please retry shortly."
}
}