# Errors & limits

Errors share one shape and are never charged. One engine failing does not fail the request: that answer gets status timeout or failed with an error field giving the reason, is free, and the other engines return as usual. Only when every requested engine is unavailable does the whole request return 503.

| HTTP | code | Meaning |
| --- | --- | --- |
| 400 | `invalid_request` | Missing or malformed parameter; message names the field |
| 400 | `unsupported_engine` | Unknown engine id in engines |
| 401 | `invalid_api_key` | API key missing, wrong or disabled |
| 402 | `insufficient_credits` | Balance too low to hold this request |
| 403 | `plan_not_allowed` | Your plan can’t use this endpoint or parameter, e.g. index on Starter, group_by on Pro |
| 404 | `not_found` | job_id does not exist or has expired |
| 500 | `internal_error` | Server error. Contact support with the request_id |
| 503 | `engines_unavailable` | Every requested engine is temporarily unavailable. The response has Retry-After (seconds); nothing is held or charged. If any one engine is available the request runs as usual |

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "本次请求需预占 9 credits，余额 4",
    "request_id": "req_7a11c2"
  }
}
```

```json
{
  "error": {
    "code": "engines_unavailable",
    "message": "请求的引擎当前都不可用：claude、grok",
    "request_id": "req_5c02e4"
  }
}
```

### Limits

- No account-level rate limit. Keep concurrency under 100 requests for stability (to be load-tested).
- At most 8 engines × 10 samples = 80 answers per request.
- Transient engine errors (network, timeout, rate limit, 5xx) are retried automatically up to 2 times within the time limit, at no extra charge.
- prompt up to 2,000 characters; up to 20 competitors.
- Cache lasts 24 hours; async job results are kept 7 days.
