Skip to content

Error contract

  1. Provider errors — forwarded to you as-is (status code and body unchanged). Your existing provider-specific error handling keeps working.
  2. Gateway errors — returned before the request reaches the provider, with a JSON envelope:
{"error": {"type": "<machine-readable>", "message": "<human-readable>"}}
CodeTypeWhenWhat to do
401unauthorizedKey missing, unknown, or revokedCheck the key and the auth header for this provider
403forbiddenMissing scope, or the model is not entitled to this keyCheck GET /gw/me; ask your admin for access
400bad_requestMalformed request the gateway must reject (e.g. async CREATE without model, invalid limit)Fix the request
404not_foundAsync task does not exist or belongs to another organization; key not found on revoke
429rate_limitedPer-key RPS or concurrency limit exceeded; Retry-After: 1 is setBack off and retry
402budget_exceededOrganization budget exhausted (when enforcement is on)Contact your admin
410goneAsync task can no longer be finalized (upstream credentials rotated)Re-create the job
503unavailableTransient failure finalizing an async taskRetry the poll
502 / 504Provider unreachable / timed out (no JSON envelope)Retry with backoff; consider SDK fallback chains

Every response carries X-Gateway-Request-Id. Quote it in support requests — it pins down the exact request in logs and usage records.

The Python SDK maps this contract onto a typed exception hierarchy (AuthError, RateLimitError, ProviderUnavailableError, …) and implements automatic retries and provider fallback.