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

# Errors

> Error shape, status codes, and why a payment failed.

Errors come back as [RFC 9457 problem details](https://www.rfc-editor.org/rfc/rfc9457) with a `Content-Type` of `application/problem+json`.

```json theme={null}
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.4",
  "title": "Forbidden",
  "status": 403,
  "detail": "Your service account is authenticated but lacks the permission this operation requires. Grant it in the Developer Hub and retry.",
  "code": "permission_denied",
  "instance": "/v1/beneficiaries"
}
```

| Field      | Use                                                                                     |
| ---------- | --------------------------------------------------------------------------------------- |
| `status`   | The HTTP status, repeated in the body.                                                  |
| `title`    | Short, stable category.                                                                 |
| `code`     | Stable machine-readable identifier for the failure. **This is the field to branch on.** |
| `detail`   | Human-readable specifics. **Log it, do not branch on it** — wording can change.         |
| `instance` | The path that produced the error.                                                       |
| `type`     | URI identifying the error class.                                                        |

<Warning>
  Branch on `status` and `code`, and on `errorKey` where a transaction carries one. Never parse
  `detail`.
</Warning>

## Authentication and access codes

These separate three problems that look identical from the outside: a signing bug, a missing
permission, and a feature you have not been provisioned. Each needs a different response from you,
and only the first is a bug in your integration.

| `code`                | Status | Meaning                                                                                                                                                                    |
| --------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `signature_required`  | `401`  | One or more of the four signature headers is missing.                                                                                                                      |
| `jwt_not_accepted`    | `401`  | You sent an `Authorization: Bearer` header. This API never accepts one.                                                                                                    |
| `signature_invalid`   | `401`  | All four headers were present, but the signature did not verify — or the nonce was replayed.                                                                               |
| `permission_denied`   | `403`  | The signature verified; the service account lacks the permission. Never a signing problem.                                                                                 |
| `feature_not_enabled` | `403`  | The signature and permissions are fine; the feature is not provisioned for your account. Granting a permission will not fix it — ask your StableMint contact to enable it. |

See [Authentication](/guides/authentication#troubleshooting) for what to change in each case.

## Status codes

| Status | Meaning                                                                                              | What to do                                                                                                                                                                              |
| ------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Malformed request — bad field, wrong shape, failed validation.                                       | Fix the request. Retrying unchanged will not help.                                                                                                                                      |
| `401`  | Authentication failed — missing, expired or invalid credentials, or a signature that did not verify. | Check the token or signature. See [Authentication](/guides/authentication).                                                                                                             |
| `403`  | Authenticated, but not permitted.                                                                    | The service account lacks the permission the operation requires. Grant it in the [Developer Hub](https://dashboard.stablemint.net/) — see [Service accounts](/guides/service-accounts). |
| `404`  | No such resource, or not yours.                                                                      | Check the identifier. StableMint returns `404` rather than `403` for resources belonging to another partner.                                                                            |
| `409`  | Conflict with current state — for example an already-consumed FX preview.                            | Re-read the resource before retrying.                                                                                                                                                   |
| `422`  | Well-formed, but a business rule refused it — an unsupported report format or currency.              | Read `code`.                                                                                                                                                                            |
| `429`  | Rate limited.                                                                                        | Back off exponentially and retry.                                                                                                                                                       |
| `500`  | Server error.                                                                                        | Safe to retry idempotent reads. For writes, verify before retrying.                                                                                                                     |

<Note>
  A `401` on a call that used to work most often means a service-account credential was rotated or an environment was crossed — sandbox credentials do not work against production, and vice versa.
</Note>

<Warning>
  **Insufficient balance is not one status across the API.** A payout answers `402`; an FX preview
  answers `400` with a full quote and a `failureReason` of `NoBalance` rather than a problem
  document — see [FX conversion](/guides/fx#when-a-preview-is-refused). Branch per endpoint rather
  than assuming a status means the same thing everywhere.
</Warning>

## Why a payment failed

A failed transaction carries an `errorKey` on `GET /v1/transactions/{reference}`. This is the field to surface to your own support team.

| `errorKey`              | Meaning                                                           | Recoverable                                                |
| ----------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------- |
| `InvalidAccountDetails` | IBAN, BIC or account details rejected.                            | Yes — correct and resubmit.                                |
| `InvalidWalletAddress`  | Destination wallet address invalid for the asset or chain.        | Yes — correct and resubmit.                                |
| `CurrencyNotAccepted`   | Receiving side will not take that currency.                       | Yes — use a different currency or beneficiary.             |
| `BankRejection`         | The beneficiary bank declined it.                                 | Sometimes — the reason sits with that bank.                |
| `BankUnreachable`       | The beneficiary bank could not be reached.                        | Yes — usually transient, retry later.                      |
| `RecipientBlocked`      | Recipient is blocked by a compliance control.                     | **No.** Do not retry. Escalate to your compliance contact. |
| `Expired`               | Lapsed before completing — typically an unpaid deposit reference. | Yes — create a new one.                                    |
| `Failed`                | Generic failure with no more specific cause.                      | Investigate the `timeline`.                                |

<Warning>
  **`RecipientBlocked` is not a technical error.** Retrying it, or routing around it with different details, may constitute circumventing a sanctions or AML control. Stop and escalate.
</Warning>

## Retrying safely

<CardGroup cols={2}>
  <Card title="Reads" icon="rotate">
    `GET` requests are safe to retry. Back off exponentially on `429` and `5xx`.
  </Card>

  <Card title="Writes" icon="shield-check">
    Send an `idempotencyKey` where the endpoint accepts one. Without it, a retry after an ambiguous failure risks creating a duplicate.
  </Card>
</CardGroup>

When a write fails and you cannot tell whether it landed, query [Transactions](/guides/transactions) before retrying rather than assuming either outcome.
