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

# Errors

> Every stable error code: meaning, HTTP status, and whether to retry.

Every error is the same envelope, with a stable `code` your integration may
branch on and a human-readable `message` that may change copy over time:

```json theme={null}
{ "error": { "code": "insufficient_funds", "message": "..." } }
```

Codes are **published**: never renamed, never removed — only added. Branch on
`code`, not on `message` or status text.

## Two namespaces

There are two different kinds of "it didn't work", and they behave
differently with money:

* **Rejections** (this page's first table) — the request itself was refused.
  **No payout was created and nothing was held.** Fix the request (or wait,
  where retryable) and submit again.
* **Failure codes** (second table) — a payout was accepted, held funds, and
  later died. The payout is terminal, `failure: { code, message }` is set,
  and **the hold is always released back to your available balance**.
  Resubmission is always a *new* payout with a *new* `Idempotency-Key`.

## Rejection codes

| Code                     | HTTP | Meaning                                                                                              | Retry?                                                                                                                                |
| ------------------------ | ---- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `validation_error`       | 400  | Malformed request: bad JSON, missing field, or a missing `Idempotency-Key` on create.                | After fixing the request.                                                                                                             |
| `unauthorized`           | 401  | Missing, malformed, revoked, or unknown API key.                                                     | No — fix the key.                                                                                                                     |
| `forbidden`              | 403  | Org suspended, or request IP not on your allowlist.                                                  | No — resolve with Jenzy / fix the allowlist.                                                                                          |
| `not_found`              | 404  | No such resource in your org. Unknown, foreign, and malformed ids look identical.                    | No.                                                                                                                                   |
| `insufficient_funds`     | 402  | The amount exceeds your available balance.                                                           | After funding (book a trade).                                                                                                         |
| `conflict`               | 409  | This `Idempotency-Key` was used with a different body, or its original request is still in progress. | Different body → new key. In progress → same key, shortly.                                                                            |
| `unknown_bank`           | 422  | `bank_uuid` doesn't name a payable bank.                                                             | After re-fetching `GET /banks`.                                                                                                       |
| `unknown_operator`       | 422  | `operator_ref_id` doesn't name a payable operator.                                                   | After re-fetching `GET /operators`.                                                                                                   |
| `invalid_mobile_number`  | 422  | The mobile number doesn't parse for the target operator.                                             | After fixing the number.                                                                                                              |
| `invalid_account_number` | 422  | The account number doesn't pass validation for the target bank.                                      | After fixing the number.                                                                                                              |
| `amount_limit_exceeded`  | 422  | This payout is above the per-payout maximum.                                                         | With a smaller amount.                                                                                                                |
| `rate_limited`           | 429  | Too many requests.                                                                                   | Yes — honor `Retry-After`.                                                                                                            |
| `org_limit_exceeded`     | 429  | Your org's rolling daily cap or payout-velocity check tripped.                                       | Yes — later.                                                                                                                          |
| `internal_error`         | 500  | Something broke on our side.                                                                         | Yes — and on create, reuse the **same** `Idempotency-Key`: you'll get the original outcome if one was reached, never a double payout. |
| `rail_disabled`          | 503  | This rail is administratively paused.                                                                | Yes — later.                                                                                                                          |
| `service_unavailable`    | 503  | A dependency is unavailable (e.g. reference data has never synced).                                  | Yes — later.                                                                                                                          |

## Failure codes

Carried in `failure.code` on a `failed` payout — on `GET /payouts/{id}` and
in the `payout.failed` webhook, identically. `failure.message` is fixed
per-code copy, safe to show to your own users.

| Code                        | Meaning                                                                          | Can a resubmission succeed?                                |
| --------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `recipient_account_invalid` | The provider rejected the destination (account doesn't resolve, invalid number). | Only after the destination is corrected.                   |
| `declined`                  | The provider declined the payout, or failed it without a reason. The catch-all.  | Unlikely unchanged — investigate before resubmitting.      |
| `provider_unavailable`      | Timeout or outage at the downstream provider.                                    | Yes — a fresh payout may plausibly succeed; retry shortly. |
| `temporarily_unavailable`   | A temporary condition on the Hermes side.                                        | Yes — retry later; no funds were deducted.                 |

<Note>
  A failed payout is never retried automatically, and the four codes above
  are the complete failure vocabulary — anything unmappable lands in
  `declined`.
</Note>
