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

# Coinbase Derivatives: Predictions WebSocket Commands

You manage subscriptions with JSON commands. Your first command must carry credentials; see [Authentication](/derivatives-predictions/websocket/authentication).

> **Commands**
>
> * [Subscribe](#subscribe): Subscribes to one channel.
> * [Unsubscribe](#unsubscribe): Removes one or more subscriptions.
> * [List subscriptions](#list-subscriptions): Lists the subscriptions on the connection.
> * [Update subscription](#update-subscription): Adds instruments to, or removes them from, a subscription.

## Command keys

Every command is a JSON object. The server rejects unknown keys and wrong JSON types with error code `8`. See [Errors](/derivatives-predictions/websocket/overview#errors).

> [!TIP]
>
> Keys are required (`Y`), optional (`N`), or conditionally required (`C`). Conditional keys are required based on the presence or value of other keys.

| Key | Type | Req | Description |
| :- | :- | :- | :- |
| `id` | Integer | N | Your request ID. Echoed as `id` on the response. `null` on the response when omitted. |
| `cmd` | String | Y | `subscribe`, `unsubscribe`, `list_subscriptions`, or `update_subscription`. |
| `params` | Object | C | Command parameters. Accepted keys: `channels`, `ticker`, `tickers`, `id`, `ids`, `sid`, `sids`, `action`. |
| `key`, `passphrase`, `signature`, `time` | String | C | Credentials. See [Authentication](/derivatives-predictions/websocket/authentication#authentication). |

Value types are strictly enforced. `channels`, `tickers`, and `ids` must be arrays of strings. `sid` must be an integer and `sids` an array of integers. Instrument IDs in `params.id` and `params.ids` must be strings.

## Subscribe

Subscribes to one channel. A command with more than one channel is rejected.

| Key | Type | Req | Description |
| :- | :- | :- | :- |
| `cmd` | String | Y | `subscribe` |
| `params.channels` | Array of strings | Y | Exactly one channel: `ticker`, `trade`, `orderbook`, `instrument_lifecycle`, or `event_lifecycle`. See [Channels](/derivatives-predictions/websocket/channels). |
| `params.ticker` | String | N | One instrument ticker. See [Instrument selectors](#instrument-selectors). |
| `params.tickers` | Array of strings | N | Instrument tickers. |
| `params.id` | String | N | One numeric instrument ID, as a string. |
| `params.ids` | Array of strings | N | Numeric instrument IDs, as strings. |

Example request:

```json theme={null}
{
  "id": 2,
  "cmd": "subscribe",
  "params": {
    "channels": ["orderbook"],
    "ticker": "NFL-GAMEWINNER-26NOV28LARSF-LAR"
  }
}
```

The server responds with a `subscribed` frame:

| Field | Type | Description |
| :- | :- | :- |
| `id` | Integer | Your request `id`. |
| `type` | String | `subscribed` |
| `msg.channel` | String | The subscribed channel. |
| `msg.sid` | Integer | Subscription ID assigned by the server. Every data frame for this subscription carries it. |

Example response:

```json theme={null}
{
  "id": 2,
  "type": "subscribed",
  "msg": {
    "channel": "orderbook",
    "sid": 1
  }
}
```

> [!NOTE]
>
> `subscribed` means the request was accepted. For the orderbook channel, the snapshot for each instrument follows separately.

On one connection, an instrument can belong to only one subscription per channel. A subscribe that overlaps an existing subscription on the same channel is rejected with error code `6`. This includes an all-instruments subscription and any explicit subscription on the same channel.

### Instrument selectors

The `ticker`, `trade`, and `orderbook` channels accept exactly four selectors: `ticker`, `tickers`, `id`, and `ids`. There are no aliases.

* You can combine selectors; the server takes their union and removes duplicates.
* Omit all selectors on `ticker` or `trade` to subscribe to all instruments.
* `orderbook` requires at least one selector.
* `instrument_lifecycle` and `event_lifecycle` always cover all resources. A selector on these channels is rejected.
* A malformed or non-canonical ID is rejected with error code `8`. A valid selector that matches no instrument is rejected with error code `5`.

The examples below use the `ticker` channel. One ticker:

```json theme={null}
{
  "id": 1,
  "cmd": "subscribe",
  "params": {
    "channels": ["ticker"],
    "ticker": "NFL-GAMEWINNER-26NOV28LARSF-LAR"
  }
}
```

Several tickers:

```json theme={null}
{
  "id": 2,
  "cmd": "subscribe",
  "params": {
    "channels": ["ticker"],
    "tickers": [
      "NFL-GAMEWINNER-26NOV28LARSF-SF",
      "NFL-GAMEWINNER-26NOV28LARSF-LAR"
    ]
  }
}
```

One instrument ID:

```json theme={null}
{
  "id": 3,
  "cmd": "subscribe",
  "params": {
    "channels": ["ticker"],
    "id": "598471892347"
  }
}
```

Several instrument IDs:

```json theme={null}
{
  "id": 4,
  "cmd": "subscribe",
  "params": {
    "channels": ["ticker"],
    "ids": ["598471892347", "598471892348"]
  }
}
```

No selector, which subscribes to all instruments. Valid on `ticker` and `trade` only:

```json theme={null}
{
  "id": 5,
  "cmd": "subscribe",
  "params": {
    "channels": ["ticker"]
  }
}
```

## Unsubscribe

Removes one or more subscriptions.

| Key | Type | Req | Description |
| :- | :- | :- | :- |
| `cmd` | String | Y | `unsubscribe` |
| `params.sids` | Array of integers | C | Subscription IDs to remove. Required unless `params.sid` is sent. |
| `params.sid` | Integer | C | One subscription ID to remove. Used when `params.sids` is absent. |

Example request:

```json theme={null}
{
  "id": 6,
  "cmd": "unsubscribe",
  "params": {
    "sids": [1, 2]
  }
}
```

The server sends one `unsubscribed` frame per removed subscription:

| Field | Type | Description |
| :- | :- | :- |
| `id` | Integer | Your request `id`. |
| `sid` | Integer | The removed subscription ID. |
| `seq` | Integer | Highest data `seq` successfully sent on the subscription. `0` if none. |
| `type` | String | `unsubscribed` |

Example response for subscription `1`, whose last data frame had `seq` `57`. A second frame follows for subscription `2`:

```json theme={null}
{
  "id": 6,
  "sid": 1,
  "seq": 57,
  "type": "unsubscribed"
}
```

If the request includes both valid and unknown subscription IDs, the server removes the valid subscriptions and returns error code `4` for the unknown IDs.

## List subscriptions

Lists the active subscriptions on the connection.

| Key | Type | Req | Description |
| :- | :- | :- | :- |
| `cmd` | String | Y | `list_subscriptions` |

Example request:

```json theme={null}
{
  "id": 4,
  "cmd": "list_subscriptions"
}
```

The server responds with an `ok` frame:

| Field | Type | Description |
| :- | :- | :- |
| `id` | Integer | Your request `id`. |
| `type` | String | `ok` |
| `msg` | Array of objects | One entry per subscription. |
| `msg[].channel` | String | Channel of the subscription. |
| `msg[].sid` | Integer | Subscription ID. |

Example response:

```json theme={null}
{
  "id": 4,
  "type": "ok",
  "msg": [
    {
      "channel": "orderbook",
      "sid": 1
    },
    {
      "channel": "event_lifecycle",
      "sid": 2
    }
  ]
}
```

## Update subscription

Adds instruments to, or removes them from, an existing subscription without tearing it down.

| Key | Type | Req | Description |
| :- | :- | :- | :- |
| `cmd` | String | Y | `update_subscription` |
| `params.action` | String | Y | `add_instruments` or `delete_instruments`. |
| `params.sid` | Integer | C | Subscription to update. Send exactly one of `params.sid` or `params.sids`. |
| `params.sids` | Array of integers | C | Subscription to update, as an array with exactly one entry. Send exactly one of `params.sid` or `params.sids`. |
| `params.ticker` | String | C | Instrument ticker. At least one selector is required. |
| `params.tickers` | Array of strings | C | Instrument tickers. |
| `params.id` | String | C | Instrument ID. Accepted for `ticker` and `orderbook` subscriptions only. |
| `params.ids` | Array of strings | C | Instrument IDs. Accepted for `ticker` and `orderbook` subscriptions only. |

Example request:

```json theme={null}
{
  "id": 5,
  "cmd": "update_subscription",
  "params": {
    "sid": 1,
    "action": "add_instruments",
    "tickers": ["NFL-GAMEWINNER-26NOV28LARSF-SF"]
  }
}
```

The server responds with an `ok` frame:

| Field | Type | Description |
| :- | :- | :- |
| `id` | Integer | Your request `id`. |
| `sid` | Integer | The updated subscription ID. |
| `seq` | Integer | Highest data `seq` successfully sent on the subscription. |
| `type` | String | `ok` |
| `msg.tickers` | Array of strings | The subscription's full instrument list after the update. An instrument without a ticker is listed by its ID. |

Example response. Subscription `1` is an `orderbook` subscription, so the snapshot for the added instrument was sent first:

```json theme={null}
{
  "id": 5,
  "sid": 1,
  "seq": 43,
  "type": "ok",
  "msg": {
    "tickers": [
      "NFL-GAMEWINNER-26NOV28LARSF-LAR",
      "NFL-GAMEWINNER-26NOV28LARSF-SF"
    ]
  }
}
```

Rules:

* `trade` subscriptions accept only `ticker` and `tickers` on update.
* Lifecycle subscriptions and all-instruments subscriptions cannot be updated. To change an all-instruments subscription, unsubscribe and subscribe again.
* You cannot add an instrument that is already in this subscription or in another subscription on the same channel.
* `delete_instruments` cannot remove every remaining instrument; that request is rejected. Use [Unsubscribe](#unsubscribe) instead.
* When you add instruments to an `orderbook` subscription, the server sends a snapshot for each new instrument before its updates. The `ok` frame is sent after the snapshots.
* An update sent while another update on the same subscription is still pending is rejected with error code `6`.
