Errors & retries
Errors are returned as JSON with a stable machine-readable error code and the matching HTTP status.
{ "error": "rate_limited", "message": "Too many requests.", "retry_after_ms": 850}Error codes
Section titled “Error codes”| HTTP | error | Retry? | Notes |
|---|---|---|---|
| 400 | invalid_request | No | A parameter failed validation — fix the request. |
| 401 | missing_api_key / unknown_api_key | No | See Authentication. |
| 403 | inactive_api_key / account_blocked | No | Key disabled or account suspended. |
| 402 | insufficient_credits | No | Top up. Body includes required and balance. |
| 429 | rate_limited | Yes, after retry_after_ms | You exceeded your per-minute limit. |
| 409 | request_in_progress | Yes | An identical idempotent request is still running. |
| 422 | (idempotency conflict) | No | An Idempotency-Key was reused with a different body. |
| 503 | service_temporarily_unavailable / too_many_concurrent_requests | Yes, with backoff | Transient capacity limit. |
| 504 | result_timeout | Yes | The upstream fetch exceeded deadline_ms. |
Retry guidance
Section titled “Retry guidance”- Retry 429 / 503 / 504 / 409 with exponential backoff. When
retry_after_msis present, wait at least that long before retrying. - Never retry 400 / 401 / 402 / 403 — the request won’t succeed until you change it.
- The official SDKs already retry transient errors for you (default 2 retries) and expose a
retryableflag on the error.