Errors & rate limits
Non-2xx responses use a small JSON error envelope. A few carry a stable code you can branch on.
Status codes
| Status | Meaning | Detail |
|---|---|---|
| 200 / 202 | Success | 200 returns the requested resource (a Check or UsageSummary); /api/feedback returns 202 with { "ok": true }. |
| 400 | Validation failed | The body did not match its schema (or the JSON was malformed). The response carries the Zod flatten() of the validation error. |
| 401 | Authentication required | No valid credential was supplied. /api/check, /api/check/stream, and /api/account/usage all require a Bearer token or session cookie. The fact-check routes return { "error": "sign in to run fact checks", "code": "unauthenticated" } — sign in or attach an API token. |
| 402 | Credits exhausted | Your monthly credit allowance is used up. The envelope includes a stable machine code: { "error": "…", "code": "credits_exhausted" }. Handle it by prompting an upgrade rather than retrying. |
| 429 | Rate limited | Too many requests. Back off and retry. |
| 503 | Daily budget / temporarily unavailable | The daily spend cap was reached, or the service is briefly unavailable. Respect the Retry-After header when present. |
Error envelope
JSON error responses share this shape. error is always present; code appears on errors with a stable machine identifier (today, most notably credits_exhausted).
| Field | Type | Required | Details |
|---|---|---|---|
error | string | required | Human-readable error message. |
code | string | optional | Stable machine code, present on some errors (e.g. "credits_exhausted"). |
Rate limiting
Every request is authenticated, so limits are enforced per account. On a 402 with credits_exhausted, stop retrying and surface an upgrade path; on 429 or 503, back off (and honor Retry-After when present). See Authentication for how to attach a token.