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

# Errors and codes

> The complete error catalog for the Qustody API.

Every error response carries both an HTTP status code and a stable numeric `code` you can switch on programmatically. The shape is:

```json theme={null}
{
  "error": {
    "code": 1300,
    "type": "NOT_FOUND",
    "message": "Wallet not found",
    "request_id": "req_01HXYZ..."
  }
}
```

Always log `request_id` — it lets Qustody operators trace the full request path.

## Code ranges

| Range       | Family                           |
| ----------- | -------------------------------- |
| `1000–1099` | Authentication and authorization |
| `1100–1199` | Validation                       |
| `1200–1299` | Policy and approval              |
| `1300–1399` | Transaction lifecycle            |
| `1400–1499` | Vault and resource ownership     |
| `1500–1599` | Upstream node and chain          |
| `1600–1699` | Server / infrastructure          |

## Authentication and authorization (1000–1099)

| Code   | Type                | HTTP | Meaning                                                           |
| ------ | ------------------- | :--: | ----------------------------------------------------------------- |
| `1000` | `UNAUTHORIZED`      |  401 | Missing or invalid bearer token                                   |
| `1001` | `FORBIDDEN`         |  403 | Authenticated but RBAC permission missing for the resource+action |
| `1002` | `API_KEY_REVOKED`   |  401 | The API key has been revoked or rotated                           |
| `1003` | `INVALID_SIGNATURE` |  401 | Webhook or request signature did not verify                       |

**Recovery:** verify the bearer token, check the user's role assignments via `GET /v1/users/{id}/roles`, or rotate the API key with `POST /v1/credentials/rotate`.

## Validation (1100–1199)

| Code   | Type                    | HTTP | Meaning                                                                        |
| ------ | ----------------------- | :--: | ------------------------------------------------------------------------------ |
| `1100` | `VALIDATION`            |  400 | Generic validation failure (see `message`)                                     |
| `1101` | `MISSING_FIELD`         |  400 | A required field is absent                                                     |
| `1102` | `INVALID_ADDRESS`       |  400 | Address is not a valid Quantum Chain address                                   |
| `1103` | `INVALID_AMOUNT`        |  400 | Amount is non-numeric, negative, or zero where not allowed                     |
| `1104` | `DUPLICATE_EXTERNAL_ID` |  409 | An object with this `external_id` already exists for the tenant                |
| `1105` | `OWNERSHIP_PROOF`       |  400 | The ownership-proof signature did not verify against the registered public key |
| `1106` | `INVALID_EMAIL`         |  400 | Email address is malformed                                                     |
| `1107` | `INVALID_URL`           |  400 | URL is malformed or non-HTTPS in production                                    |
| `1108` | `INVALID_PAGINATION`    |  400 | `limit` is out of range or `cursor` is malformed                               |
| `1109` | `AMOUNT_OVERFLOW`       |  400 | Amount exceeds 256-bit unsigned bounds                                         |
| `1110` | `STRING_TOO_LONG`       |  400 | A string field exceeds its allowed length                                      |

**Recovery:** fix the input. Validation errors are not retryable.

## Policy and approval (1200–1299)

| Code   | Type                 | HTTP | Meaning                                                                                                          |
| ------ | -------------------- | :--: | ---------------------------------------------------------------------------------------------------------------- |
| `1200` | `POLICY_DENIED`      |  422 | A policy rule rejected the transaction outright (e.g. amount > MAX\_AMOUNT, address on BLACKLIST\_ADDRESS)       |
| `1201` | `APPROVAL_REQUIRED`  |  422 | The transaction requires approvers; this is informational. The transaction is created in `PENDING_AUTHORIZATION` |
| `1202` | `APPROVAL_NOT_FOUND` |  404 | The approval record does not exist or has expired                                                                |

**Recovery:** for `1200`, modify the request or update the policy. For `1201`, route the transaction to the appropriate approvers.

## Transaction lifecycle (1300–1399)

| Code   | Type                    | HTTP | Meaning                                                                                              |
| ------ | ----------------------- | :--: | ---------------------------------------------------------------------------------------------------- |
| `1300` | `TX_NOT_FOUND`          |  404 | The transaction ID does not exist for this tenant                                                    |
| `1301` | `TX_INVALID_STATE`      |  409 | Operation not allowed in the transaction's current state (e.g. signing a `BROADCASTING` transaction) |
| `1302` | `TX_SIGNATURE_MISMATCH` |  422 | The submitted post-quantum signature did not verify against the wallet's registered public key       |
| `1303` | `TX_BROADCAST_FAILED`   |  502 | The Quantum Chain node rejected the raw transaction                                                  |
| `1304` | `TX_NONCE_TOO_LOW`      |  422 | The nonce was already used on chain                                                                  |

**Recovery:** for `1301`, fetch the latest state with `GET /v1/transactions/{id}`. For `1302`, confirm the signer is using the correct key. For `1303` and `1304`, cancel the transaction and resubmit.

## Vault and resource (1400–1499)

| Code   | Type              | HTTP | Meaning                               |
| ------ | ----------------- | :--: | ------------------------------------- |
| `1400` | `VAULT_NOT_FOUND` |  404 | Vault does not exist for this tenant  |
| `1401` | `VAULT_DUPLICATE` |  409 | A vault with this name already exists |

## Upstream node and chain (1500–1599)

| Code   | Type               | HTTP | Meaning                                                                |
| ------ | ------------------ | :--: | ---------------------------------------------------------------------- |
| `1500` | `NODE_UNAVAILABLE` |  503 | The Quantum Chain RPC node is unreachable; circuit breaker may be open |
| `1501` | `CHAIN_ERROR`      |  502 | The node returned an error (gas estimation, QVM revert, etc.)          |

**Recovery:** retry with exponential backoff. If `CUSTODY_NODE_BACKUP_RPC_URLS` is configured, Qustody fails over automatically.

## Server / infrastructure (1600–1699)

| Code   | Type                   | HTTP | Meaning                                                        |
| ------ | ---------------------- | :--: | -------------------------------------------------------------- |
| `1600` | `INTERNAL_ERROR`       |  500 | Unexpected server error; see `request_id`                      |
| `1601` | `IDEMPOTENCY_CONFLICT` |  422 | Same `Idempotency-Key` reused with a different method or path  |
| `1602` | `RATE_LIMITED`         |  429 | Tenant or API key exceeded the rate limit; honor `Retry-After` |

**Recovery:** for `1600`, retry once after a short delay; if it persists, contact support with the `request_id`. For `1601`, generate a fresh idempotency key. For `1602`, respect the `Retry-After` header and consider a Redis-backed limiter for cluster deployments.

## Retry policy

| HTTP class                         | Retry? | Strategy                                       |
| ---------------------------------- | ------ | ---------------------------------------------- |
| `4xx` (validation, auth, conflict) | No     | Fix input; do not retry                        |
| `409` `TX_INVALID_STATE`           | No     | Refresh state, then act                        |
| `429`                              | Yes    | Back off `Retry-After` seconds                 |
| `502 / 503`                        | Yes    | Exponential backoff with jitter, max 5 retries |
| `500`                              | Yes    | Once after 1–2s; if persistent, escalate       |

Always include an `Idempotency-Key` on retried mutating requests so the server collapses duplicates.

## Webhook delivery errors

Webhook delivery failures don't surface to the API caller. They appear in:

* `GET /v1/webhooks/{id}/deliveries` — per-delivery status, last response code, retry count.
* `webhook.delivery.failed` events — when an endpoint exhausts its retry budget.

If your endpoint returns `410 Gone`, Qustody marks it `DISABLED` permanently. Recreate it to resume deliveries.

## Related

* [API overview](/qustody/api-overview)
* [Troubleshooting](/qustody/troubleshooting)
* [Webhooks](/concepts/webhooks)
