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

# Errors reference

> Every error code, its HTTP status, and what it means.

All error responses are JSON with `{ "error": "<code>", ... }`. Some include
a `details` object with extra context.

## Authentication & authorisation

| Code                       | HTTP | Meaning                                                         |
| -------------------------- | ---- | --------------------------------------------------------------- |
| `missing_bearer_token`     | 401  | No `Authorization: Bearer …` header on a `/me/*` call.          |
| `invalid_token`            | 401  | JWT could not be verified (signature, exp, iss mismatch, etc.). |
| `unknown_issuer`           | 401  | JWT's `iss` doesn't match any registered partner.               |
| `invalid_claims`           | 401  | JWT verified but is missing required claims (`sub`, `role`).    |
| `missing_partner_slug`     | 401  | `/integrations/*` request missing `x-partner-slug`.             |
| `missing_signature`        | 401  | `/integrations/*` request missing `x-signature`.                |
| `unknown_partner`          | 401  | `x-partner-slug` doesn't match a known partner.                 |
| `invalid_signature_format` | 401  | `x-signature` parse failed (missing `t=` or `v1=`).             |
| `signature_expired`        | 401  | Timestamp outside the ±5 min window.                            |
| `invalid_signature`        | 401  | HMAC did not verify against the body.                           |
| `partner_disabled`         | 403  | Partner exists but is disabled in admin.                        |
| `forbidden`                | 403  | Caller has the wrong role for the endpoint.                     |

## Consumer & redemption

| Code                           | HTTP | Meaning                                                                                           |
| ------------------------------ | ---- | ------------------------------------------------------------------------------------------------- |
| `validation_failed`            | 400  | Zod body validation failed. `issues` array has details.                                           |
| `voucher_not_found`            | 404  | No voucher with that ID.                                                                          |
| `voucher_inactive`             | 422  | Voucher exists but is not currently active.                                                       |
| `voucher_not_wallet_flow`      | 422  | Tried to claim an instant-flow voucher.                                                           |
| `voucher_not_yet_valid`        | 422  | Voucher's `validFrom` is in the future.                                                           |
| `voucher_expired`              | 422  | Past `validUntil`.                                                                                |
| `voucher_out_of_scope`         | 403  | Voucher's merchant or category is outside your partner allowlist.                                 |
| `voucher_not_valid_at_outlet`  | 422  | Voucher not linked to this outlet.                                                                |
| `merchant_not_found`           | 404  |                                                                                                   |
| `merchant_inactive`            | 422  |                                                                                                   |
| `merchant_out_of_scope`        | 403  |                                                                                                   |
| `outlet_not_found`             | 404  |                                                                                                   |
| `outlet_inactive`              | 422  |                                                                                                   |
| `outlet_pin_not_set`           | 422  | Outlet hasn't configured a PIN yet — staff needs to set one.                                      |
| `invalid_pin`                  | 401  | Wrong 4-digit PIN.                                                                                |
| `no_claim`                     | 422  | Wallet voucher redeemed without first claiming.                                                   |
| `voucher_not_yet_applicable`   | 422  | Wallet voucher redeemed before its `applicableFrom` date. `details: { applicableFrom }`.          |
| `voucher_no_longer_applicable` | 422  | Wallet voucher redeemed after its `applicableUntil` date. `details: { applicableUntil }`.         |
| `not_a_favorite`               | 403  | Voucher is `favoritesOnly` and user hasn't favorited the merchant.                                |
| `limit_reached`                | 422  | Per-user cycle redemption count exceeded. `details: { limit, used, cycleKey }`.                   |
| `global_cap_reached`           | 422  | Shared cycle cap exhausted across all users for this voucher. `details: { cap, used, cycleKey }`. |
| `too_far`                      | 422  | GPS distance > 150m. `details: { distanceMeters, maxMeters }`.                                    |
| `codes_exhausted`              | 422  | Manual code pool empty — the merchant needs to upload more.                                       |
| `code_generation_failed`       | 500  | Internal: auto code generator gave up. Treat as retryable.                                        |
| `rate_limited`                 | 429  | Too many redemption attempts. `details: { retryAfterSeconds }`.                                   |
| `user_not_found`               | 404  | (DELETE) No user for `(partner, externalUserId)`.                                                 |
| `upsert_failed`                | 500  | (POST users) Race-recovery failed; safe to retry.                                                 |
