API errors and rate limits
How errors look, what each code means, how to respond, and how fast one key can go.
Failures arrive as ordinary JSON, and OpenAI SDKs map them to the classes you know (APIError, AuthenticationError, RateLimitError and so on).
{ "error": { "code": "spend_limit_reached", "message": "This API key reached its monthly spend limit", "monthlyLimitMicro": 5000000, "spentThisPeriodMicro": 5000000, "periodResetsAt": "2026-11-01T00:00:00.000Z" } }
Write your logic against error.code and leave the message text alone. Fields ending in Micro count micro-USD: $1 is 1,000,000.
Every code comes with a next move
| HTTP | Code | Your next move |
|---|---|---|
| 400 | invalid_request | Correct the field named in message |
| 400 | upstream_rejected | The model refused your input, for example because it overflows the context window |
| 401 | invalid_api_key | Bad or revoked key. Make a fresh one |
| 402 | insufficient_credits | Your free and paid credits together fall short. Cut max_tokens, switch model or top up. resetsAt gives the free refill time |
| 402 | spend_limit_reached | Monthly cap reached. Lift it on the Developers page or wait until periodResetsAt |
| 403 | tee_api_not_available | TEE lives in the app. Send mode: "anonymous" |
| 404 | model_not_found | No such model id. Look it up with GET /v1/models |
| 404 | model_unavailable | No answer possible at this moment, and no charge. Switch model or set fallback_models |
| 404 | not_found | That video job or media link is unknown or has expired |
| 409 | request_in_progress | An image call with this X-Angerona-Request-Id hasn't finished. Poll GET /media/by-request/{id} |
| 413 | payload_too_large | Your body exceeds 4 MB |
| 422 | content_blocked | The safety check turned down this image or video prompt |
| 429 | rate_limited | Ease off and honor Retry-After |
| 502 | upstream_error | Provider failure with no charge. Send it again |
| 503 | upstream_unavailable, upstream_rate_limited | A passing problem with no charge. Back off and resend |
| 503 | moderation_unavailable | Image and video screening is offline. Try again in a moment |
| 503 | media_unavailable | Storing the image for delivery failed, with no charge. Send it again |
| 500 | internal_error | A bug on our side. Resend, and let us know if it keeps happening |
A key gets 120 requests per minute
- All keys share this same per-key ceiling.
- Cross it and you get
429 rate_limited, withRetry-Afterin seconds. - OpenAI SDKs resend
429and5xxby themselves, two times unless told otherwise.
Failed calls are free
- Nothing is billed for a call that fails.
- When a stream dies midway, only the prompt and the generated part are billed.
- Resending carries no risk: each retry counts as its own request with its own bill.