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

# Errors

> How Payzor reports errors, and what every status code means.

# Errors

Payzor returns JSON errors with an HTTP status code:

```json theme={null}
{ "error": "Saldo insuficiente. Disponible: $56 USDC" }
```

## Status codes

| Status | Meaning                            | Typical cause                                                                                                   |
| ------ | ---------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `400`  | Bad request                        | Missing/invalid field (`amountUsdCents` not a positive integer, bad address...).                                |
| `401`  | Unauthenticated                    | Missing or wrong credential; the message names the expected one.                                                |
| `402`  | Payment required / policy rejected | Budget exceeded, per-charge cap, or the agent's hard limits blocked the payment. The body explains exactly why. |
| `403`  | Forbidden                          | Valid credential, wrong scope (e.g. another merchant's resource), or KYT-blocked address.                       |
| `404`  | Not found                          | Unknown charge/PayLink/endpoint id.                                                                             |
| `409`  | Conflict                           | Operation invalid for current state (paying a paid charge, expired PayLink).                                    |
| `500`  | Server error                       | Bug or infrastructure issue. Safe to retry.                                                                     |
| `503`  | Service unavailable                | Feature requires PostgreSQL and it isn't configured; x402 facilitator unreachable.                              |

## Policy rejections are 200s (sometimes)

One nuance worth knowing: when an agent pays a charge and its **policy** blocks or pauses the payment, the endpoint still answers `200` with a structured outcome rather than an error code:

```json theme={null}
{ "paid": true, "charge": { "...": "..." } }                        // settled
{ "pendingApproval": true, "approvalId": "...", "reason": "..." }   // paused for human
{ "error": "Categoría 'services' no está ..." }                     // blocked (HTTP 402)
```

Agents are programs that branch on outcomes; giving them a machine-readable reason is more useful than a bare status code.

## Designing your integration around errors

1. **Branch on the three payment outcomes**, not just success/failure.
2. **Parse budget errors**: `excede_presupuesto_restante_350` embeds the exact remaining cents.
3. **Retry on 5xx only.** 4xx means your input or state is wrong; repeating won't help.
4. **Log `reference` values** from successful payments; they match across merchant charges and agent audit trails.
