# Errors

When a request fails the API responds with a non-2xx HTTP status code and a JSON body using the same envelope for every endpoint.

## Error response shape

```json
{
  "message": "A human-readable description of what went wrong.",
  "api_reference": "9a4b1c8e-2f63-4f9a-9f3a-9b1f5a7c2d4f",
  "errors": {
    "data.passport_number": ["The passport number format is invalid."]
  }
}
```

| Field           | Always present | Description                                                                                                                                                                                              |
|-----------------|:--------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `message`       | Yes            | A short, human-readable message. Suitable for logging or surfacing to operators - not always suitable for end users.                                                                                     |
| `api_reference` | Yes            | A unique UUID for this exact request. The same value is recorded against the call's audit trail entry on WatchEye's side.                                                                                |
| `errors`        | On `400` only  | Field-keyed map of per-field validation messages. Present when the failure is a validation error (e.g. missing or malformed `data.*` fields). Each value is an array of one or more messages.            |

The same envelope is used across all error status codes (`400`, `401`, `402`, `403`, `404`, `409`, `422`, `429`, `5xx`). Successful responses also include `api_reference` so you can correlate any response - success or failure - against your own logs.

## Using api_reference when raising support tickets

Every API call - whether it succeeded, returned a validation error, or hit an internal error - is written to WatchEye's audit log, keyed by the `api_reference` UUID. If you need to raise a support ticket about a specific failed call:

1. Capture the `api_reference` value from the response body. (Many integrations already log every response payload - if yours does not, log at minimum the status code, the `message`, and the `api_reference`.)
2. Include the `api_reference` in your support request, along with the endpoint you called and the rough time of the call.
3. Support can use the `api_reference` to look up the exact request body, status code, response body and (where applicable) upstream provider response that we stored for that call.

This makes intermittent failures much easier to diagnose than a textual description of the symptoms alone, especially for endpoints that proxy out to third-party providers (`business_check`, ID checks, etc.).

> **Note:** For idempotent replays (see the [Idempotency](/docs/guides/watcheye_api/idempotency) section), the `api_reference` returned by the replay is the same UUID as the original successful call, not a new value. That is intentional - the replay is identical to the original response in every respect.
