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

# Errors

> Error shape, codes, and how to handle them.

## Error envelope

Every error response uses the same shape:

```json theme={null}
{ "error": { "code": "INSUFFICIENT_CREDITS", "message": "Not enough credits", "details": null } }
```

* `code` - stable, machine-readable; branch on this.
* `message` - human-readable.
* `details` - present on validation errors (`400`); the offending fields and why they failed.

## Common codes

| HTTP | `code`                     | Meaning                                                   |
| ---- | -------------------------- | --------------------------------------------------------- |
| 400  | `VALIDATION_ERROR`         | Request body/params failed validation (see `details`).    |
| 401  | `UNAUTHORIZED`             | Missing, invalid, revoked, or expired API key.            |
| 402  | `INSUFFICIENT_CREDITS`     | Not enough credits for this generation.                   |
| 402  | `SUBSCRIPTION_REQUIRED`    | Your plan can't perform this action.                      |
| 404  | `NOT_FOUND`                | The job, style, or upload doesn't exist (or isn't yours). |
| 429  | `RATE_LIMIT_ERROR`         | Per-key rate limit hit - see [Rate limits](/rate-limits). |
| 429  | `CONCURRENT_LIMIT_REACHED` | Too many generations in flight at once.                   |
| 429  | `USAGE_LIMIT_EXCEEDED`     | Usage allowance exceeded for the period.                  |
| 500  | `INTERNAL_ERROR`           | Unexpected server error - safe to retry with backoff.     |

## Job failures vs request errors

The errors above are returned by the HTTP request itself. A generation that **starts** but fails
returns `200` with a terminal job whose `status` is `failed`:

```json theme={null}
{ "data": { "id": "...", "status": "failed", "error": { "code": "GENERATION_FAILED", "message": "..." } } }
```

Job-level `error.code` is one of `GENERATION_FAILED` or `EXTRACTION_FAILED`.

## Handling guidance

* `402` → top up credits / upgrade before retrying.
* `429` → honor `Retry-After` and back off ([Rate limits](/rate-limits)).
* `400` → fix the request using `details`; don't blind-retry.
* `5xx` → retry with exponential backoff (use an [Idempotency-Key](/idempotency) on creates).
