# L2 Book

After subscribing, the server pushes a `snapshot` (full book) followed by `delta` updates after each block. Maintain the book locally by applying deltas to the snapshot.

{% hint style="info" %}
**No auth.** Each `(symbol_id, depth, merge)` tuple is an independent channel instance with its own sequence number.
{% endhint %}

## Subscribe

```json
{ "channel": "l2_book", "symbol_id": 100001, "depth": 20, "merge": 10 }
```

| Param       | Detail                                                                                                                   |
| ----------- | ------------------------------------------------------------------------------------------------------------------------ |
| `symbol_id` | Required.                                                                                                                |
| `depth`     | One of `5 / 10 / 20 / 50 / 100 / 200`. Default `20`.                                                                     |
| `merge`     | Integer multiple of `tick_size`. Default `1` (no merge). Allowed values from the symbol's `price_step_merge_multiplier`. |

### Merge Rule

Effective granularity = `tick_size × merge`. Bids round down, asks round up to the nearest merged price; sizes at the same merged price are summed.

> Sequences (`seq`/`q`) from **different `merge` values are not comparable**. Each `(depth, merge)` combination maintains its own series. Always pair a snapshot with deltas that share the same merge value.

## Push Type

The outer envelope's `type` is either `"snapshot"` or `"delta"`.

## Payload

| Field | Type         | REST equivalent                               |
| :---: | ------------ | --------------------------------------------- |
|  `s`  | integer      | `symbol_id`                                   |
|  `b`  | array        | `bids` — `[price, size]`, descending by price |
|  `a`  | array        | `asks` — `[price, size]`, ascending by price  |
|  `m`  | integer      | `merge`                                       |
|  `p`  | integer      | previous update ID (sequence)                 |
|  `q`  | integer      | this update ID                                |
|  `t`  | integer (ms) | `time`                                        |

## Delta Rules

For each price level in the delta:

* `size == "0"` → **remove** that level
* Price not currently in the local book → **insert**
* Price already present → **update size**

## Local-Book Maintenance

{% stepper %}
{% step %}

### On `snapshot`

Replace the local book and record `q`.
{% endstep %}

{% step %}

### On `delta`

If `p == local.q`, apply the delta and set `local.q = q`. Otherwise **re-subscribe** to fetch a new snapshot.
{% endstep %}

{% step %}

### On server restart

A new snapshot arrives with `q = 1`; reset.
{% endstep %}
{% endstepper %}

> **Sequence gap = data loss.** If `delta.p` doesn't match your `local.q`, you missed at least one delta. Don't try to interpolate — re-subscribe and reset.

## Example Pushes

```json
{
  "channel": "l2_book",
  "symbol_id": 100001,
  "type": "snapshot",
  "ts": 1719500000150,
  "finality": "final",
  "data": {
    "s": 100001,
    "b": [["67500.00","2.3"],["67499.50","1.7"]],
    "a": [["67500.50","1.5"],["67501.00","2.1"]],
    "m": 10, "p": 0, "q": 100, "t": 1719500000120
  }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.lynxtrade.world/websocket/public-channels/l2-book.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
