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

# Error codes

> Every v0 error code, what returns it, and how to fix it

When a `/api/v0` request fails, the API returns an HTTP error status and a JSON
body carrying a **stable, machine-readable code** and a human-readable message.

```json theme={null}
{
  "code": "ERRWLT_1005",
  "message": "KYC not completed"
}
```

| Field     | Type   | Description                                                                   |
| --------- | ------ | ----------------------------------------------------------------------------- |
| `code`    | string | Stable error code. **Build your integration on this value.**                  |
| `message` | string | Human-readable description. It may be reworded over time, so do not parse it. |

The HTTP status always matches the code.

<Warning>
  **Two shapes are in play, and which you get depends on where the error is
  raised.** The codes on this page are returned by the services behind the edge.
  Errors raised *at* the edge — a rejected key, a tripped rate limit — currently
  come back in the envelope described on [Errors and the response
  envelope](/api-reference/errors), with a numeric `code`.

  Parse defensively: branch on the HTTP status first, then read `code` if it is a
  string and `errors[0].code` otherwise.
</Warning>

## Code format

Codes follow `ERR<MODULE>_<4-digit number>` — `ERRWLT_1000`. This matches the
platform's core codes, `ERRCORE_####`.

| Module      | Prefix    | Codes           | Applies to               |
| ----------- | --------- | --------------- | ------------------------ |
| Wallet      | `ERRWLT_` | 1000–1003, 1005 | `/api/v0/wallets`        |
| Reference   | `ERRREF_` | 1000–1001       | every `/api/v0` endpoint |
| Quote       | `ERRQUO_` | 1000            | `/api/v0/quotes`         |
| Recipient   | `ERRREC_` | 1000            | `/api/v0/recipients`     |
| Account     | `ERRACC_` | 1000            | `/api/v0/accounts`       |
| Transaction | `ERRTXN_` | 1000–1001       | POBO transactions        |

## Stability guarantee

**Error codes are permanent.** An existing code is never changed, reused for a
different meaning, removed, or renumbered. A new error always gets the next
unused number in its module. Only the human-readable message may be reworded.

## Fallback rules

| Situation                                                                                            | Code                        |
| ---------------------------------------------------------------------------------------------------- | --------------------------- |
| A reference id — `cus_…`, `wlt_…`, `acct_…`, `rec_…`, `qut_…`, `txn_…`, `snd_…` — cannot be resolved | `ERRREF_*`, on any endpoint |
| A required parameter that is **not** a reference id is missing, such as `currency`                   | `ERRCORE_1001`              |
| Authentication fails                                                                                 | `ERRCORE_1004`              |
| Anything else without a module-specific code                                                         | `ERRCORE_*`                 |

## Field validation errors

Some requests can fail validation on **several fields at once** — creating a
wallet, generating a quote, adding or updating a recipient. Those return a
`bad_request` with a **list of field errors**, not a single module code.

## Retries

<Note>
  **None of the current error codes are retryable.** Fix the request before
  sending it again.
</Note>

## Wallet errors

| Code                          | HTTP  | Meaning               |
| ----------------------------- | ----- | --------------------- |
| [`ERRWLT_1000`](#errwlt-1000) | `404` | Wallet not found      |
| [`ERRWLT_1001`](#errwlt-1001) | `400` | Wallet id is required |
| [`ERRWLT_1002`](#errwlt-1002) | `400` | User id is required   |
| [`ERRWLT_1003`](#errwlt-1003) | `400` | Unsupported network   |
| [`ERRWLT_1005`](#errwlt-1005) | `403` | KYC not completed     |

### `ERRWLT_1000`

**`404` · Wallet not found** · constant `WALLET_NOT_FOUND`

The wallet doesn't exist or doesn't belong to this customer.

**Returned when**

* The `walletId` doesn't match any wallet.
* The wallet belongs to a different customer. For security, access to another customer's wallet is always reported as not found.
* The wallet hasn't been created on the network yet (it has no provider wallet id).
* The wallet has been deleted (on get or balance).

**Endpoints**

* `GET /{userId}/{walletId}`
* `GET /{userId}/{walletId}/balance`
* `PATCH /{userId}/{walletId}`
* `DELETE /{userId}/{walletId}`
* `POST /{userId}/{walletId}/create-on-network`

<Tip>
  Use a `walletId` that belongs to this `userId` and hasn't been deleted.
</Tip>

### `ERRWLT_1001`

**`400` · Wallet id is required** · constant `WALLET_ID_REQUIRED`

The `walletId` path segment is blank or missing on a wallet-scoped operation.

**Returned when**

* A wallet-scoped operation is called with a blank or missing `walletId`.

**Endpoints**

* `get`
* `balance`
* `update`
* `delete`
* `create-on-network`

### `ERRWLT_1002`

**`400` · User id is required** · constant `USER_ID_REQUIRED`

A wallet operation is called with a blank or missing `userId`.

**Returned when**

* Any wallet operation is called with a blank or missing `userId`.

**Endpoints**

* `All wallet operations (list, get, create, balance, …)`

### `ERRWLT_1003`

**`400` · Unsupported network** · constant `UNSUPPORTED_NETWORK`

A balance is requested for a wallet on a network that isn't supported. The message lists the supported networks.

**Returned when**

* The wallet's network isn't supported and isn't the aggregate value `all`.

**Endpoints**

* `GET /{userId}/{walletId}/balance`

### `ERRWLT_1005`

**`403` · KYC not completed** · constant `KYC_NOT_COMPLETED`

The customer must complete KYC before a wallet can be created.

**Returned when**

* The customer's KYC status is not `COMPLETED`.
* The customer has no KYC record.

**Endpoints**

* `POST /{userId}`
* `POST /{userId}/{walletId}/create-on-network`

<Tip>
  Complete the customer's KYC, then create the wallet again.
</Tip>

<Note>
  A malformed or unknown `wlt_…` id returns a reference error (`ERRREF_1000` or `ERRREF_1001`). Validation of the create-wallet request body returns field-level `bad_request` errors.
</Note>

## Reference errors

v0 endpoints identify records by **reference ids** such as `cus_…`, `wlt_…`, `acct_…`, `rec_…`, `qut_…`, `txn_…` and `snd_…`. These codes are returned when a reference id can't be resolved, so they can appear on **any** module's endpoints.

| Code                          | HTTP  | Meaning              |
| ----------------------------- | ----- | -------------------- |
| [`ERRREF_1000`](#errref-1000) | `400` | Invalid reference id |
| [`ERRREF_1001`](#errref-1001) | `404` | Reference not found  |

### `ERRREF_1000`

**`400` · Invalid reference id** · constant `INVALID_REFERENCE`

The reference id is missing, blank, malformed, or the wrong type.

**Returned when**

* It's missing or blank. For example, `GET /api/v0/rails` with no `userId`.
* It's malformed and doesn't match the `<prefix>_<id>` format.
* It's the wrong type. For example, a `wlt_…` id sent where a `cus_…` id is expected.

**Endpoints**

* `Any path, query or body field that takes a reference id`

<Tip>
  Send the exact reference id the API returned, and check it's the right type for the field.
</Tip>

### `ERRREF_1001`

**`404` · Reference not found** · constant `REFERENCE_NOT_FOUND`

The reference id is correctly formatted but doesn't match any record.

**Returned when**

* The id never existed, has been deleted, or belongs to a different environment. The message names the entity, for example `Recipient 'rec_x' not found`.

**Endpoints**

* `Any v0 endpoint that takes a reference id`

<Note>
  **Reference errors vs module errors:** if a reference id doesn't resolve at all, the API returns `ERRREF_1001`. If it resolves but the caller can't access the record (for example, a quote owned by a different user), the API returns that module's own code, such as `ERRQUO_1000` or `ERRREC_1000`.
</Note>

## Quote errors

| Code                          | HTTP  | Meaning         |
| ----------------------------- | ----- | --------------- |
| [`ERRQUO_1000`](#errquo-1000) | `404` | Quote not found |

### `ERRQUO_1000`

**`404` · Quote not found** · constant `QUOTE_NOT_FOUND`

The quote doesn't exist or doesn't belong to this user.

**Returned when**

* The `quoteId` resolves but no matching quote exists.
* The quote belongs to a different user. For security, access to another user's quote is always reported as not found.
* A POBO pre-transaction or submit request refers to a quote that can't be found.

**Endpoints**

* `GET /quotes/{userId}/{quoteId}`
* `POST /pobo/transactions/pre-txn`
* `POST /pobo/transactions/submit`

<Note>
  A malformed or unknown `qut_…` id returns a reference error (`ERRREF_1000` or `ERRREF_1001`). Validation errors when generating a quote are returned as field-level `bad_request` errors.
</Note>

## Recipient errors

| Code                          | HTTP  | Meaning             |
| ----------------------------- | ----- | ------------------- |
| [`ERRREC_1000`](#errrec-1000) | `404` | Recipient not found |

### `ERRREC_1000`

**`404` · Recipient not found** · constant `RECIPIENT_NOT_FOUND`

The recipient doesn't exist, was deleted, or doesn't belong to this user.

**Returned when**

* This user has no active (non-deleted) recipient with this id.
* The recipient belongs to a different user. For security, access to another user's recipient is always reported as not found.

**Endpoints**

* `GET /recipients/{userId}/{recipientId}/counterparty-checks`

<Note>
  A malformed or unknown `rec_…` id returns a reference error. Validation errors when adding or updating a recipient (bank details, rail, address) are returned as field-level `bad_request` errors.
</Note>

## Account errors

| Code                          | HTTP  | Meaning             |
| ----------------------------- | ----- | ------------------- |
| [`ERRACC_1000`](#erracc-1000) | `400` | User id is required |

### `ERRACC_1000`

**`400` · User id is required** · constant `USER_ID_REQUIRED`

An account endpoint is called with a blank or missing `userId`.

**Returned when**

* Any account endpoint is called with a blank or missing `userId`.

**Endpoints**

* `open`
* `list`
* `get`
* `balance`
* `activity`
* `available-for-opening`
* `activate`
* `deactivate`

<Note>
  A malformed or unknown `acct_…` id returns a reference error. Validation errors when opening an account are returned as field-level `bad_request` errors.
</Note>

## Transaction errors

These codes apply to the **POBO (payment on behalf of)** flow.

| Code                          | HTTP  | Meaning                   |
| ----------------------------- | ----- | ------------------------- |
| [`ERRTXN_1000`](#errtxn-1000) | `400` | Sender id is required     |
| [`ERRTXN_1001`](#errtxn-1001) | `400` | Payout rail not supported |

### `ERRTXN_1000`

**`400` · Sender id is required** · constant `SENDER_ID_REQUIRED`

A POBO pre-transaction or submit request is sent without a `senderId`.

**Returned when**

* A pre-transaction or submit request doesn't include a `senderId` (`snd_…`). Every POBO transaction needs one.

**Endpoints**

* `POST /pobo/transactions/pre-txn`
* `POST /pobo/transactions/submit`

### `ERRTXN_1001`

**`400` · Payout rail not supported** · constant `RAIL_NOT_SUPPORTED`

The currency or payout rail doesn't support POBO.

**Returned when**

* A POBO quote or transaction would go through a payout rail that doesn't support POBO, such as ACH, FEDWIRE, SEPA or SWIFT.

**Endpoints**

* `POBO quote generation`
* `POST /pobo/transactions/pre-txn`
* `POST /pobo/transactions/submit`

<Tip>
  Use a supported currency and rail, for example INR via BANK\_TRANSFER, IMPS, UPI or CRYPTO.
</Tip>

<Note>
  **Related codes:** an unknown `txn_…` id returns `ERRREF_1001`, a missing POBO quote returns `ERRQUO_1000`, and a missing partner context returns `ERRCORE_1004`. Validation errors for amounts, currencies and purpose codes are returned as field-level `bad_request` errors.
</Note>
