Errors
Topo uses standard HTTP status codes and returns errors in the OpenAI shape, with a stable type to branch on and a request ID for support.
Error shape
error.json
json
{ "error": { "type": "insufficient_balance", "message": "Wallet balance 0.0021 USDT is below the estimated cost 0.0041 USDT.", "param": null, "request_id": "req_7Hq2kf91" }}Error codes
| Status | Type | What happened | Retry |
|---|---|---|---|
| 400 | invalid_request | The body is malformed or a parameter is out of range. | No |
| 401 | invalid_api_key | The key is missing, revoked or mistyped. | No |
| 402 | insufficient_balance | The wallet cannot cover the estimated cost. Top up or lower max_tokens. | After top-up |
| 402 | spend_limit_reached | The key or agent wallet hit its spend limit. | No |
| 403 | key_scope_violation | The model, region or IP is outside the key's scope. | No |
| 404 | model_not_found | No model with that ID, or it is not enabled on your plan. | No |
| 409 | idempotency_conflict | An Idempotency-Key was reused with a different body. | No |
| 429 | rate_limited | Too many requests or tokens per minute. Wait for retry-after. | Yes |
| 500 | internal_error | Unexpected error in the router. | Yes |
| 502 | node_unavailable | The node dropped mid-request. Topo already retried once on another node. | Yes |
| 503 | capacity_exhausted | No healthy capacity for the model. Add a topo.fallback. | Yes |
| 504 | node_timeout | No first token arrived in time. | Yes |
Retries
Retry 429 and 5xx responses with exponential backoff and jitter, and send the same Idempotency-Key on every attempt. A request is settled at most once per key, even when several attempts reach a node.
import osimport uuidfrom openai import OpenAI client = OpenAI( base_url="https://api.topolabs.ai/v1", api_key=os.environ["TOPO_API_KEY"], max_retries=4, # backoff with jitter on 429 and 5xx) response = client.chat.completions.create( model="claude-sonnet-5.5", messages=[{"role": "user", "content": "Summarize this ticket"}], extra_headers={"Idempotency-Key": str(uuid.uuid4())},)import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.topolabs.ai/v1", apiKey: process.env.TOPO_API_KEY, maxRetries: 4, // backoff with jitter on 429 and 5xx}); const response = await client.chat.completions.create( { model: "claude-sonnet-5.5", messages: [{ role: "user", content: "Summarize this ticket" }] }, { headers: { "Idempotency-Key": crypto.randomUUID() } },);