Error format
Inference APIs return errors in the OpenAI format. /v1/messages can use the Anthropic format (type: "error").
{
"error": {
"message": "Incorrect API key provided. ...",
"type": "authentication_error",
"param": null,
"code": "invalid_api_key"
}
}Branch on error.code; message wording can change. param names the field that caused the error.
Errors after a stream starts arrive as stream events. See streaming. The event's error.code is the same as in the table below (for example provider_unavailable or upstream_timeout). Stream events carry no Retry-After, so wait a few seconds before resending.
What to do for each status
| Status | type / code | Cause | Retry? |
|---|---|---|---|
| 400 | invalid_request_error / unsupported_parameter · unsupported_value · image_input_unsupported · context_length_exceeded | Invalid parameter, context too long, or an option or image input the model doesn't support | No. Fix the request |
| 401 | authentication_error / missing_api_key · invalid_api_key | Missing, invalid or expired key | No |
| 402 | insufficient_quota_error / insufficient_quota · spend_limit_exceeded | Not enough credit, or the key's spend limit | After adding credit or raising the limit |
| 403 | permission_error / model_not_allowed · insufficient_scope | Model or scope not allowed for this key | No |
| 404 | invalid_request_error / model_not_found · job_not_found | Wrong model ID, model blocked by your settings, or expired job | No |
| 409 | idempotency_* | Idempotency-Key collision. See below | Depends |
| 413 | invalid_request_error / request_too_large | Body over the size limit | After making it smaller |
| 429 | rate_limit_error / rate_limit_exceeded | Per-minute request limit exceeded | Yes, after Retry-After |
| 502 | api_error / backend_unavailable · upstream_error | The model provider returned an error | Yes, with backoff |
| 503 | api_error / model_warming | The model is starting | Yes, after Retry-After |
| 503 | api_error / provider_unavailable | Every route for this model is briefly blocked. Your request was not run | Yes, after Retry-After (30 s at most) |
| 504 | api_error / upstream_timeout | The model provider did not respond in time | Yes, with backoff |
When a provider rejects the request, the 400 carries the provider's field and code in param and code (for example param: "reasoning_effort", code: "unsupported_value"). The field is renamed to the API you called: a Chat Completions request gets messages, not the provider wire's input. The provider's own message text is not included.
For 404 model_not_found on an ID that looks right, check the key's allowed models and your access settings.
409: when an Idempotency-Key collides
| code | Meaning | What to do |
|---|---|---|
idempotency_in_progress | The same request is still running | Wait. Don't resend with a new key |
idempotency_key_reused | A different body was sent with the same key | Use a new key per distinct request |
idempotency_response_not_replayable | It already ran, but a stream or large result can't be replayed | Check the output and your usage |
503 model_warming
The model is starting. Your request was not run. Retry after Retry-After seconds. Some models take 10–20 minutes to start.
Rate limits
Each key allows 100 requests per minute by default; change it when you create or edit the key. Login, sign-up and other auth endpoints have a lower limit.
| Header | Meaning |
|---|---|
X-RateLimit-Limit | The key's per-minute limit |
X-RateLimit-Remaining | Requests left in the window |
X-RateLimit-Reset | Reset time (Unix milliseconds) |
Retry-After | Seconds to wait before retrying a 429 or 503 |
Retry code
The OpenAI SDK retries 429 and 5xx twice with short waits. A 503 model_warming can last minutes, so retry yourself.
import os
import random
import time
from openai import APIStatusError, OpenAI
client = OpenAI(
base_url="https://api.everyais.com/v1",
api_key=os.environ["EVERYAIS_API_KEY"],
max_retries=0, # we retry below
)
RETRYABLE = {429, 502, 503, 504}
def create_with_retry(attempts=5, **request):
for attempt in range(attempts):
try:
return client.chat.completions.create(**request)
except APIStatusError as error:
if error.status_code not in RETRYABLE or attempt == attempts - 1:
raise
wait = float(error.response.headers.get("retry-after") or 2 ** attempt)
time.sleep(wait + random.random())- Send an
Idempotency-Keywith automatic retries so a request doesn't run twice. See compatibility features. - Video submission doesn't support
Idempotency-Key. If you lose the submit response, check the job status before resubmitting.
Contacting support
Include the x-request-id response header, the HTTP status and error.code.