# Errors

Errors use a consistent JSON format:

```json
{
  "type": "validation_error",
  "errors": [
    {"code": "invalid", "detail": "Only numbers is required. Remove space and any other non-numeric character", "attr": "transactions.0.account"}
  ]
}
```

| Field | Description |
|---|---|
| `type` | `validation_error` (bad input), `client_error` (request can't be processed) or `server_error` |
| `errors[].code` | Machine-readable code |
| `errors[].detail` | Human-readable message. Safe to show to your users |
| `errors[].attr` | The field at fault, using a dot path for nested fields (for example `transactions.0.amount`), or `null` |

## HTTP status codes

| Status | Meaning |
|---|---|
| `400` | Invalid request, or a business rule failed (for example insufficient balance or limits exceeded) |
| `401` | Missing, invalid or expired credentials, or a key used in the wrong environment |
| `403` | Your role can't perform this action, or your IP isn't whitelisted |
| `404` | Not found |
| `429` | Rate limited. Retry after the `Retry-After` header |
| `500` | Unexpected error. Retry with the same idempotency key, or contact support |

## Common error codes

| `code` | Meaning |
|---|---|
| `invalid_request_data` | The request failed a business check. Read `detail` |
| `limits_exceeded` | Over your account's per-transaction or daily limit |
| `invalid_api_ref` | `api_ref` must be unique |
| `validation_error` | Invalid API keys or other input |

Some older endpoints return `{"detail": "..."}` instead. Handle both.
