Errors & limits
Errors use the OpenAI shape, so the official SDKs classify and retry them correctly with no configuration.
{
"error": {
"message": "Insufficient credits. Your balance is $0.00. Top up at ...",
"type": "insufficient_quota",
"param": null,
"code": "insufficient_credits",
"request_id": "isr_01KYGHW7S1GTR2AVE40C"
}
}The request_id is an addition — the SDKs ignore unknown fields. Quoting it lets us trace a failure end to end without needing your prompt, which we don’t have.
Status codes
| Status | Type | Meaning | Retry? |
|---|---|---|---|
| 400 | invalid_request_error | The request is malformed or a parameter is invalid. | No |
| 401 | authentication_error | The key is missing, wrong, revoked or expired. | No |
| 402 | insufficient_quota | Out of credit. Top up to continue. | No |
| 403 | permission_error | Account suspended, or the key is restricted. | No |
| 404 | not_found_error | No such model, or you cannot access it. | No |
| 413 | invalid_request_error | The prompt exceeds the model context limit. | No |
| 429 | rate_limit_error | Rate limit exceeded. Respect retry-after. | Yes |
| 500 | api_error | An internal error. Quote the request id. | Yes |
| 502 | api_error | An upstream model server failed. | Yes |
| 503 | overloaded_error | No healthy capacity for that model right now. | Yes |
| 504 | api_error | The upstream did not respond in time. | Yes |
Rate limits
Every response carries your current budget:
x-ratelimit-limit-requests: 200
x-ratelimit-remaining-requests: 199
x-ratelimit-reset-requests: 42s
x-ratelimit-limit-tokens: 400000
x-ratelimit-remaining-tokens: 399987
x-ratelimit-reset-tokens: 42sThree limits apply independently:
- Requests per minute. A fixed window.
- Tokens per minute. Charged optimistically against your
max_tokensat the start of a request, then corrected to the real count once it finishes — so under-using your limit doesn’t throttle you for tokens you never consumed. - Concurrent requests. The one that matters most for inference: a single request can hold a GPU slot for minutes, so opening a hundred streams starves everyone regardless of how few requests per minute that is.
Mid-stream failures
A stream that has already started cannot be re-routed — doing so would splice two different generations together. If an upstream dies mid-generation, you receive an SSE frame containing an error object and the stream ends without a [DONE] marker.
You are billed for the tokens that were actually produced, and the request appears in your activity log with the failure recorded. Handle it by checking for an error key on each frame — the OpenAI SDKs surface these as an exception mid-iteration.
Cancellation
Closing the connection aborts generation immediately, freeing the GPU. You are billed for what was produced up to that point — no more — and the request is logged as cancelled with status 499 so it doesn’t inflate your error rate.