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

# Errors

> Response envelopes, HTTP status codes, and error codes

## Response envelopes

Successful responses always open with `status`, `message` and `success: true`, in that order. Most endpoints then nest the payload under `data`, but some return it at the top level beside `success` — each endpoint's reference page shows which:

```json theme={null}
{
  "status": 200,
  "message": "Business wallets retrieved successfully",
  "success": true,
  "data": { ... }
}
```

Error responses carry the HTTP code in `status` and a human-readable `message` — note there is **no** `success` field on errors:

```json theme={null}
{
  "status": 403,
  "message": "API access has been disabled for this account"
}
```

<Tip>
  Branch on the HTTP status code (or `success === true`), not on the presence of `status` — it is present on both success and error responses, as a number.
</Tip>

## HTTP status codes

| Code  | Meaning                                                                                                                             |
| ----- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `200` | Success                                                                                                                             |
| `201` | Resource created (e.g. a new virtual account)                                                                                       |
| `202` | Accepted — the request is queued for review (e.g. USD bank account issuance)                                                        |
| `400` | Bad request — validation failed, insufficient balance, or a domain rule was violated                                                |
| `401` | Missing or invalid API key, or the account no longer exists                                                                         |
| `403` | Key valid but not allowed: IP not allowlisted, API access disabled, restricted account, or a feature your account isn't enabled for |
| `404` | Resource not found                                                                                                                  |
| `409` | Conflict — e.g. duplicate email on account creation                                                                                 |
| `500` | Something went wrong on Rolla's side — safe to retry with backoff                                                                   |

## Validation errors

Requests that fail schema validation return `400` with `"message": "Validation failed"` and an `errors` array carrying one entry per offending field. Each entry has a `code`, a `message` and a `path` (an array, because the field may be nested), and the field's own name is prefixed onto `message` so a single string is enough to show a user:

```json theme={null}
{
  "status": 400,
  "message": "Validation failed",
  "errors": [
    {
      "code": "too_small",
      "message": "Description: Memo is required",
      "path": ["description"]
    }
  ]
}
```

Not every `400` carries an `errors` array. Rejections that come from a domain rule rather than the schema — insufficient balance, an unsupported currency, a duplicate account number — return a descriptive `message` and nothing else.

## Error codes

Some errors additionally carry a machine-readable `code` at the top level of the body:

| `code`                     | HTTP  | Meaning                                                                                                                                |
| -------------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `ACCOUNT_DOES_NOT_EXIST`   | `401` | The account behind the API key has been deleted                                                                                        |
| `ACCOUNT_RESTRICTED`       | `403` | The account is deactivated or blacklisted (also sets `accountBlocked: true`)                                                           |
| `EMAIL_BLOCKLISTED`        | `403` | The email cannot be used ([Create Account](/api-reference/endpoint/accounts/create))                                                   |
| `PAYER_NAMES_DISABLED`     | `403` | [Named Payouts](/guides/named-payouts) is not enabled for your account                                                                 |
| `ACCOUNT_EMAIL_EXISTS`     | `409` | An account with that email already exists ([Create Account](/api-reference/endpoint/accounts/create))                                  |
| `APPLICATION_NOT_APPROVED` | `400` | The account's application must be approved first                                                                                       |
| `MISSING_ACCOUNT_DETAILS`  | `400` | Bank account issuance needs more data — the body lists the missing fields                                                              |
| `ACCOUNT_NOT_SUBMITTED`    | `409` | The account must be submitted before it can be approved ([Approve Account](/api-reference/endpoint/accounts/approve-account), sandbox) |
| `REQUEST_DECLINED`         | `409` | A previous issuance request for this account was declined                                                                              |
| `USD_ACCOUNT_NOT_FOUND`    | `404` | No USD deposit account exists for this account                                                                                         |

Errors without a `code` are identified by their HTTP status and `message`. Most `403`s carry no code — a key that isn't a white-label tenant calling `/accounts` or [List Transactions Across Accounts](/api-reference/endpoint/accounts/list-transactions), or a request from an IP that isn't allowlisted, are refused by `message` alone.

## Handling failures in money movement

A payout that fails **after** being created doesn't come back as an HTTP error — the transaction moves to `failed` or `rejected` and the funds return to your wallet. Listen for [`transaction.failed` webhooks](/api-reference/webhooks/events) rather than relying on the initial response alone, and see [Idempotency & Retries](/concepts/idempotency) for safely retrying ambiguous requests.
