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

# WebSocket Topics

> Topic names, payloads, snapshots, sequencing, and recovery rules.

Subscribe to WebSocket topics by sending a `subscribe` message. Topic names are case-insensitive for the pair segment at input time and are normalized by Stabyl. Examples use the canonical topic key `USD_NGN`.

```json theme={null}
{
  "type": "subscribe",
  "topics": ["orderbook.USD_NGN", "trades.USD_NGN"],
  "snapshot": true
}
```

## Topic Catalog

| Topic                           | Access  | Snapshot | Description                                   |
| ------------------------------- | ------- | -------- | --------------------------------------------- |
| `orderbook.{pair_key}`          | Public  | Yes      | Order book snapshots and delta batches        |
| `trades.{pair_key}`             | Public  | No       | Public trade tape updates                     |
| `trades.*`                      | Public  | No       | Public trade updates for all available pairs  |
| `ticker.{pair_key}`             | Public  | No       | 24-hour ticker updates                        |
| `ticker.*`                      | Public  | No       | Ticker updates for all available pairs        |
| `candles.{pair_key}.{interval}` | Public  | No       | OHLCV candle updates for one interval         |
| `candles.*`                     | Public  | No       | Candle updates across all pairs and intervals |
| `user.orders`                   | API key | No       | Order status updates for your account         |
| `user.fills`                    | API key | No       | Fill updates for your account                 |

Supported candle intervals are `1m`, `5m`, `15m`, `1h`, `4h`, and `1d`.

<Note>
  `orderbook.*` is not supported. Subscribe to exact order book topics such as
  `orderbook.USD_NGN`.
</Note>

## Subscription Response

When a subscription succeeds, the server responds with `subscribed`.

```json theme={null}
{
  "type": "subscribed",
  "topics": ["orderbook.USD_NGN", "trades.USD_NGN"],
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "snapshots": [
    {
      "topic": "orderbook.USD_NGN",
      "data": {
        "pair_id": "USD/NGN",
        "bids": [{ "price": "1650.00", "quantity": "10.00" }],
        "asks": [{ "price": "1650.50", "quantity": "8.00" }],
        "sequence": 901234
      },
      "ts": "2026-01-14T10:30:00Z"
    }
  ]
}
```

Snapshots are best effort and currently apply to exact order book topics. If a snapshot is omitted, fetch the REST order book snapshot before applying live deltas.

## Data Envelope

All topic updates use the same outer envelope:

```json theme={null}
{
  "type": "data",
  "topic": "trades.USD_NGN",
  "data": {},
  "seq": 12345,
  "ts": "2026-01-14T10:30:00Z",
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b"
}
```

Use the envelope `seq` for WebSocket recovery. Payloads may also include their own domain sequence fields.

## Order Book Payloads

An `orderbook.{pair_key}` message can carry either a snapshot-style payload or a delta batch.

Snapshot style payload:

```json theme={null}
{
  "type": "data",
  "topic": "orderbook.USD_NGN",
  "seq": 901234,
  "ts": "2026-01-14T10:30:00Z",
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "data": {
    "pair_id": "USD/NGN",
    "bids": [{ "price": "1650.00", "quantity": "10.00" }],
    "asks": [{ "price": "1650.50", "quantity": "8.00" }],
    "sequence": 901234,
    "timestamp": "2026-01-14T10:30:00Z"
  }
}
```

Delta batch payload:

```json theme={null}
{
  "type": "data",
  "topic": "orderbook.USD_NGN",
  "seq": 901235,
  "ts": "2026-01-14T10:30:02Z",
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "data": {
    "pair_id": "USD/NGN",
    "updates": [
      {
        "side": "bid",
        "price": "1650.00",
        "quantity": "12.00",
        "sequence": 901235
      }
    ],
    "timestamp": "2026-01-14T10:30:02Z"
  }
}
```

Recommended recovery:

1. Fetch `GET /partner/exchange/orderbook/USD%2FNGN/snapshot`.
2. Subscribe to `orderbook.USD_NGN` with `snapshot: true`.
3. Apply updates in `seq` order.
4. If a gap is detected, fetch a fresh REST snapshot and resume from the new baseline.

## Trade Payload

`trades.{pair_key}` and `trades.*` carry public trade tape updates.

```json theme={null}
{
  "type": "data",
  "topic": "trades.USD_NGN",
  "seq": 901235,
  "ts": "2026-01-14T10:31:00Z",
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174222",
    "pair_id": "USD/NGN",
    "price": "1649.50",
    "quantity": "25.00",
    "side": "buy",
    "sequence": 901235,
    "timestamp": "2026-01-14T10:31:00Z"
  }
}
```

Use `GET /partner/exchange/trades` for backfills and WebSocket trades for live updates.

## Ticker Payload

`ticker.{pair_key}` and `ticker.*` carry current 24-hour market statistics.

```json theme={null}
{
  "type": "data",
  "topic": "ticker.USD_NGN",
  "seq": 1201,
  "ts": "2026-01-14T10:31:00Z",
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "data": {
    "pair_id": "USD/NGN",
    "last": "1650.00",
    "best_bid": "1649.50",
    "best_ask": "1650.50",
    "volume": "10000.00",
    "volume_quote": "16500000.00",
    "timestamp": "2026-01-14T10:31:00Z"
  }
}
```

## Candle Payload

`candles.{pair_key}.{interval}` and `candles.*` carry OHLCV candle updates.

```json theme={null}
{
  "type": "data",
  "topic": "candles.USD_NGN.1m",
  "seq": 3201,
  "ts": "2026-01-14T10:31:00Z",
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "data": {
    "pair_id": "USD/NGN",
    "interval": "1m",
    "timestamp": "2026-01-14T10:31:00Z",
    "open": "1649.00",
    "high": "1651.00",
    "low": "1648.50",
    "close": "1650.00",
    "volume": "125.00",
    "volume_quote": "206250.00",
    "trade_count": 8
  }
}
```

## Private Order Update

`user.orders` carries order updates for your account. Subscribe with an API key that is enabled for exchange reads.

```json theme={null}
{
  "type": "data",
  "topic": "user.orders",
  "seq": 44,
  "ts": "2026-01-14T10:31:00Z",
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "data": {
    "id": "123e4567-e89b-12d3-a456-426614174000",
    "order_id": "123e4567-e89b-12d3-a456-426614174000",
    "pair_id": "USD/NGN",
    "side": "buy",
    "order_type": "limit",
    "time_in_force": "gtc",
    "status": "partially_filled",
    "quantity": "100.00",
    "filled_quantity": "50.00",
    "remaining_quantity": "50.00",
    "price": "1650.00",
    "avg_fill_price": "1649.50",
    "client_order_id": "cli-123",
    "created_at": "2026-01-14T10:30:00Z",
    "timestamp": "2026-01-14T10:31:00Z"
  }
}
```

Treat `filled`, `cancelled`, `rejected` as terminal. Confirm final state with `GET /partner/exchange/orders/{order_id}` when needed.

## Private Fill Update

`user.fills` carries fills for your account. It does not expose counterparty identity.

```json theme={null}
{
  "type": "data",
  "topic": "user.fills",
  "seq": 45,
  "ts": "2026-01-14T10:31:00Z",
  "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
  "data": {
    "fill_id": "123e4567-e89b-12d3-a456-426614174222",
    "pair_id": "USD/NGN",
    "order_id": "123e4567-e89b-12d3-a456-426614174000",
    "side": "buy",
    "liquidity": "maker",
    "price": "1649.50",
    "quantity": "25.00",
    "notional": "41237.50",
    "fee": "0.25",
    "fee_currency": "USD",
    "sequence": 901235,
    "timestamp": "2026-01-14T10:31:00Z"
  }
}
```

## Resume

Send `resume` when reconnecting:

```json theme={null}
{
  "type": "subscribe",
  "topics": ["orderbook.USD_NGN", "trades.USD_NGN", "user.orders"],
  "snapshot": true,
  "resume": {
    "epoch": "019bd2d1-5a9c-7e23-9cf1-1f87a3f2e91b",
    "seq": {
      "orderbook.USD_NGN": 901235,
      "trades.USD_NGN": 901235,
      "user.orders": 44
    }
  }
}
```

Resume is supported for exact topics, including `user.orders` and `user.fills`. Wildcard topics such as `trades.*` are not replayed. If the server cannot resume, it may omit replayed messages or send `connection_reset`. Rebuild the affected topic from REST, then continue processing new `data` messages.
