Appearance
Error Codes
All errors follow a consistent shape:
json
{ "error": "ERROR_CODE", "message": "Human readable description" }Error Reference
| HTTP | Code | When |
|---|---|---|
400 | VALIDATION_ERROR | Missing/invalid params, unknown model, amount too low, thinking/reasoning_effort not allowed |
401 | UNAUTHORIZED | Missing/invalid API key or SIWE signature |
402 | INSUFFICIENT_BALANCE | Not enough credit for the estimated cost |
404 | NOT_FOUND | Resource not found |
429 | RATE_LIMITED | Per-wallet rate limit exceeded |
500 | INTERNAL_ERROR | Server error |
502 | UPSTREAM_ERROR | LLM provider failed or timed out |
Detailed Examples
Insufficient Balance (402)
Returned when balance can't cover the pessimistic cost estimate. Includes current balance and required amount.
json
{
"error": "INSUFFICIENT_BALANCE",
"message": "Insufficient balance. Top up at /v1/topup.",
"balance_usdc": 1000,
"required_usdc": 5000
}Rate Limited (429)
Returned when per-wallet sliding window limits are exceeded.
json
{
"error": "RATE_LIMITED",
"message": "Rate limit exceeded",
"retry_after_ms": 15000
}Validation Error (400)
json
{
"error": "VALIDATION_ERROR",
"message": "Thinking/reasoning models are not supported"
}Upstream Error (502)
Returned when the LLM provider fails. Balance lock is released (no charge).
json
{
"error": "UPSTREAM_ERROR",
"message": "Provider returned an error"
}Error Handling Behavior
| Scenario | Behavior |
|---|---|
| Insufficient balance | HTTP 402 with top-up instructions and current balance |
| Provider down | Release lock, return 502, no balance deducted |
| Invalid model | Return 400, release lock, no balance deducted |
| Rate limited | Return 429 with retry_after_ms, no balance deducted |
| Invalid API key | Return 401 |
| Expired/invalid SIWE | Return 401 |
| Top-up below minimum | Return 400 before issuing 402 |