Error Handling
Tchavi returns standard HTTP status codes with a structured JSON error body.
Tchavi returns standard HTTP status codes. Errors include a flat JSON body — the machine-readable code is in error, and some codes add a details object:
{
"error": "insufficient_credits",
"message": "You don't have enough credits for this request.",
"statusCode": 402,
"details": { "credits_remaining": 12, "credits_required": 40 }
}Common error codes
| Status | Code | Description |
|---|---|---|
| 400 | bad_request | Invalid parameter — the message says which one |
| 401 | invalid_api_key | Missing or invalid API key |
| 402 | insufficient_credits | Not enough credits — details carries credits_remaining and, when known, credits_required |
| 403 | key_inactive | The key is revoked, suspended or expired — details.status says which |
| 403 | plan_model_restricted | Free-level account calling a model outside the Budget group — top up to unlock it (details.upgrade_url) |
| 403 | model_not_allowed | The model is not available (inactive or unknown) |
| 403 | forbidden | The key's IP allow-list or endpoint restrictions reject this request |
| 404 | not_found | Unknown model ID or job ID |
| 413 | prompt_too_long | Prompt exceeds this model's limit — see below |
| 429 | rate_limit_exceeded | RPM, TPM or IP limit reached — wait for Retry-After seconds (also in details.retry_after) |
| 429 | free_tier_daily_limit | Free-level daily cap (50 requests) reached — resets at midnight UTC, Retry-After says when |
| 500 | internal_error | Server error — retry or contact support |
| 502 | provider_error | The AI provider returned an error — retry, or try another model |
| 503 | provider_saturated | The provider is at capacity — retry after details.retry_after seconds |
| 503 | service_unavailable | Temporary outage — retry with backoff |
Prompt length limits
A few models accept a smaller prompt than their underlying context window, because the provider charges a higher rate above a threshold and we cap the window rather than raise the credit rate for everyone. Those models return 413 prompt_too_long, with the exact ceiling in the response so you can split the input without guessing:
{
"error": "prompt_too_long",
"message": "Prompt is too long for \"grok-4.6\". This model accepts up to 180000 tokens of input; your request is about 241300.",
"statusCode": 413,
"details": { "model": "grok-4.6", "max_prompt_tokens": 180000 }
}| Model | Prompt limit |
|---|---|
grok-4.6 | 180 000 tokens |
gemini-3.1-pro | 180 000 tokens |
qwen3.7-flash | 230 000 tokens |
max_prompt_tokens is the limit we actually enforce, and it matches the context window shown on each model's page — a request trimmed to it is accepted. Every other model accepts input up to its full context window. Base64 images and PDFs do not count toward the limit.
See also Rate Limits and Credits & Billing.