SDKs
Official Python, TypeScript, and Rust clients for REST, WebSocket, and order-book reconstruction.
Official clients for the core API in Python, TypeScript, and Rust.
Installation
Install the package for your runtime.
Python
Bash
pip install oxarchiveTypeScript / Node.js
Bash
npm install @0xarchive/sdkRust
Bash
cargo add oxarchiveREST usage
SDK method names stay close to the REST routes.
# pip install oxarchivefrom oxarchive import Client
client = Client(api_key="0xa_your_api_key")
# Hyperliquid datahl_orderbook = client.hyperliquid.orderbook.get("BTC")print(f"Hyperliquid BTC mid price: {hl_orderbook.mid_price}")
# Lighter.xyz datalighter_orderbook = client.lighter.orderbook.get("BTC")print(f"Lighter BTC mid price: {lighter_orderbook.mid_price}")
# HIP-3 builder perpship3_ob = client.hyperliquid.hip3.orderbook.get("xyz:XYZ100")print(f"HIP-3 XYZ100 mid price: {hip3_ob.mid_price}")
hip3_trades = client.hyperliquid.hip3.trades.recent("xyz:XYZ100", limit=10)print(f"Recent HIP-3 trades: {len(hip3_trades)}")
# Get trades with cursor paginationresult = client.hyperliquid.trades.list("ETH", start="2026-01-01", end="2026-01-02", limit=1000)trades = result.data
# Continue fetching all pageswhile result.next_cursor: result = client.hyperliquid.trades.list( "ETH", start="2026-01-01", end="2026-01-02", cursor=result.next_cursor, limit=1000 ) trades.extend(result.data)WebSocket usage
The same client handles live subscriptions and replay.
import asynciofrom oxarchive import OxArchiveWs, WsOptions
async def main(): ws = OxArchiveWs(WsOptions(api_key="0xa_your_api_key"))
# Subscribe to real-time data ws.on_orderbook(lambda coin, data: print(f"{coin}: {data.mid_price}"))
await ws.connect() ws.subscribe_orderbook("BTC")
# Or replay historical data await ws.replay("orderbook", "BTC", start=1704067200000, speed=10)
asyncio.run(main())Order book reconstruction
Reconstruct Hyperliquid and HIP-3 L4/L2 books server-side or client-side. Lighter uses checkpoints and deltas.
Server-side reconstruction (Hyperliquid / HIP-3)
- Tier
- Pro+ (L4) / Build+ (L2)
- For
- Point-in-time L4 or L2 snapshots
- Recommended
- One API call, server handles matching engine
# Server-side L4 reconstruction (Pro+ tier)# The server handles the matching engine — just pass a timestamp.from oxarchive import Client
client = Client(api_key="0xa_your_api_key")
# Hyperliquid: get L4 orderbook at a specific point in timel4 = client.hyperliquid.l4_orderbook.get("BTC", timestamp=1711900800000)print(f"BTC L4: {l4['bid_count']} bids, {l4['ask_count']} asks")print(f"Best bid: {l4['bids'][0]['price']}, Best ask: {l4['asks'][0]['price']}")
# HIP-3: same method, same response formathip3_l4 = client.hyperliquid.hip3.l4_orderbook.get("xyz:CL", timestamp=1711900800000)print(f"Crude Oil L4: {hip3_l4['bid_count']} bids, {hip3_l4['ask_count']} asks")
# Omit timestamp for current live state (from Redis, sub-second)live = client.hyperliquid.l4_orderbook.get("BTC")
# L2 full-depth (aggregated from L4, Build+ tier)l2 = client.hyperliquid.l2_orderbook.get("BTC", timestamp=1711900800000)print(f"BTC L2: {l2['bid_levels']} bid levels, {l2['ask_levels']} ask levels")print(f"Best bid: {l2['bids'][0]['px']} ({l2['bids'][0]['n']} orders)")| Endpoint | Tier | Returns |
|---|---|---|
/orderbook/:symbol/l4 | Pro+ | L4 order-level book: individual orders with OID, wallet, price, size. |
/orderbook/:symbol/l2 | Build+ | L2 full-depth book: aggregated price levels with total size and order count. |
Client-side L4/L2 reconstruction (Hyperliquid / HIP-3)
- Tier
- Pro+
- For
- Time-series iteration, backtesting, custom analysis
- Exchanges
- Same method for both Hyperliquid and HIP-3
# Client-side L4 reconstruction with matching engine (Pro+ tier)# Same approach for Hyperliquid and HIP-3 — identical diff format.from oxarchive import Client, L4OrderBookReconstructorfrom collections import defaultdict
client = Client(api_key="0xa_your_api_key")start, end = 1711900800000, 1711901100000 # 5-minute window
# 1. Fetch nearest L4 checkpointcheckpoints = client.hyperliquid.l4_orderbook.history("BTC", start=start-1800000, end=start)checkpoint = checkpoints.data[-1] # nearest before target
# 2. Fetch L4 diffs from checkpoint to targetdiffs = client.hyperliquid.l4_orderbook.diffs("BTC", start=start, end=end)
# 3. Fetch order statuses for non-resting filter (optional, improves accuracy)statuses = client.hyperliquid.orders.history("BTC", start=start, end=end)non_resting = defaultdict(set)for s in statuses.data: if s["status"] != "open": non_resting[s["block_number"]].add(s["oid"])
# 4. Reconstruct with matching enginebook = L4OrderBookReconstructor()book.load_checkpoint(checkpoint)
# Group diffs by block, apply in orderblocks = defaultdict(list)for d in diffs.data: blocks[d["block_number"]].append(d)
for bn in sorted(blocks): nr = non_resting.get(bn) for diff in blocks[bn]: book.apply_diff(diff, nr)
# 5. Result: non-crossed L4 orderbookassert not book.is_crossed(), "Book should not be crossed"print(f"Best bid: {book.best_bid()}, Best ask: {book.best_ask()}")print(f"Orders: {len(book.bids())} bids, {len(book.asks())} asks")
# 6. Derive L2 from L4 (aggregate by price level)l2_bids, l2_asks = book.derive_l2()print(f"L2 levels: {len(l2_bids)} bid, {len(l2_asks)} ask")| Method | Best use | Notes |
|---|---|---|
L4OrderBookReconstructor | Core reconstruction class | Matching engine built in. Handles crossing orders and non-resting filter. |
loadCheckpoint() / applyDiff() | Step through time | Initialize from checkpoint, then apply diffs block-by-block. |
deriveL2() | L2 from L4 | Aggregate L4 orders by price level (sum sizes, count orders per level). |
isCrossed() | Validation | Should always return false after correct reconstruction. |
Lighter tick reconstruction
- Tier
- Enterprise
- For
- Tick-level Lighter order book history
- Preferred path
- Auto-paginating iterator
# Orderbook Reconstruction (Enterprise tier only)from oxarchive import Client, OrderBookReconstructor
client = Client(api_key="0xa_your_api_key")
# Option 1: Auto-paginating iterator (recommended for large time ranges)# Automatically handles pagination, fetching up to 1,000 deltas per requestfor snapshot in client.lighter.orderbook.iterate_tick_history( "BTC", start="2026-01-01T00:00:00Z", end="2026-01-01T12:00:00Z" # 12 hours of data): print(f"{snapshot.timestamp}: mid={snapshot.mid_price}") if some_condition: break # Early exit supported
# Option 2: Get fully reconstructed snapshots (single page)snapshots = client.lighter.orderbook.history_reconstructed( "BTC", start="2026-01-01T00:00:00Z", end="2026-01-01T01:00:00Z")for ob in snapshots: print(f"{ob.timestamp}: bid={ob.bids[0].px} ask={ob.asks[0].px}")
# Option 3: Get raw tick data for custom reconstructiontick_data = client.lighter.orderbook.history_tick("BTC", start=start, end=end)print(f"Checkpoint: {len(tick_data.checkpoint.bids)} bids")print(f"Deltas: {len(tick_data.deltas)} updates")
# Check for sequence gapsgaps = OrderBookReconstructor.detect_gaps(tick_data.deltas)if gaps: print("Gaps detected:", gaps)| Method | Best use | Notes |
|---|---|---|
iterateTickHistory() | Long windows and production replay | Auto-paginates and handles large delta ranges cleanly. |
historyTick() | Raw checkpoints and deltas | Single page, maximum 1,000 deltas. |
historyReconstructed() | Direct reconstructed snapshots | Single page when you need the finished book immediately. |
detectGaps() | Continuity checks | Use before backtests or downstream reconstruction pipelines. |
Published packages
Registry links and source repos for the published packages.