Skip to main content
Stream Lighter order books, trades, open interest, and funding live, and replay all six Lighter channels. Live messages use the same subscribe command and data envelope as live Hyperliquid channels, with the payload shapes on this page. Lighter’s second deployment, on Robinhood Chain, has its own rh_lighter_* channels with the same live shapes; see Lighter on Robinhood Chain.

Endpoint and access

Connect to wss://api.0xarchive.io/ws with the same server-side authentication as any other channel. See WebSocket connection. The stream.0xarchive.io endpoint does not carry Lighter channels: a Lighter subscribe there returns an error that names wss://api.0xarchive.io/ws. Every plan, including Free, can subscribe to the live Lighter channels. Each delivered message is metered like other WebSocket data; see Credits. For lighter_orderbook, each book sent is one metered message, so the interval you choose caps the order-book message rate. Your plan’s subscription and connection limits apply, and each connection accepts at most 10 subscribe operations per second. See WebSocket limits.

Subscribe

Use the Lighter symbols returned by GET /v1/lighter/instruments; Lighter REST covers that route and the current and historical reads. Symbols are case-insensitive on subscribe, and the acknowledgment returns the symbol as that route lists it, which is uppercase for markets such as BTC and ETH. Match data messages to subscriptions without regard to case. Keep Lighter subscriptions in the Lighter family even when the same symbol text is also a Hyperliquid market.
The server confirms each subscription before you should treat it as active:
To stop a stream, send unsubscribe with the same channel and symbol:
Sending subscribe again for a channel and symbol you already hold replaces that subscription. Use this to change interval_ms without unsubscribing first. The server sends a new subscribed acknowledgment. The subscription limit is checked before the replacement, so if the connection is already at its plan’s subscription limit, unsubscribe first, then subscribe with the new interval_ms. Live Lighter data arrives in the envelope type, channel, coin, symbol, and data, with type set to data. The data payload depends on the channel, as described below. Notices arrive as error messages; see Errors and lag notices.

lighter_orderbook

Each message is a full top-20 L2 book, not a diff. Replace your local book with every message instead of applying it as a change. This example is a real message shortened to three levels per side; live messages carry up to 20 levels per side.

Order-book rate and interval_ms

The server sends the newest book at most once per interval. The default interval is one book per second. To choose another rate, pass interval_ms on subscribe with a value from 100 to 5000, inclusive. When the book changes several times within one interval, only the newest book is sent, and a newer book is never replaced by an older one. The interval is a maximum rate, not a heartbeat. A book is sent only when Lighter publishes an update, so quiet markets send fewer books than the interval allows. On subscribe, the current book is sent immediately when one is available. An illiquid market can go minutes without a change, so the first book can stay current for a long time. interval_ms is accepted only on lighter_orderbook. See Errors and lag notices for the messages returned by an invalid value.

lighter_trades

Each message carries an array of fills. Every trade appears as two legs, one per side, with the same tid. This example is a real message with both legs of one trade:
Count trades by distinct tid, not by array length. Compute volume from sz on one leg per tid; adding both legs doubles it. Keep a record of tid values you have processed so a trade is counted once across messages.

Preliminary and finalized trades

Live trades are delivered as they happen and are preliminary. The finalized record, which adds fields the live stream does not carry, such as fees, is served by GET /v1/lighter/trades/{symbol}. That route returns only reconciled trades; meta.finalized_through reports how far reconciliation has reached. GET /v1/lighter/trades/{symbol}/recent serves the preliminary tier over REST. See Trades for both tiers.

lighter_open_interest and lighter_funding

Both channels carry the same market-context message. Subscribe to the channel name that fits your code. If you subscribe to both for one symbol, each update arrives on both channels and each message is metered. This example is a real message:
The current routes are GET /v1/lighter/openinterest/{symbol}/current and GET /v1/lighter/funding/{symbol}/current. Numeric values are decimal strings. Updates arrive as Lighter publishes them, about once per second per market. On subscribe, the latest values are sent immediately when they are available. The message has no timestamp field, so record the receive time if your application needs one.

Errors and lag notices

Rejected commands and stream notices arrive as error messages: {"type":"error","message":"...","error_code":"..."}. Branch on error_code and log the full message text. Lag notices and slow-connection stops carry slow_consumer, the interval_ms rejections carry invalid_parameter, a live subscribe to a replay-only channel carries unsupported_for_venue, and the full list is on Errors.
  • interval_ms on a channel other than lighter_orderbook: interval_ms is only supported on lighter_orderbook. Remove interval_ms from the subscribe command.
  • interval_ms outside 100 to 5000: interval_ms must be between 100 and 5000 for lighter_orderbook (got 50). Leave it out for one book a second. Send a value in range, or leave it out for the default.
  • Live subscribe to lighter_candles or lighter_l3_orderbook: An error stating that the channel does not support real-time subscriptions. Use REST for current reads and op: "replay" for history.
  • Lighter subscribe on stream.0xarchive.io: The 'lighter_trades' channel is not available on this endpoint. Subscribe to it on wss://api.0xarchive.io/ws. Subscribe on wss://api.0xarchive.io/ws.
  • The connection falls behind lighter_trades: Dropped ~N live lighter_trades messages for BTC: your connection fell behind the Lighter stream, and those trades were not delivered. The stream continues, but the dropped trades are not resent. Fill the gap from the REST trade routes.
  • The connection falls behind lighter_open_interest or lighter_funding: Dropped ~N live lighter_funding messages for BTC: your connection fell behind the Lighter stream. Each message is a full state, so the next one resyncs. No repair is needed; the next message is complete.
  • The connection stays behind on lighter_trades, lighter_open_interest, or lighter_funding: Stopped the lighter_trades stream for BTC: your connection is too slow to keep up. Re-subscribe to resume. That subscription sends nothing more. Reduce the subscription set or speed up processing, then subscribe again.
lighter_orderbook does not send drop notices for books skipped by its interval. Each book is a full state, so skipping an older book loses nothing, and a newer book is never replaced by an older one. Move message handling off the socket callback when processing is slow, and watch for these notices in the same place you watch reconnects and gaps. See WebSocket limits for consumer sizing.

Live and replay message shapes

Replay is available on all six Lighter channels, and op: "replay" returns historical_data rows in the stored Lighter shape, not the live shape above. Use separate parsers for live data messages and replay historical_data messages. Connect with version=2026-10-01 in the URL to receive replay rows in the live shapes instead, on both deployments and in multi-channel replay snapshots. Replayed trades then arrive as fill legs, one leg per stored row, and finalized rows fill fee and closed_pnl, which live legs leave null. See Versioning and the Protocol reference for the command and event contract.

Replay

A replay reads stored history for a bounded window and completes with replay_completed; it does not continue into the live stream. These examples run on any plan, including Free, whose history covers the most recent 30 days.
  • Trades: trade replay returns finalized trades only, the same record as GET /v1/lighter/trades/{symbol}. The window is cut off at meta.finalized_through, which trails the present by a day or more, so the trades example replays a window from three days ago.
  • Candles: candle replay sends one-hour bars unless you pass interval (1m, 5m, 15m, 30m, 1h, 4h, 1d, or 1w). The candles example asks for one-minute bars.
WebSocket replay covers replay controls, gap events, and run manifests.

Lighter on Robinhood Chain

Lighter has two deployments: mainnet and Robinhood Chain. The Robinhood Chain deployment has its own channel family, rh_lighter_*, next to the mainnet lighter_* channels above. Its markets are separate from mainnet even when the symbol text matches, so keep the two families apart in subscriptions, storage, and logs. Lighter on Robinhood Chain live subscriptions are available on rh_lighter_orderbook, rh_lighter_trades, rh_lighter_open_interest, and rh_lighter_funding through wss://api.0xarchive.io/ws. rh_lighter_candles is replay-only, and all five Robinhood Chain channels support historical replay. There is no L3 channel on this deployment. Use GET /v1/rh-lighter/orderbook/{symbol} for current depth. Use the symbols returned by GET /v1/rh-lighter/instruments. Perp symbols are uppercase, such as BTC; spot symbols are dashed with the USDG quote asset, such as AAPL-USDG. Spot markets have no open interest or funding.
The live payloads are identical to the mainnet Lighter live shapes documented above: rh_lighter_orderbook sends the same full top-20 book, rh_lighter_trades the same arrays of fill legs with two legs per tid, and rh_lighter_open_interest and rh_lighter_funding the same market-context message. Prices and quote volumes are in USDG, and users holds Robinhood Chain account indexes, which are unrelated to mainnet account indexes. Live trades are preliminary; GET /v1/rh-lighter/trades/{symbol} serves the finalized record with meta.finalized_through. rh_lighter_orderbook takes the same optional interval_ms, from 100 to 5000, with one book a second by default. Rejections and notices name the Robinhood Chain channel:
  • interval_ms on another Robinhood Chain channel: interval_ms is only supported on rh_lighter_orderbook.
  • interval_ms outside 100 to 5000: interval_ms must be between 100 and 5000 for rh_lighter_orderbook (got 50). Leave it out for one book a second.
  • Live subscribe to rh_lighter_candles: An error stating that the channel does not support real-time subscriptions.
  • Robinhood Chain subscribe on stream.0xarchive.io: The 'rh_lighter_trades' channel is not available on this endpoint. Subscribe to it on wss://api.0xarchive.io/ws.
  • The connection falls behind rh_lighter_trades: Dropped ~N live rh_lighter_trades messages for BTC: your connection fell behind the Lighter (Robinhood Chain) stream, and those trades were not delivered.
The stream.0xarchive.io endpoint does not carry Robinhood Chain channels either. The slow-consumer notices and the stop behavior are the same as on mainnet; see Errors and lag notices. Replay works as it does on mainnet and returns historical_data rows in the stored Lighter shape. Trade replay returns finalized trades only, up to meta.finalized_through, and candle replay takes the same optional interval. A multi-channel replay cannot mix rh_lighter_* channels with lighter_* channels, because each deployment is its own replay family.

Server-side example

Keep the API key on the server. This Node.js example subscribes to BTC books at two per second and to BTC trades, and counts each trade once:

Next step

Control a replay and record its run manifest with WebSocket replay.
Last modified on October 6, 2026