Concepts

Errors

One envelope, seven codes, and a requestId on everything — never a stack trace, never HTML. A failed call is never charged.

The envelope

Every error is JSON with a stable code, a human message, and a requestId (also in the x-request-id header) you can quote at us to trace the exact call.

402 Payment Required
{
  "error": {
    "code": "insufficient_credits",
    "message": "This call costs 10 credits; your balance is 3."
  },
  "requestId": "req_9f2c41d0aa8b7e6c5d3f1a2b"
}

Every code

CodeHTTPMeaningWhat to do
unauthorized401Missing, malformed, revoked, or unknown API key.Fix the Authorization header — retrying the same key won't help.
invalid_request400The body failed validation; the message names the exact field.Correct the request and resend.
insufficient_credits402Your balance can't cover this call. Nothing was charged.Top up (or arm auto-recharge), then resend.
unprocessable422Valid request, but the input couldn't be processed (e.g. an unreadable file).Resend with a different input; the same input will fail again.
rate_limited429Per-key rate limit for this endpoint exceeded.Wait Retry-After seconds, then resend.
inference_unavailable503Every model rail for this capability is briefly unavailable.Safe to retry with backoff — the call was never charged.
server_error500Something failed on our side. Never charged.Retry with backoff; quote the requestId if it persists.

Retry discipline

rate_limited carries Retry-After — honor it. inference_unavailable and server_error are safe to retry with exponential backoff, because a failed call is never billed. The 4xx codes are yours to fix — retrying the same request reproduces the same error.