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

# WebSocket l2Book: Real-Time Full Order Book Snapshots

> Subscribe to l2Book over WebSocket to receive full L2 order book snapshots for any contract on every block — no polling required.

The `l2Book` channel delivers a complete order book snapshot for a contract on every block — roughly every 500 ms. Every message includes all price levels for both bids and asks, so you can always replace your local book state in full rather than applying partial diffs. When you subscribe, the server immediately pushes the current snapshot, so you get a consistent starting state without making a separate REST call.

## Subscribing

```json theme={"system"}
{"method": "subscribe", "subscription": {"type": "l2Book", "asset": "1"}}
```

Replace `"1"` with the numeric contract ID you want to track. You can hold simultaneous `l2Book` subscriptions for multiple assets on the same connection.

## Push message format

The server pushes a message like the following on every block:

```json theme={"system"}
{
  "channel": "l2Book",
  "data": {
    "asset": "1",
    "time": 0,
    "bookVersion": 1,
    "markPx": "0",
    "oraclePx": "0",
    "levels": [
      [
        {"px": "200", "sz": "20", "n": 2},
        {"px": "100", "sz": "10", "n": 1}
      ],
      []
    ]
  }
}
```

## Field reference

<ResponseField name="asset" type="string">
  The contract ID this snapshot belongs to. Matches the `asset` value in your subscription.
</ResponseField>

<ResponseField name="time" type="number">
  Snapshot timestamp in Unix milliseconds. May be `0` when the exchange is in a pre-launch state.
</ResponseField>

<ResponseField name="bookVersion" type="number">
  Monotonically increasing version counter for this asset's order book. Use this to detect duplicate or out-of-order messages — discard any message whose `bookVersion` is lower than or equal to the last one you processed.
</ResponseField>

<ResponseField name="markPx" type="string">
  Current mark price as a raw string. Returns `"0"` when mark price is not yet available.
</ResponseField>

<ResponseField name="oraclePx" type="string">
  Current oracle price as a raw string. Returns `"0"` when oracle price is not yet available.
</ResponseField>

<ResponseField name="levels" type="array">
  A two-element array: `levels[0]` contains bids sorted **high-to-low** by price; `levels[1]` contains asks sorted **low-to-high** by price. An empty array means no orders on that side.

  Each element within a level array is an object with the following fields:

  * **`px`** *(string)* — Price of this level (raw).
  * **`sz`** *(string)* — Total size resting at this price (raw).
  * **`n`** *(number)* — Number of individual orders aggregated at this price.
</ResponseField>

## Handling the initial snapshot

The server pushes the first snapshot immediately on subscribe. You can safely use this as your starting state:

<Steps>
  <Step title="Subscribe and receive the first snapshot">
    Send the subscribe message. The first `l2Book` message you receive is a full snapshot of the current book — store all levels in your local state.
  </Step>

  <Step title="Replace state on every subsequent message">
    Each subsequent push is also a full snapshot. Replace your entire local book (both sides) with the new `levels` — there is no need to apply diffs or maintain a patch log.
  </Step>

  <Step title="Use bookVersion for deduplication">
    If you subscribe to both `l2Book` and `bbo` for the same asset, compare `bookVersion` values to avoid processing stale data when messages arrive out of order.
  </Step>
</Steps>

<Tip>
  Use the WebSocket `l2Book` channel instead of polling the REST `/info` `l2Book` endpoint. You receive the initial snapshot automatically on subscribe, and every subsequent push keeps your local state current without any request overhead.
</Tip>

<Note>
  All price and size values are returned as raw strings. Apply the appropriate decimal precision for the contract when displaying values to users.
</Note>
