Errors and limits
Every error has the same body:
{"error": {"code": "insufficient_balance", "message": "Your Ward balance does not cover this call. Top up to continue.",
"request_id": "a1b2c3d4", "details": {"cost_usd": 0.0021, "balance_usd": 0.0}}}
Branch on code; show message; include request_id when you contact support.
| Status | code |
Meaning | Retry? |
|---|---|---|---|
| 401 | INVALID_API_KEY, API_KEY_REVOKED, API_KEY_EXPIRED |
Key missing, wrong or revoked | No |
| 402 | insufficient_balance |
Balance does not cover the call; nothing ran | After top-up |
| 403 | account_suspended, FORBIDDEN |
Account suspended, or the key lacks the scope | No |
| 404 | NOT_FOUND |
Unknown id, or the capability is not enabled for your account | No |
| 409 | idempotency_key_reused, in_progress |
Same key with a different body; first call still running | in_progress: yes |
| 413 | call_too_large, window_full |
Over the per-call token cap; session window full | Split / new session_id |
| 422 | VALIDATION_ERROR |
Invalid body; details.errors[] lists each field and message |
No |
| 422 | unknown_model, needs_mapping, async_not_enabled, file codes |
See the capability page | After fixing |
| 429 | RATE_LIMITED |
Too many requests; honour Retry-After |
Yes |
| 500, 502, 503 | INTERNAL_ERROR, SERVICE_UNAVAILABLE |
Ward or a dependency failed | Yes, with backoff and the same Idempotency-Key |
Limits
| Limit | Value |
|---|---|
| Requests per key | 500 per minute (X-RateLimit-Limit, Retry-After on 429) |
Real-time call (payment, intent, agent, screen) |
32,000 input tokens |
| File call | 1,000,000 input tokens |
| Session context window | 1,000,000 tokens |
| Statement files | 10 MB each, 200 files, 60 MB per call |
| Document file | 8 MB |
| KYC codes | 10-minute expiry, 5 attempts, 5 sends per destination per hour |
Retries
Retry 429 and 5xx with exponential backoff (0.5 s, 1 s, 2 s, … up to 30 s, with jitter) and the same Idempotency-Key, so a retry never decides or bills twice. The SDKs do this by default.