# l2Book stream

> HyperCore private-preview documentation.

> For the complete documentation index, see [llms.txt](/docs/llms.txt).

<Callout intent="info">
  This API is in private preview. Target September 2026; timing is subject to change.
</Callout>


# l2Book stream

`l2Book` delivers aggregated price-level order book snapshots, one per block for each
market whose book changed. This is ideal for order book displays, depth analysis, and pricing.

For the corresponding gRPC snapshot stream, see [StreamL2Book](/docs/chains/hypercore-grpc/api-reference/stream-l2-book). For the diff representation and bootstrap procedure, see [l2BookDiff](/docs/chains/websockets/hypercore/streams/l2-book-diff#snapshot-to-diff-bootstrap).

## Subscribe

```json
{"method":"subscribe","subscription":{"type":"l2Book","coins":["BTC","ETH"],"nSigFigs":5,"mantissa":2,"nLevels":20}}
```

Use `marketTypes` instead of `coins` to subscribe to all markets of selected types:

```json
{"method":"subscribe","subscription":{"type":"l2Book","marketTypes":["spot"]}}
```

## Subscription parameters

| Parameter | Type | Required | Source | Description |
| --- | --- | --- | --- | --- |
| `coins` | string[] | No | Alchemy extension | Markets to subscribe to. Omit to subscribe to every market of the types in `marketTypes`, which defaults to perpetuals. The native API takes a single `coin` per subscription; the plural array is an Alchemy extension. |
| `marketTypes` | string[] | No | Alchemy extension | Restricts delivery by market type. Accepted values: `perp`, `spot`, `outcome`, or `*`. Defaults to `["perp"]`. Rejected if combined with `coins`. |
| `nSigFigs` | number | No | Foundation native | Aggregate price levels to N significant figures. Accepted values: `2`, `3`, `4`, `5`. |
| `mantissa` | number | No | Foundation native | Snap prices to a mantissa step. Accepted values: `2` or `5`. Valid only when `nSigFigs` is `5`. |
| `nLevels` | number | No | Alchemy extension | Levels per side: `1`, `10`, `20` (default), or `50`. |

The default never grows. New market types must be added to `marketTypes` explicitly, or pass `["*"]` to opt in to future types automatically.

Aggregation rounds bids down and asks up. With `nSigFigs: 5` and `mantissa: 2`, a bid of `70325` becomes `70324` and an ask of `70325` becomes `70326`.

## Acknowledgement

```json
{"channel":"subscriptionResponse","data":{"subscriptionId":"sub_01","type":"l2Book"}}
```

## Event envelope

```json
{"channel":"l2Book","subscriptionId":"sub_01","blockHeight":123456,"blockTime":1780000000000,"data":{"coin":"BTC","time":1780000000000,"levels":[[{"px":"100000.0","sz":"1.25","n":3}],[{"px":"100001.0","sz":"0.80","n":2}]]}}
```

## Payload fields

| Field | Type | Description |
| --- | --- | --- |
| `coin` | string | Market symbol. |
| `time` | integer | Block timestamp in milliseconds. |
| `levels` | array | Two-element tuple of `[bids, asks]`. Bids sorted descending, asks ascending. |
| `levels[][].px` | string | Price, as a decimal string. |
| `levels[][].sz` | string | Total size resting at this price level, as a decimal string. |
| `levels[][].n` | integer | Number of orders aggregated into this level. |

## Snapshot behavior

* Every message is a complete snapshot for the market it names
* A market is sent only when its book changed in that block
* Levels are aggregated: one level may represent many orders, and `n` reports how many
* Order IDs and user addresses are not exposed on this stream — use `l4BookUpdates` for those

## Choosing a book stream

| | l2Book | l2BookDiff | bbo | l4BookUpdates |
| --- | --- | --- | --- | --- |
| **Delivers** | Complete aggregated snapshot | Changed aggregated levels | Best bid and ask only | Changed individual orders |
| **Client state** | None required | Maintains a local book | None required | Maintains a local book |
| **Detail** | Aggregated levels | Aggregated levels | Top of book | Individual orders, with queue position |
| **Use case** | Displays, periodic reads | Efficient live book | Price and spread tracking | Market making, queue analysis |

## Unsubscribe

```json
{"method":"unsubscribe","subscription":{"type":"l2Book","coins":["BTC","ETH"]}}
```

Every message is a complete snapshot, so there is nothing to replay. After a disconnect, resubscribe and the next message re-establishes your state.