## GET /openapi/v1/derivatives/pairs

The perpetual and futures contracts of one crypto asset, or of one exchange, with price,
volume, funding rate, open interest and basis.

**Coverage.** Only the derivatives exchanges we collect, and only contracts whose base asset is
an asset on `/assets`. The list is refreshed once an hour, and each row's `data_time` is the
hour of the refresh it comes from. An exchange whose latest refresh failed keeps its previous
rows, so its `data_time` is older. A futures contract leaves the list at its expiration, and one
without an expiration date is not listed.

### Query parameters

| Parameter | Type | Default | Notes |
|:--|:--|:--|:--|
| `id` | integer | | The asset id from `/assets`. **Exactly one** of `id` and `exchange_id` |
| `exchange_id` | integer | | An exchange id, as `/exchanges` and `/derivatives/exchanges` publish it |
| `category` | string | both | `perpetual` or `futures` |
| `page`, `size`, `limit`, `offset` | integer | `size` 20 | As on `/assets` |
| `sort` | string | `volume_24h:desc` | `volume_24h`, `open_interest_usd`, `funding_rate`, written `<key>[:asc\|desc]`; a key with no direction is ascending. A `null` sorts last descending and first ascending. Equal values keep a fixed order |

### Response

```json
{
  "code": 0,
  "message": "success",
  "message_key": "SUCCESS",
  "result": {
    "items": [
      {
        "exchange": { "id": 42, "name": "Binance", "slug": "binance", "logo": "https://s2.coinmarketcap.com/static/img/exchanges/64x64/270.png" },
        "base": { "id": 1, "symbol": "BTC", "name": "Bitcoin", "slug": "bitcoin" },
        "pair": "BTC/USDT",
        "quote_symbol": "USDT",
        "category": "perpetual",
        "price": "67210.5",
        "volume_24h": "12345678901.23",
        "volume_percent": "31.52",
        "index_price": "67205.1",
        "funding_rate": "0.0001",
        "open_interest_usd": "8765432109.87",
        "index_basis": "0.00008",
        "expiration_time": null,
        "data_time": "2026-10-27T08:00:00Z"
      }
    ],
    "page": 1,
    "total_page": 3,
    "total": 52
  }
}
```

#### Item fields

| Field | Type | Notes |
|:--|:--|:--|
| `exchange` | object | `{id, name, slug, logo}`; `id` is the `/exchanges` id, `logo` an **empty string** when there is none. Present whichever of `id` and `exchange_id` you asked by |
| `base` | object | `{id, symbol, name, slug}`; `id` is the `/assets` id. Present either way too |
| `pair` | string | Such as `BTC/USDT` |
| `quote_symbol` | string | |
| `category` | string | `perpetual` or `futures` |
| `price` | string | |
| `volume_24h` | string | 24h volume in USD |
| `volume_percent` | string | This contract's share of the 24h volume of **every contract your request matched** — across all pages, not only this one — as a percentage: `"31.52"` is 31.52%. `"0"` when the matched volume is zero |
| `index_price` | string or `null` | `null` when the exchange reports none, or reports 0 |
| `funding_rate` | string or `null` | `null` for futures |
| `open_interest_usd` | string or `null` | Some exchanges report a contract's open interest as a quantity of the asset rather than in USD; we pass the value on as reported |
| `index_basis` | string or `null` | |
| `expiration_time` | string or `null` | When a futures contract expires, RFC3339 UTC; `null` for perpetuals |
| `data_time` | string | The hour of the refresh this row comes from, RFC3339 UTC — always on the hour |

### Examples

```bash
# Bitcoin's perpetuals, biggest volume first
curl -H "X-Api-Key: <your-api-key>" \
  "https://open-api.coinworldcap.com/openapi/v1/derivatives/pairs?id=1&category=perpetual"

# One exchange's contracts, by open interest
curl -H "X-Api-Key: <your-api-key>" \
  "https://open-api.coinworldcap.com/openapi/v1/derivatives/pairs?exchange_id=42&sort=open_interest_usd:desc&limit=50"
```

| HTTP status | `code` | When |
|:--|:--|:--|
| 400 | 40000 | Both or neither of `id` and `exchange_id`; either not a positive integer (one value, not a list); a `category` other than `perpetual` and `futures`; a `sort` key outside the three above, or a malformed `sort`; the paging limits of `/assets` |

An `id` or `exchange_id` with no contracts — one that does not exist, an RWA's id, an exchange
we do not collect — is an empty page, not a `404`. The other errors are in [Errors](#errors).
