> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pornfactoryai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors and rate limits

> Handle API failures without duplicating work or charges.

Errors use one JSON shape:

```json theme={"system"}
{
  "error": "A human-readable explanation.",
  "code": "invalid_request"
}
```

| Status | Code                   | Meaning                                          |
| ------ | ---------------------- | ------------------------------------------------ |
| `400`  | `api_error`            | Missing or malformed input                       |
| `401`  | `unauthorized`         | Missing, invalid, expired, or revoked key        |
| `402`  | `insufficient_credits` | The wallet cannot cover the request              |
| `403`  | `forbidden`            | Missing scope or suspended account               |
| `404`  | `not_found`            | The scoped request does not exist                |
| `409`  | `conflict`             | Idempotency key reused with a different body     |
| `413`  | `payload_too_large`    | Request payload exceeds the limit                |
| `422`  | `invalid_request`      | Unsupported source or media input                |
| `429`  | `rate_limited`         | API key exceeded the request window              |
| `502`  | `api_error`            | Generation submission is temporarily unavailable |
| `503`  | `service_unavailable`  | A temporary platform dependency is unavailable   |

## Retry guidance

* Retry `429`, `502`, and `503` with exponential backoff and jitter.
* Retry a timed-out generation submit with the same idempotency key and body.
* Do not retry `400`, `401`, `402`, `403`, or `422` without changing the cause.
* Treat `409` as a request-body mismatch, not a transient failure.

The default key limit is 60 authenticated requests per 60-second window.
Inspect `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and
`X-RateLimit-Reset` on authenticated responses.
