API reference
Errors
Error shapes#
The OpenAI-compatible endpoints put the code in both error.code and error.type; the Anthropic-compatible ones use Anthropic's error.type. The HTTP status is the same either way.
{ "error": { "message": "The model `gpt-4o` does not exist or is not available.", "type": "model_not_found", "code": "model_not_found", "request_id": "req_64c97dcaee881c19a0187fae" }}Request IDs#
Every response from /v1, successful or not, carries an x-request-id header like req_b7fc216b3c39b963328f4ff1. Error bodies repeat it as request_id: inside error on the OpenAI-compatible endpoints, at the top level on the Anthropic-compatible ones (where Anthropic puts its own). The same ID shows when you open the call's row in Logs.
Log it with your errors, and include it when contacting support: it finds the exact call. The SDKs' errors keep the response headers, so it's there in Python as error.response.headers["x-request-id"].
Error codes#
| Status | Code (OpenAI) | Type (Anthropic) | What happened | What to do | Retry |
|---|---|---|---|---|---|
| 400 | invalid_request_error | invalid_request_error | The body is malformed, or the model rejected a field. The message says which. | Fix the request; the same request fails the same way. | No |
| 400 | invalid_model_kind | invalid_request_error | The model is another kind than the endpoint serves: an embedding model at chat completions, say. | Call chat models at /v1/chat/completions or /v1/messages, embedding models at /v1/embeddings and rerankers at /v1/rerank. | No |
| 401 | invalid_api_key | authentication_error | No key, an unknown key, or a revoked one. | Check the header and the key on the API keys page. | No |
| 401 | key_expired | authentication_error | The key passed its expiry date. | Create a new key and switch your app over. | No |
| 401 | project_archived | authentication_error | The key's project was archived, which revoked its keys. | Create a key in another project. | No |
| 402 | insufficient_quota | billing_error | Your prepaid balance is empty and this month's plan allowance is used up. | Add credit, turn on auto top-up, or upgrade your plan. | Later |
| 403 | account_suspended | permission_error | The account is suspended. | Email support. | No |
| 403 | model_not_allowed | permission_error | The key is locked to other models. | Use an allowed model, or change the key's model list. | No |
| 403 | ip_not_allowed | permission_error | The key only accepts certain IP addresses, and this wasn't one. | Call from an allowed address, or add this one to the key. | No |
| 404 | model_not_found | not_found_error | No live model has that ID (or it was retired). | Check the ID against GET /v1/models. | No |
| 429 | rate_limit_exceeded | rate_limit_error | Too many requests this minute for the key on this model, or for the account. | Wait for retry-after, then retry with backoff. | Yes |
| 429 | key_limit_reached | rate_limit_error | The key hit its monthly spend cap. | Raise the cap on the API keys page, or wait for the new month. | Later |
| 429 | project_budget_reached | rate_limit_error | The key's project hit its monthly budget. | Raise it under Developers → API projects, or wait for the new month. | Later |
| 502 | upstream_error | api_error | The model's host failed or couldn't be reached. You aren't charged. | Retry after a moment. | Yes |
| 503 | overloaded | overloaded_error | The model is at capacity right now. You aren't charged. | Retry with exponential backoff. | Yes |
| 504 | upstream_timeout | api_error | The model didn't start answering within 60 seconds. | Retry; if it keeps happening, try another model. | Yes |
Refused calls (anything before the model runs) are never charged. Messages are written for people and may change; branch on the status and code, not the text.
Which errors to retry#
- Retry with backoff:
429 rate_limit_exceeded(afterretry-after),502,503and504. The OpenAI and Anthropic SDKs already do this (twice by default). A backoff example is on Rate limits. - Retry after a change:
402,key_limit_reachedandproject_budget_reachedclear when credit is added, a cap is raised, or the month (UTC) turns. - Don't retry:
400,401,403and404fail the same way until the request or the key changes.
Before you ever see a 502 or 503, FullsendAI has already retried a busy model once and, for models with a backup host, moved the call there at the same price (see Automatic failover). Live and past uptime per model is on the status page.
Errors during a stream#
An error before the first token is an ordinary JSON error with its status. Once a stream has started the status is already 200, so if the model goes quiet for 60 seconds the stream ends with an error event instead, and you're charged only for what was sent:
data: {"error":{"message":"The model stopped answering for 60 seconds, so the answer was cut off.","type":"upstream_timeout","code":"upstream_timeout"}}Finding failed calls#
Every call, refused ones included, is listed in Logs with its status, code, message, key, model and the calling app and IP address. A stream you stopped yourself shows as Stopped (status 499), charged only for what was generated. Open a call to see its request ID, with a button to copy it. Turn on body logging for a project to see the exact request and reply (how).
Stuck? Email [email protected]System statusChangelog