l2BookDiff

Stream real-time L2 orderbook diffs (incremental updates) per block.

New endpoint - this endpoint is not a part of original Hyperliquid API and is added by us for builder convenience.

Stream incremental L2 orderbook changes as they happen. Each message contains all changed price levels across all subscribed coins for a single block, making this far more bandwidth-efficient than full snapshots.

For full snapshots, use l2Book. For just top-of-book, use bbo.

Subscribe

{
    "method": "subscribe",
    "subscription": {
        "type": "l2BookDiff",
        "coins": ["ETH", "BTC"]
    }
}

Parameters:

Parameter
Type
Required
Description

coins

string[]

No

Coins to subscribe to. Omit for all markets (requires ws:l2BookDiffAll permission).

marketTypes

string[]

No

All-markets only. Filters delivery by market type — see All-markets filter. Rejected if combined with coins.

All-markets filter

When coins is omitted, the optional marketTypes field restricts the firehose to specific market types. Each entry is "perp", "spot", "outcome", or the wildcard "*" (alone) for "every type the server currently tracks":

{
    "method": "subscribe",
    "subscription": {
        "type": "l2BookDiff",
        "marketTypes": ["perp", "outcome"]
    }
}

Omitting marketTypes defaults to ["perp"] — outcome and spot markets do not appear unless you opt in. The default never grows; new market types must be added to your marketTypes array explicitly. Pass ["*"] to auto-opt-in to future types.

A second subscribe with a different marketTypes value replaces the previous filter rather than coexisting with it.

Unsubscribe

Update data format

Each message contains all changed levels for all subscribed coins in a single block. One message per block (~14 blocks/sec). Levels with sz: "0" indicate that price level has been removed from the book.

Resync signal

When a block height gap is detected (e.g., after a service restart or connection loss), the server sends a resync message. Clients must discard their local book and re-bootstrap from a REST snapshot.

Field reference

Envelope fields (on every message):

Field
Type
Description

seq

number

Per-subscription sequence number (continuous across all coins, for session replay)

cursor

string

Cursor for session reconnection replay (format: height:timestamp)

Batch data fields (data):

Field
Type
Description

height

number

Block height

time

number

Block timestamp (milliseconds since epoch)

diffs

array

Array of per-coin diffs (only coins with changes in this block)

Per-coin diff fields (each item in diffs):

Field
Type
Description

coin

string

Market symbol (e.g., "ETH", "BTC")

epoch

string

Server epoch (UUID) — changes on service restart

seq

number

Per-coin sequence number — increments by 1 for each diff for this coin

prev_seq

number

Previous per-coin sequence number (for gap detection)

levels

array

Tuple of [bids, asks] — only changed levels are included

levels[][].px

string

Price as decimal string

levels[][].sz

string

Size as decimal string ("0" means level removed)

levels[][].n

number

Number of orders at this level (0 when level removed)

Resync data fields (data when type is "resync"):

Field
Type
Description

type

string

"resync"

coin

string

Market symbol

reason

string

Why resync occurred (e.g., "height_gap")

new_epoch

string

The new server epoch after restart

Building a local orderbook

  1. Subscribe to l2BookDiff for your coin(s) — start buffering messages.

  2. Fetch snapshot via the REST l2BookDiffSnapshot endpoint. Note the epoch and seq for each coin.

  3. Discard stale diffs: For each coin in each buffered batch, drop diffs where epoch doesn't match or seq <= snapshot.seq.

  4. Apply remaining diffs in order. The first diff for each coin should have prev_seq == snapshot.seq.

    • For each level in bids and asks:

      • If sz is "0", remove that price level.

      • Otherwise, upsert the price level with the new sz and n.

  5. Ongoing gap detection: Per coin, check prev_seq == your_current_seq on each diff. If there's a gap, re-bootstrap.

  6. Resync: If you receive a resync message, discard local state and re-bootstrap from step 1.

Examples

Common errors

  1. Too many coins - Reduce number of coins or upgrade tier

  2. Subscribing to all markets requires permission - Needs ws:l2BookDiffAll add-on

  3. Rate limit exceeded - Reduce subscription frequency

  4. Authentication failed - Check API key

Last updated