Errors & retries
All errors return a JSON body in the same shape:
{
"error": {
"message": "This model is temporarily unavailable: its backend is down or being updated. Retry after the Retry-After delay.",
"type": "service_unavailable",
"code": "model_unavailable"
},
"docs": "https://appelon.ai/docs/errors"
}
Branch on error.code in your client, not on the message text. Messages may change; codes are stable.
Error codes
| HTTP | error.code |
Meaning | Retry? |
|---|---|---|---|
400 |
invalid_request |
Malformed request or unknown model name. Check GET /v1/models. |
No |
401 |
auth_error |
Missing, invalid, or revoked API key. | No |
402 |
quota_error |
Monthly quota or trial credits exhausted. | No |
403 |
license_error |
License canceled, past due, or archived. | No |
503 |
model_unavailable |
The model’s backend is down, restarting, or loading a model update. | Yes, after Retry-After |
503 |
capacity_error |
All GPU capacity is in use and the queue wait timed out. | Yes, after Retry-After |
502 |
upstream_error |
The backend accepted the request but failed while processing it. | Yes, with backoff |
500 |
server_error |
Unexpected error in the gateway. | Yes, with backoff |
Model updates and maintenance
When we roll out a model update, its backend is briefly unavailable while the new
weights load (typically a few minutes). During that window requests fail fast with
503 and error.code: "model_unavailable", plus a Retry-After header (in
seconds). Your request is not lost or half-processed: it never reached the model,
so it is always safe to retry.
A simple retry loop:
import time
import requests
def chat(payload, headers, max_attempts=5):
for attempt in range(max_attempts):
resp = requests.post(
"https://router.appelon.ai/v1/chat/completions",
json=payload, headers=headers,
)
if resp.status_code != 503:
return resp
wait = int(resp.headers.get("Retry-After", 30))
time.sleep(wait)
return resp
Most OpenAI-compatible SDKs already retry 503 responses automatically; if you
use the official OpenAI client with max_retries set, no extra handling is
needed.
Busy periods
capacity_error means all GPU slots were taken for longer than the queue wait
window. Retrying after the Retry-After delay usually succeeds. Streaming chat
requests are queued instead: while you wait for a slot you receive valid
chat.completion.chunk events with an extra queue field describing your
queue status, followed by the normal response stream.