> ## 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.

# API overview

> How the Qustody API is organized — auth, idempotency, pagination, errors, and rate limits.

The Qustody API is a JSON over HTTPS API. Every endpoint accepts and returns `application/json` and is versioned under `/v1`.

The full machine-readable spec is available at [`/api-reference/openapi.json`](/api-reference/openapi.json) and is rendered at [API reference](/api-reference/introduction).

## Base URL

```
https://api.your-qustody-host.example
```

Set `CUSTODY_ENV=production` to enforce HTTPS for tenant URLs and webhook endpoints. Development environments may use HTTP.

## Resource families

| Family       | Path prefix                       | What it manages                                                  |
| ------------ | --------------------------------- | ---------------------------------------------------------------- |
| Tenants      | `/v1/tenants`                     | Tenant accounts (multi-tenant deployments)                       |
| Vaults       | `/v1/vaults`                      | Logical groupings of wallets                                     |
| Wallets      | `/v1/wallets`                     | Quantum Chain addresses with registered post-quantum public keys |
| Transactions | `/v1/transactions`                | Outbound transfers, lifecycle, signing payloads                  |
| Approvals    | `/v1/transactions/{id}/approvals` | Multi-approver workflow                                          |
| Policies     | `/v1/policies`                    | Spending limits, whitelists, approval rules                      |
| Webhooks     | `/v1/webhooks`                    | Outbound event delivery                                          |
| Assets       | `/v1/assets`                      | Token metadata for QRC-20 and native assets                      |
| Users        | `/v1/users`                       | Human users (when SSO is enabled)                                |
| Roles        | `/v1/roles`                       | RBAC role definitions and assignments                            |
| Credentials  | `/v1/credentials`                 | API keys, rotation, revocation                                   |
| Audit        | `/v1/audit`                       | Tamper-evident audit log                                         |
| Compliance   | `/v1/compliance`                  | AML screenings and travel-rule data                              |

## Authentication

All non-public endpoints require authentication. Two modes are supported.

### API key

```bash theme={null}
curl "$BASE_URL/v1/wallets" \
  -H "Authorization: Bearer $API_KEY"
```

API keys are created with `POST /v1/credentials` and scoped to a tenant. Rotate with `POST /v1/credentials/rotate`.

### SSO (OIDC)

Enabled with `CUSTODY_SSO_ENABLED=true`. Exchange your IdP token for a Qustody access token at `POST /v1/auth/login`, then send it in the `Authorization: Bearer` header. Refresh with `POST /v1/auth/refresh`.

## Idempotency

Every mutating endpoint accepts an `Idempotency-Key` header. Duplicate requests with the same key within 24 hours return the original response without re-executing.

```bash theme={null}
curl -X POST "$BASE_URL/v1/transactions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: 6a8b8b3e-77d0-4f60-9a18-6f4d3e3e1f3a" \
  -H "Content-Type: application/json" \
  -d '{ "wallet_id": "...", "to_address": "0x...", "value": "1000000000000000000" }'
```

Use a UUIDv4 per logical operation. Reusing keys across different requests is an error.

## Pagination

List endpoints use cursor-based pagination:

```bash theme={null}
curl "$BASE_URL/v1/transactions?limit=50&cursor=eyJpZCI6Li4ufQ==" \
  -H "Authorization: Bearer $API_KEY"
```

```json theme={null}
{
  "items": [...],
  "next_cursor": "eyJpZCI6Li4ufQ==",
  "has_more": true
}
```

When `has_more` is `false`, `next_cursor` is null. `limit` defaults to 50 and may not exceed 200.

## Filtering and sorting

Common query parameters:

| Param                             | Type    | Notes                                                   |
| --------------------------------- | ------- | ------------------------------------------------------- |
| `status`                          | string  | Filter transactions by state (e.g. `PENDING_SIGNATURE`) |
| `wallet_id`                       | uuid    | Scope to one wallet                                     |
| `vault_id`                        | uuid    | Scope to one vault                                      |
| `created_after`, `created_before` | RFC3339 | Time range                                              |
| `sort`                            | string  | `created_at:desc` (default) or `created_at:asc`         |

## Rate limits

Default rate limit is 120 requests per minute per API key with a burst of 20. Configurable via `CUSTODY_RATE_LIMIT_RPM` and `CUSTODY_RATE_LIMIT_BURST`.

When exceeded, the API returns `429 Too Many Requests` with `Retry-After` header.

```
HTTP/1.1 429 Too Many Requests
Retry-After: 12
```

For multi-replica deployments, configure a Redis backend with `CUSTODY_RATE_LIMIT_REDIS_URL` so limits are enforced cluster-wide.

## Standard response shape

Successful single-resource responses return the resource directly:

```json theme={null}
{
  "id": "...",
  "status": "SUBMITTED",
  "created_at": "2024-..."
}
```

List responses are wrapped:

```json theme={null}
{
  "items": [ /* ... */ ],
  "next_cursor": "...",
  "has_more": true
}
```

## Error envelope

All errors return:

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

The full code catalog is at [Errors and codes](/qustody/errors).

## Standard headers

| Header                                                       | Direction           | Purpose                                |
| ------------------------------------------------------------ | ------------------- | -------------------------------------- |
| `Authorization: Bearer <token>`                              | Request             | Authentication                         |
| `Idempotency-Key: <uuid>`                                    | Request (mutating)  | Safe retries                           |
| `X-Request-ID`                                               | Response            | Trace ID; quote it in support requests |
| `Retry-After`                                                | Response (429, 503) | Seconds to wait before retrying        |
| `X-Webhook-ID`, `X-Webhook-Timestamp`, `X-Webhook-Signature` | Webhook delivery    | HMAC-SHA256 verification               |

## Versioning

The API is versioned in the URL path (`/v1`). Breaking changes ship as `/v2` with a deprecation period announced in the changelog. Additive changes (new fields, new endpoints) are released within `/v1`.

## Health

| Endpoint       | Auth required  | Purpose                 |
| -------------- | -------------- | ----------------------- |
| `GET /healthz` | No             | Liveness                |
| `GET /readyz`  | No             | Readiness (DB + signer) |
| `GET /metrics` | No (port 9090) | Prometheus metrics      |

## Related

* [API reference](/api-reference/introduction)
* [Errors and codes](/qustody/errors)
* [Webhooks](/concepts/webhooks)
* [Authentication](/concepts/authentication)
