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

# WebSocket L4 order book

> Use 0xArchive WebSocket and REST history together for L4 order-book reconstruction and gap-aware state.

Keep an order-level (L4) book for Hyperliquid core, Spot, HIP-3, or HIP-4: start from a checkpoint, apply ordered diffs, and rebuild when a gap appears. Every L4 family supports live subscriptions and checkpoint-anchored WebSocket replay: `l4_diffs` and `l4_orders` on core, and the `spot_`, `hip3_`, and `hip4_` prefixed channels on the other families. REST history and checkpoint routes serve the same records for bounded pulls. Lighter has L3 individual-order depth instead.

<div className="oxa-pipeline">
  <div className="oxa-pipeline-step">
    <span className="oxa-flow-tag">Snapshot</span>
    <span className="oxa-heading">Start from a checkpoint</span>
    <span>Pull an L4 snapshot for one family and symbol, or use the `l4_snapshot` that opens a subscription or replay.</span>
  </div>

  <div className="oxa-pipeline-step">
    <span className="oxa-flow-tag">Diffs</span>
    <span className="oxa-heading">Apply updates in order</span>
    <span>Apply server-ordered diffs without dropping or reordering them, and keep each event's block and order metadata.</span>
  </div>

  <div className="oxa-pipeline-step">
    <span className="oxa-flow-tag">Live book</span>
    <span className="oxa-heading">Hold current state</span>
    <span>On a gap event, mark the book unsafe and rebuild from a fresh checkpoint.</span>
  </div>
</div>

## Subscribe to L4 diffs

An L4 subscription opens with an `l4_snapshot` of the full book, then sends ordered `l4_batch` messages. This script prints the snapshot size and the first few batches for SOL. It runs on any plan, including Free.

```javascript theme={"theme":"github-dark"}
import WebSocket from "ws";

const apiKey = process.env.OXARCHIVE_API_KEY;
if (!apiKey) throw new Error("Set OXARCHIVE_API_KEY");

const ws = new WebSocket("wss://api.0xarchive.io/ws", {
  headers: { Authorization: `Bearer ${apiKey}` }
});
let batches = 0;

ws.onopen = () => ws.send(JSON.stringify({ op: "subscribe", channel: "l4_diffs", symbol: "SOL" }));

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  if (message.type === "l4_snapshot") {
    const { bids, asks } = message.data;
    console.log("snapshot at block", message.last_block_number, bids.length, "bid orders", asks.length, "ask orders");
  }
  if (message.type === "l4_batch") {
    // Apply message.data in order; each diff carries its block number (bn) and order ID (oid).
    console.log("batch of", message.data.length, "diffs, first:", message.data[0]?.dt, message.data[0]?.oid);
    if (++batches === 5) ws.close();
  }
  if (message.type === "error") console.error(message.error_code, message.message);
};
```

A BTC snapshot is several megabytes, so expect the first message on a busy market to take a moment.

## Order events

Live `l4_orders`, `hip3_l4_orders`, `spot_l4_orders`, and `hip4_l4_orders` messages use the `l4_batch` type. Items are ordered by block number, then by their order within the block. Each item carries the fields below; optional fields are omitted when absent.

| Field | Meaning |
| - | - |
| `ts` | Event time, Unix milliseconds |
| `bn` | Block number |
| `user` | Address that owns the order |
| `hash` | Transaction hash, when the event has one |
| `status` | Status as Hyperliquid reports it, such as `open`, `filled`, or `canceled` |
| `coin` | Market as Hyperliquid names it. On Spot this can be a pair ID such as `@107`; the message's `symbol` carries the pair as you subscribed, such as `HYPE-USDC` |
| `side` | `B` for a bid, `A` for an ask |
| `px`, `sz` | Limit price and size |
| `oid` | Order ID |
| `type` | Order type, such as `Limit` or `Stop Market` |
| `ro` | Reduce-only |
| `trig` | Trigger order |
| `tif` | Time in force, such as `Gtc`, `Ioc`, or `Alo`, when the order has one |
| `cloid` | Client order ID set by the client that placed the order: `0x` followed by 32 hexadecimal characters. Omitted when the order has none |
| `exchange` | `hl`, `hip3`, `spot`, or `hip4` |

Use `cloid` to match an event to an order your own system placed. Hyperliquid core and HIP-3 channels carry accepted orders only. Spot and HIP-4 channels also carry rejected orders, with the rejection reason in `status`.

## Keep the book correct

* **Baseline:** start every family from a REST snapshot or checkpoint route, or from the `l4_snapshot` that opens a subscription or replay.
* **Updates:** use live diffs for current state, and WebSocket replay, REST history, or the [SDK reconstruction helpers](/sdks/reconstruction) for historical work.
* **Ordering:** apply L4 events in the order the server sends them and keep the block and order metadata. Never sort by timestamp alone. (Lighter L3 history orders by `sequence` instead.)
* **Queue placement:** a new-order item in an `l4_batch` can carry an optional `insert_before` key. Insert the new order ahead of that order ID within its price level; when the key is absent, append it at the tail. The initial `l4_snapshot` lists each price level in queue priority.
* **Gaps:** when a sequence or replay gap appears, mark the book unsafe, stop output, and rebuild from a snapshot or replay checkpoint, or rerun the bounded window.
* **Load:** confirm one symbol keeps up before adding markets, and drop or throttle UI updates before you ever drop book events. Size the client against [WebSocket limits](/websocket/limits), and check the symbol's published coverage before requesting history.
* **Storage:** label stored data as L2, L3, or L4, and as current, historical, replayed, or reconstructed. Do not collapse L4 into a generic "orderbook" label; the distinction matters for backtests, charts, alerts, and anything you publish.

A production L4 client often uses REST for the baseline and recovery, WebSocket for live state or replay, and the [Data quality](/data-quality) routes before trusting the output.

## Next step

Replay an L4 window from a checkpoint with [WebSocket replay](/websocket/replay#l4-and-full-depth-replay).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.