Error response format#
{
"error": {
"code": "INVALID_API_KEY",
"message": "API key not found or has been revoked."
}
}Status codes#
| HTTP | Code | Description |
|---|---|---|
| 401 | MISSING_API_KEY | Missing bearer header. |
| 401 | INVALID_API_KEY | Invalid, expired, or revoked key. |
| 400 | API_KEY_ERROR | Other API-key validation failure. |
| 403 | INSUFFICIENT_SCOPE | Key scope does not allow the route. |
| 403 | INSUFFICIENT_TIER | No prepaid credit or Developer plan to draw on. |
| 429 | RATE_LIMITED | The room's one request at a time, or the key's or room's limit, exceeded. |
| 503 | RATE_LIMIT_UNAVAILABLE | The local rate limiter could not be queried. |
| 400 | EMPTY_PROMPT | Prompt missing. |
| 400 | PROMPT_TOO_LARGE | Prompt exceeds 100,000 bytes. |
| 400 | INVALID_MODEL | Unknown level. |
| 400 | MODEL_UNAVAILABLE | The level is not available in this room at present. |
| 400 | INVALID_REQUEST | Malformed request rejected by the inference gateway. |
| 402 | BUDGET_EXCEEDED | The room's spend limit, or your credit, would be exceeded by the request. |
| 404 | NOT_FOUND | Requested upstream object was not found. |
| 404 | SOURCES_NOT_FOUND | No live sources retained for that request ID. |
| 413 | PAYLOAD_TOO_LARGE | Upstream payload exceeded the accepted size limit. |
| 422 | SAFETY_BLOCKED | Gateway safety pre-screen blocked the request. |
| 429 | INFERENCE_RATE_LIMITED | Upstream inference service throttled the request. |
| 503 | EVA_UNAVAILABLE | Inference service unavailable. |
| 401 | INFERENCE_UNAUTHORIZED | Gateway credentials were rejected upstream. |
| 503 | INFERENCE_BUSY | Inference backend reported temporary saturation. |
| 500 | DB_ERROR | Usage or billing query failed. |
| 500 | SERVER_MISCONFIGURED | API key verification is not configured correctly. |
| 502 | INFERENCE_ERROR | Gateway or upstream dispatch failure. |
| 503 | DB_UNAVAILABLE | Required database services are unavailable. |
Retry guidance#
429: rate limited
When request limits are exceeded, the API returns retry-after: 60, x-ratelimit-limit, and x-ratelimit-remaining: 0. Respect those headers instead of retrying immediately.
400/402: contract or budget errors
Do not retry unchanged requests that fail with validation, model-selection, or budget-cap errors. Fix the payload, switch model, lower max_output_rungs, or adjust the project budget first.
500/502/503: service errors
Retry with bounded exponential backoff. If the failure persists, stop retrying and inspect upstream availability, database health, workspace budget state, and current platform status.
Example error handling (Python)#
import requests
import time
def call_eva(prompt, retries=3):
for attempt in range(retries):
response = requests.post(
"https://evaesi.dev/api/v1/responses",
headers={"Authorization": "Bearer esi_dev_YOUR_KEY"},
json={"prompt": prompt, "level": "focus"},
)
if response.status_code == 200:
return response.json()
if response.status_code == 429:
wait = int(response.headers.get("retry-after", 60))
time.sleep(wait)
continue
if response.status_code >= 500:
time.sleep(2 ** attempt)
continue
error = response.json()
raise Exception(f"{response.status_code}: {error['error']['message']}")
raise Exception("Max retries exceeded")