Errors
Response shape
Most errors come back as a single-field JSON object:
{ "error": "descriptive message" }Some errors originate inside the internal tRPC layer and get forwarded with a richer shape:
{
"code": "UNAUTHORIZED",
"message": "descriptive message",
"issues": [ /* optional Zod validation details */ ]
}Either way, inspect the HTTP status code first and use the body for a human-readable explanation.
Hit this through the civitai CLI rather than the REST API?
The CLI turns these statuses into exit codes and its own messages, and the mapping is not one-to-one — one 429 is exit 2, another is exit 6. Look the message you got up on CLI troubleshooting, which is indexed by the string the binary prints.
Status codes
| Status | Meaning | Typical cause |
|---|---|---|
| 200 | OK | Successful read. |
| 400 | Bad Request | Invalid query parameters. For list endpoints, response body includes Zod-style validation issues. Combining ?query= with ?page= also returns 400. |
| 401 | Unauthorized | Missing or invalid token on an Authenticated endpoint, or an auth-only filter (e.g. ?favorites=true) on a Mixed endpoint without a session. |
| 403 | Forbidden | Valid token, but the user is not permitted to access the resource. |
| 404 | Not Found | Unknown model, version, or hash. Body shape: {"error": "No model with id 0"}. |
| 405 | Method Not Allowed | Wrong HTTP verb for the endpoint. |
| 429 | Too Many Requests | Either edge rate limiting (Cloudflare) or the page * limit > 1000 pagination cap — see Pagination. |
| 500 | Internal Server Error | Unexpected failure. Safe to retry with backoff. |
Retries
The API does not expose a Retry-After header for most failures. For 5xx and 429 responses, apply exponential backoff starting at ~1 second and cap at ~30 seconds. Don't retry 4xx responses other than 429 — the request shape itself is the problem.
Rate limits
There is no per-endpoint rate limit exposed as a stable contract. Cloudflare enforces edge limits (generic DDoS / abuse protection) in front of the API; those are operational, not a published SLA. Treat unexpected 429s as a signal to back off, not as a scheme to code against.