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

# Errors

> Standard error responses across all Closient APIs.

All APIs return errors in a consistent envelope format.

## Error Format

```json theme={null}
{
  "error": {
    "code": "NOT_FOUND",
    "message": "The requested resource was not found.",
    "status": 404,
    "details": null
  }
}
```

## Error Codes

| Status | Code               | Description                                         |
| ------ | ------------------ | --------------------------------------------------- |
| 400    | `BAD_REQUEST`      | The request body or parameters are invalid          |
| 401    | `UNAUTHORIZED`     | Missing or invalid API key                          |
| 403    | `FORBIDDEN`        | Valid key but insufficient permissions              |
| 404    | `NOT_FOUND`        | Resource does not exist                             |
| 409    | `CONFLICT`         | Resource already exists or state conflict           |
| 422    | `VALIDATION_ERROR` | Request body failed validation                      |
| 429    | `RATE_LIMITED`     | Too many requests — see [Rate Limits](/rate-limits) |
| 500    | `INTERNAL_ERROR`   | Unexpected server error                             |

## Validation Errors

`422 VALIDATION_ERROR` responses include field-level details:

```json theme={null}
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input.",
    "status": 422,
    "details": [
      {
        "field": "gtin",
        "message": "GTIN must be 8, 12, 13, or 14 digits."
      }
    ]
  }
}
```

## Best Practices

* **Check the `code` field** for programmatic error handling, not the `message`
* **Log the full error response** for debugging
* **Implement retry logic** with exponential backoff for `429` and `5xx` errors
* **Do not retry** `4xx` errors (except `429`) — they indicate a client issue

## Domain-specific 422 responses

Some endpoints return `422` with a domain-specific message identifying which input field failed which rule. See:

* [AB 660 / Date Labels](/guides/ab-660-date-labels) — the Products API returns `422` when `product_name`, `description`, `net_content`, or `usage_instructions` contains a phrase banned by California AB 660 (e.g. `"sell by"`, `"best before"`, `"expires on"`).
