API
Errors
Every status and message the API returns, and which errors are passed through from the model provider unchanged.
The shape of an error
Errors raised by the AlphaNeural API itself have one shape:
{"error": {"message": "insufficient balance: add funds to continue"}}Errors from the model provider or the gateway are passed through unchanged: the same status and the same body the gateway returned, usually the OpenAI shape with message, type, param and code. They are never rewritten, so "out of credit at the provider", "rate limited" and "model is down" stay distinguishable.
Chat completions
POST /v1/chat/completions, in the order the checks run:
| Status | Message | Cause |
|---|---|---|
401 | missing API key | No Authorization header. |
400 | could not read request body | The body could not be read. |
400 | invalid JSON body | The body is not JSON, or a field has the wrong type. |
400 | model is required | No model. |
400 | stream cannot be combined with escalation: the output must be complete before it can be verified | Both stream and escalation.ladder were sent. alphaneural/auto accepts stream. |
503 | alphaneural/auto is not available on this server | The operator has switched routing off. Name a model instead. |
400 | alphaneural/auto builds its own ladder: ... | escalation.ladder was sent with alphaneural/auto. |
400 | escalation.max_rungs must be between 1 and 5 | |
400 | max_spend must be a positive amount in USD: ... | alphaneural/auto was sent max_spend of 0 or less. Omit it for the default. |
401 | unknown or inactive API key | The key does not exist, is inactive, or is not an API key. |
500 | could not verify API key | A fault on our side. Nothing was recorded; send the same request again. |
402 | insufficient balance: add funds to continue | Your balance is zero, and the model is not one of your own deployments. See Billing. |
500 | could not verify balance | A fault on our side. Nothing was recorded; send the same request again. |
404 | thread not found | The thread id belongs to another account, or the thread store could not be reached while loading or creating the thread (a request that sent no id gets this too). Retry once before treating the thread as gone. |
400 | unrecognised message content | A message's content is neither a string nor an array of parts. |
500 | could not record the message | A message could not be saved. Earlier messages in the same request may have been. |
500 | could not read the thread | alphaneural/auto only: the thread could not be loaded to plan the ladder. |
503 | the model catalogue is unavailable, so alphaneural/auto cannot choose a model; retry, or name a model | |
502 | could not list the models this key may call | alphaneural/auto only: the gateway did not answer which models the key may call. |
400 | escalation.ladder must contain at least one model | escalation was sent with an empty ladder. |
500 | could not build the upstream request, could not run the ladder | A fault on our side, after your messages were recorded. |
502 | could not reach the model | The gateway could not be reached. |
422 | type: ladder_exhausted, code: budget, rejected, upstream_errors or no_candidates | With escalation or alphaneural/auto: no answer was accepted. The body also carries the escalation object. See Routing. |
| provider's | provider's | The model call failed at the gateway or the provider. Passed through unchanged. |
Everything before 404 thread not found in this table leaves your threads untouched. From unrecognised message content onwards, messages you sent may already be in the thread; to retry without duplicating them, see Threads and memory. Two 500s happen before anything is recorded and are safe to send again unchanged: could not verify API key and could not verify balance.
A role other than system, user, assistant or tool cannot be stored, and fails with 500 could not record the message.
A 200 from a routed request always carries an accepted answer: escalation.accepted is never false on a 200. The only routing failure is the 422.
Threads
GET /v1/threads and GET /v1/threads/{thread_id}:
| Status | Message | Cause |
|---|---|---|
401 | missing API key, unknown or inactive API key | As above. |
400 | limit must be a non-negative integer | limit is negative or not a number. |
404 | thread not found | The id does not exist or is not yours. |
500 | could not verify API key, could not list threads, could not load thread | A fault on our side. |
Models
GET /v1/models:
| Status | Message | Cause |
|---|---|---|
401 | missing API key, unknown or inactive API key | As above. |
404 | model listing is not enabled | Listing is switched off on the server. |
401, 400, 429 | the gateway's, with a type of authentication_error, invalid_request_error or rate_limit_error | The gateway refused the key: unknown or blocked there, over its own budget, or rate limited. The same key gets the same answer from a chat completion. |
502 | could not load the model list | The gateway did not answer. |
Cost traces
GET /v1/tasks and GET /v1/tasks/{task_id}/trace:
| Status | Message | Cause |
|---|---|---|
401 | missing API key, unknown or inactive API key | As above. |
404 | cost tracing is not enabled | Tracing is switched off on the server. |
400 | limit must be a non-negative integer | limit is negative or not a number. |
400 | cursor is not valid: pass next_cursor from the previous page unchanged | The cursor was not one the list issued. |
500 | could not list tasks | A fault on our side. |
A task with no recorded usage is not an error: it returns 200 with a note. See Cost traces.
What to do about it
| Status | Do |
|---|---|
400 | Fix the request. Retrying unchanged gets the same answer. |
404 | Fix the request, unless it is thread not found for a thread you know is yours: that can be the thread store failing, so retry once. |
422 | The ladder was exhausted. Read error.code and escalation: raise max_spend, change the ladder, or fix the schema, then retry with the same thread id and an empty messages array. See Routing. |
401 | Check the key on the API Keys page. |
402 | Add funds, then send the same request again. Nothing was recorded. |
429 | Rate limited by the gateway or the provider. Retry with exponential backoff. |
500, 502, 503 | Retry with backoff. |
When a threaded request fails at the model call, with 502 could not reach the model, a 422 from routing, or an error passed through from the gateway or provider (a 429 included), your message is already in the thread. Retry with the same thread id and an empty messages array, so it is not added twice. After 500 could not record the message, could not build the upstream request or could not run the ladder you cannot tell from the status alone which of your messages were recorded: read the thread and check its last turns before you retry. Only could not verify API key and could not verify balance are safe to resend unchanged.