@0xarchive/sdk
v1.13.0
Published
TypeScript SDK for the 0xArchive market data API for Hyperliquid (perps, HIP-3, HIP-4, spot) and Lighter (mainnet and Robinhood Chain), including account positions
Maintainers
Readme
@0xarchive/sdk
TypeScript client for 0xArchive market data in Node services, dashboards, coding-agent workflows, and agent backends.
0xArchive is granular market data infrastructure for two venues: Hyperliquid and Lighter. Hyperliquid includes core perps (/v1/hyperliquid), HIP-3 builder perps (/v1/hyperliquid/hip3), HIP-4 outcome markets (/v1/hyperliquid/hip4), and Hyperliquid Spot (/v1/hyperliquid/spot). Lighter has two deployments: mainnet (/v1/lighter) and Robinhood Chain (/v1/rh-lighter). In this SDK these map to client.hyperliquid, client.hyperliquid.hip3, client.hyperliquid.hip4, client.spot, client.lighter, and client.rhLighter. Account positions are available on client.hyperliquid, client.hyperliquid.hip3, client.lighter, and client.rhLighter.
Use this SDK when the integration belongs in TypeScript or JavaScript code and you want typed REST helpers, WebSocket support, replay workflows, webhook management with signature verification, and order-book reconstruction utilities.
Installation
npm install @0xarchive/sdk
# or
yarn add @0xarchive/sdk
# or
pnpm add @0xarchive/sdkQuick Start
import { OxArchive } from '@0xarchive/sdk';
const client = new OxArchive({ apiKey: '0xa_your_api_key' });
// First successful call: Hyperliquid BTC order book
const hlOrderbook = await client.hyperliquid.orderbook.get('BTC');
console.log(`Hyperliquid BTC mid price: ${hlOrderbook.midPrice}`);
// Lighter uses its own venue client
const lighterOrderbook = await client.lighter.orderbook.get('BTC');
console.log(`Lighter BTC mid price: ${lighterOrderbook.midPrice}`);
// Lighter on Robinhood Chain is the second Lighter deployment (USDG-quoted)
const rhOrderbook = await client.rhLighter.orderbook.get('BTC');
const rhSpotTrades = await client.rhLighter.trades.recent('AAPL-USDG');
// Account positions: a wallet's live positions, with snapshot context in meta
const { data: wallet, meta } = await client.hyperliquid.positions.get('0x1234...');
console.log(`${wallet.positions.length} positions as of ${meta.asOf}`);
// Hyperliquid HIP-3 builder perps stay under client.hyperliquid.hip3
const hip3Instruments = await client.hyperliquid.hip3.instruments.list();
const hip3Orderbook = await client.hyperliquid.hip3.orderbook.get('xyz:SP500');
const hip3Trades = await client.hyperliquid.hip3.trades.recent('xyz:SP500');
const hip3Funding = await client.hyperliquid.hip3.funding.current('xyz:XYZ100');
const hip3Oi = await client.hyperliquid.hip3.openInterest.current('xyz:XYZ100');
// Hyperliquid Spot lives at client.spot. Symbols are dashed canonical (HYPE-USDC).
const spotPairs = await client.spot.pairs.list();
const spotOrderbook = await client.spot.orderbook.get('HYPE-USDC');
const spotTrades = await client.spot.trades.recent('HYPE-USDC');
const spotCandles = await client.spot.candles.history('HYPE-USDC', {
start: Date.now() - 7 * 86400000, // the last 7 days
end: Date.now(),
interval: '1h',
});
// Get historical order book snapshots
const history = await client.hyperliquid.orderbook.history('ETH', {
start: Date.now() - 86400000, // 24 hours ago
end: Date.now(),
limit: 100
});Choose Your Next Path
| Need | Link | | --- | --- | | First authenticated route | Quick Start | | SDK install and route docs | SDK docs | | Claude Code, ChatGPT Codex, and coding-agent workflows | AI Clients | | Example notebooks | Examples | | File-based historical pulls | Data Catalog | | Route contract and machine context | OpenAPI, llms.txt |
Data Coverage
Dates are the first served instant of each dataset, as client.capabilities() reports it (UTC). Starts can be later for individual markets.
| Venue | Coverage | Notes |
| --- | --- | --- |
| Hyperliquid | Order book from 2023-04-15; trades from 2023-04-15 03:31; funding, open interest, and prices from 2023-05-20 02:50; candles from 2025-03-22 12:00; liquidations from 2025-12-22; L4, full-depth L2, and order history from 2026-03-11 01:03 | Core perpetual markets. |
| Hyperliquid HIP-3 | Trades from 2025-10-13 12:24; oracle prices from 2025-10-13 12:12; candles and liquidations from 2025-12-22; order book from 2026-02-16 16:57; funding and OI from 2026-02-16 17:03; L4, full-depth L2, and order history from 2026-03-11 01:03 | Builder perps; funding and OI update at roughly 10 seconds. Candle history accepts up to 10,000 rows per request. |
| Hyperliquid HIP-4 | L4 and order history from 2026-05-02 07:47; trades and candles from 2026-05-02 08:00; order book, open interest, and prices from 2026-05-02 16:51 | Outcome markets. OI updates at about 10 seconds. No funding or liquidations. |
| Hyperliquid Spot | Candles from 2025-03-22 10:50; trades from 2025-03-22 10:50:22; TWAP from 2026-05-05 13:05; order book from 2026-05-05 19:56; L4 from 2026-05-05 22:57 (PURR-USDC from 2026-03-11 01:03), with REST order history reaching back further | Pairs use dashed symbols (HYPE-USDC, PURR-USDC); client.spot.pairs.list() returns the current set. Candle intervals are 1m/5m/15m/30m/1h/4h/1d/1w with max limit 1000 and numeric-string cursors passed through unchanged. No funding, OI, or liquidations. |
| Lighter (mainnet) | Trades from 2025-01-17 08:43; candles from 2025-08-01; funding, OI, and prices from 2025-08-25 15:28; order book from 2026-01-29 02:13; L3 order book from 2026-03-05 03:33; liquidations from 2026-06-10 | Perpetuals. Fills carry maker/taker context where served; L3 is capped at 250 orders per side and funding/OI update at approximately 10s. |
| Lighter (Robinhood Chain) | Trades and liquidations from 2026-06-26 20:10:26 (launch); candles from 2026-06-26 20:10; order book, open interest, and funding from 2026-08-22 18:43 | The second Lighter deployment, quoted in USDG: perpetuals such as BTC and spot markets such as AAPL-USDG; client.rhLighter.instruments.list() returns the current set. No L3 order book. Funding and OI are perpetuals only. |
Account positions coverage: Hyperliquid core position changes from 2025-05-25 and HIP-3 from 2025-10-13, hourly snapshots from 2026-06-07, and a live snapshot about every 5 minutes. Lighter mainnet from 2025-01-17 and Lighter on Robinhood Chain from 2026-06-26, with hourly snapshots over the whole history and a live snapshot about every 2 minutes.
For the first served instant of every venue and datatype, and which WebSocket channels stream live and replay, call client.capabilities().
Configuration
const client = new OxArchive({
apiKey: '0xa_your_api_key', // Required
baseUrl: 'https://api.0xarchive.io', // Optional
timeout: 30000, // Optional, request timeout in ms (default: 30000)
validate: false, // Optional, enable Zod schema validation
});API version
The SDK is built against the dated API contract 2026-10-01. Every REST request sends the header 0xArchive-Version: 2026-10-01, and OxArchiveWs connects with version=2026-10-01. You do not set either; they are exported as API_VERSION and API_VERSION_HEADER for reference. Under this version:
- Every successful response is
{ success, data, meta }, including data quality and/v1/symbols. The SDK returnsdata(andmetaon paged methods). - Failed requests carry a stable
error_code, surfaced asOxArchiveError.errorCode. See Error Handling. - Paged routes set
meta.hasMorebesidemeta.nextCursor. See Pagination. - Record times are RFC 3339 UTC strings; integer milliseconds appear only in fields ending
Ms. See Timestamp Formats. - Lighter and Robinhood Chain WebSocket replay rows use the same shapes as live messages.
Method names
Resources use four verbs: get for a point-in-time read, current for the latest value, history for a paged series, and list for a catalog. Where a resource used another name first, the older name stays and the verb is added beside it:
| Series | Name | Same call |
| --- | --- | --- |
| Trades | trades.history(symbol, params) | trades.list(symbol, params) |
| Spot TWAP by pair | spot.twap.history(symbol, params) | spot.twap.bySymbol(symbol, params) |
Pagination
Paged methods return { data, nextCursor, hasMore, meta }. Keep paging while hasMore is true: pass nextCursor back unchanged as cursor, with the same start, end and filters. hasMore is false on the last page, which can be empty when the previous page was exactly full. Cursors are opaque strings; do not parse or build them.
const window = { start: Date.now() - 3_600_000, end: Date.now(), limit: 1000 };
let page = await client.hyperliquid.trades.history('BTC', window);
const trades = [...page.data];
while (page.hasMore) {
page = await client.hyperliquid.trades.history('BTC', { ...window, cursor: page.nextCursor });
trades.push(...page.data);
}
console.log(page.meta?.symbol, page.meta?.venue); // 'BTC', 'hyperliquid'On per-symbol routes, the meta a paged method returns also carries the canonical public symbol and its venue as meta.symbol and meta.venue (hyperliquid, hip3, hip4, spot, lighter or rh-lighter). Point-in-time methods such as orderbook.get() return the record itself. The cursor-following iterators on account positions (iterateHistory(), iterateChanges() and the others) stop when hasMore is false.
Capabilities
client.capabilities() returns what each venue serves, one row per venue and datatype (GET /v1/capabilities, public, no credits): the REST routes, the WebSocket channels and whether they stream live and replay, the first served instant, cadence, page limit and accepted intervals.
const rows = await client.capabilities();
const hip3Trades = rows.find((r) => r.venue === 'hip3' && r.datatype === 'trades');
console.log(hip3Trades?.availableFrom, hip3Trades?.pageLimit, hip3Trades?.restRoutes);
// Channels that replay, and those replayed in bulk (L4 and full depth)
const replayable = rows.filter((r) => r.replay).flatMap((r) => r.wsChannels);The WebSocket client checks channels against WS_CHANNEL_CAPABILITIES, a table that mirrors this endpoint, so a live subscription or replay the API does not offer is refused before it is sent.
REST API Reference
Core resources (orderbook, trades, instruments, funding, openInterest, candles, freshness, summary, priceHistory) are exposed on the venue and family clients where the route is supported. Hyperliquid core, HIP-3, HIP-4, Spot, and the two Lighter deployments have different resource subsets; see each section for details. client.rhLighter has the same resources as client.lighter except the L3 order book and the L1 account lookup; see Lighter on Robinhood Chain.
Order Book
// Get current order book (Hyperliquid)
const orderbook = await client.hyperliquid.orderbook.get('BTC');
// Get current order book (Lighter)
const lighterOb = await client.lighter.orderbook.get('BTC');
// Get order book at specific timestamp with custom depth
const historical = await client.hyperliquid.orderbook.get('BTC', {
timestamp: Date.now() - 3600000, // one hour ago
depth: 20 // Number of levels per side
});
// Get historical snapshots (start is required)
const history = await client.hyperliquid.orderbook.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 1000
});
// History with the best 5 levels per side (every venue)
const top5 = await client.hyperliquid.hip3.orderbook.history('xyz:SP500', {
start: Date.now() - 3600000,
end: Date.now(),
depth: 5
});Orderbook Depth
The depth parameter controls how many price levels are returned per side, on current and historical snapshots on every venue (Hyperliquid core, HIP-3, HIP-4, Spot and Lighter) and on full-depth L2 history. Depth limits are route-specific.
Note: Hyperliquid native L2 source data contains ~20 levels. Dedicated L2 routes derived from L4 can return all available levels where supported. Lighter L3 is individual order-level data capped at 250 orders per side, not an unlimited full-depth book. Depth limits apply to L2 snapshot endpoints only; L4 and L2 diff endpoints return full data.
Lighter Orderbook Granularity
Lighter orderbook history supports a granularity parameter for different data resolutions.
| Granularity | Interval | Credit Multiplier |
|-------------|----------|-------------------|
| checkpoint | ~60s | 1x |
| 30s | 30s | 2x |
| 10s | 10s | 3x |
| 1s | 1s | 10x |
| tick | tick-level | 20x |
// Get Lighter orderbook history with 10s resolution
const history = await client.lighter.orderbook.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
granularity: '10s'
});
// Get 1-second resolution
const history = await client.lighter.orderbook.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
granularity: '1s'
});
// Tick-level data - returns checkpoint + raw deltas
const history = await client.lighter.orderbook.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
granularity: 'tick'
});Note: The granularity parameter is ignored for Hyperliquid orderbook history.
Orderbook Reconstruction
For tick-level data, the SDK provides client-side orderbook reconstruction. This efficiently reconstructs full orderbook state from a checkpoint and incremental deltas.
import { OrderBookReconstructor } from '@0xarchive/sdk';
// Option 1: Get fully reconstructed snapshots (simplest)
const snapshots = await client.lighter.orderbook.historyReconstructed('BTC', {
start: Date.now() - 3600000,
end: Date.now()
});
for (const ob of snapshots) {
console.log(`${ob.timestamp}: bid=${ob.bids[0]?.px} ask=${ob.asks[0]?.px}`);
}
// Option 2: Get raw tick data for custom reconstruction
const tickData = await client.lighter.orderbook.historyTick('BTC', {
start: Date.now() - 3600000,
end: Date.now()
});
console.log(`Checkpoint: ${tickData.checkpoint.bids.length} bids`);
console.log(`Deltas: ${tickData.deltas.length} updates`);
// Option 3: Auto-paginating iterator (recommended for large time ranges)
// Automatically handles pagination, fetching up to 1,000 deltas per request
for await (const snapshot of client.lighter.orderbook.iterateTickHistory('BTC', {
start: Date.now() - 86400000, // 24 hours of data
end: Date.now()
})) {
console.log(snapshot.timestamp, 'Mid:', snapshot.midPrice);
if (someCondition(snapshot)) break; // Early exit supported
}
// Option 4: Manual iteration (single page, for custom logic)
const reconstructor = client.lighter.orderbook.createReconstructor();
for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas)) {
// Process each snapshot without loading all into memory
if (someCondition(snapshot)) break; // Early exit if needed
}
// Option 5: Get only final state (most efficient)
const final = reconstructor.reconstructFinal(tickData.checkpoint, tickData.deltas);
// Check for sequence gaps
const gaps = OrderBookReconstructor.detectGaps(tickData.deltas);
if (gaps.length > 0) {
console.warn('Sequence gaps detected:', gaps);
}Methods:
| Method | Description |
|--------|-------------|
| historyTick(coin, params) | Get raw checkpoint + deltas (single page, max 1,000 deltas) |
| historyReconstructed(coin, params, options) | Get fully reconstructed snapshots (single page) |
| iterateTickHistory(coin, params, depth?) | Auto-paginating async iterator for large time ranges |
| createReconstructor() | Create a reconstructor instance for manual control |
Note: The API returns a maximum of 1,000 deltas per request. For time ranges with more deltas, use iterateTickHistory() which handles pagination automatically.
ReconstructOptions:
| Option | Default | Description |
|--------|---------|-------------|
| depth | all | Maximum price levels in output |
| emitAll | true | If false, only return final state |
Trades
The trades API uses cursor-based pagination for efficient retrieval of large datasets. trades.history() and trades.list() are the same call.
// Get trade history with cursor-based pagination
const window = { start: Date.now() - 86400000, end: Date.now(), limit: 1000 };
let result = await client.hyperliquid.trades.history('BTC', window);
// Paginate through all results
const allTrades = [...result.data];
while (result.hasMore) {
result = await client.hyperliquid.trades.history('BTC', { ...window, cursor: result.nextCursor });
allTrades.push(...result.data);
}
// Only taker buys ('buy') or taker sells ('sell'), on every venue
const buys = await client.hyperliquid.trades.history('BTC', { ...window, side: 'buy' });
// Get recent trades (venues with real-time data)
const recent = await client.lighter.trades.recent('BTC', 100);
const recentSells = await client.hyperliquid.hip3.trades.recent('xyz:SP500', { limit: 100, side: 'sell' });side filters on the server, so a full page still holds limit matching trades and the cursor pages the filtered tape; send the same side on every page. 'buy' keeps trades whose taker bought (side: 'B'), 'sell' those whose taker sold (side: 'A').
Note: The recent() method is available for Lighter (client.lighter.trades.recent(), client.rhLighter.trades.recent()), HIP-3 (client.hyperliquid.hip3.trades.recent()), HIP-4 (client.hyperliquid.hip4.trades.recent() / getTradesRecent()), and Spot (client.spot.trades.recent()). Hyperliquid core has no recent-trades route: read its latest trades with history() over a recent window, or stream them live on the trades WebSocket channel. Calling client.hyperliquid.trades.recent() throws an OxArchiveError with errorCode route_not_found.
Lighter trades are fill-grain: describe the returned records as per fill · maker + taker where that context is served. Do not describe them as every order, a complete order history, or an unlimited trade archive.
On both Lighter deployments, trades.history() serves reconciled trades only. The window is clamped to the finalization boundary, about a day behind, which it returns as meta.finalizedThrough; when the requested end was past it, meta.clampedTo and meta.requestedEnd show the clamp. trades.recent() serves the preliminary tier for the latest trades.
const page = await client.rhLighter.trades.history('BTC', { start: Date.now() - 2 * 86400000, end: Date.now() });
console.log(`final through ${page.meta?.finalizedThrough}`);
if (page.meta?.clampedTo) {
console.log(`clamped from ${page.meta.requestedEnd} to ${page.meta.clampedTo}`);
}Instruments
// List all trading instruments (Hyperliquid)
const instruments = await client.hyperliquid.instruments.list();
// Get specific instrument details
const btc = await client.hyperliquid.instruments.get('BTC');
console.log(`BTC size decimals: ${btc.szDecimals}`);Lighter Instruments
Lighter instruments have a different schema with additional fields for fees, market IDs, and minimum order amounts:
// List Lighter instruments (returns LighterInstrument, not Instrument)
const lighterInstruments = await client.lighter.instruments.list();
// Get specific Lighter instrument
const eth = await client.lighter.instruments.get('ETH');
console.log(`ETH taker fee: ${eth.takerFee}`);
console.log(`ETH maker fee: ${eth.makerFee}`);
console.log(`ETH market ID: ${eth.marketId}`);
console.log(`ETH min base amount: ${eth.minBaseAmount}`);Key differences:
| Field | Hyperliquid (Instrument) | Lighter (LighterInstrument) |
|-------|---------------------------|------------------------------|
| Symbol | name | symbol |
| Size decimals | szDecimals | sizeDecimals |
| Fee info | Not available | takerFee, makerFee, liquidationFee |
| Market ID | Not available | marketId |
| Min amounts | Not available | minBaseAmount, minQuoteAmount |
HIP-3 Instruments
HIP-3 instruments are derived from live market data and include mark price, open interest, and mid price:
// List all HIP-3 instruments
const hip3Instruments = await client.hyperliquid.hip3.instruments.list();
for (const inst of hip3Instruments) {
console.log(`${inst.coin} (${inst.namespace}:${inst.ticker}): mark=${inst.markPrice}, OI=${inst.openInterest}`);
}
// Get specific HIP-3 instrument (case-sensitive)
const sp500 = await client.hyperliquid.hip3.instruments.get('xyz:SP500');
console.log(`Mark price: ${sp500.markPrice}`);HIP-3 coins: builders list and delist markets over time, so this README does not pin a list. Call client.hyperliquid.hip3.instruments.list() for the current set. Coin names are case-sensitive and carry the builder prefix (xyz:XYZ100, xyz:SP500).
HIP-3 Market Breadth
HIP-3 breadth reports the percentage of eligible instruments trading above
their current UTC-session VWAP. History begins on 2026-08-28 and is
aggregate-only; there is no synthetic pre-launch history. Instruments with no
session volume or a stale last completed candle are excluded, so coverage can
change overnight and on weekends. Percentages should not be averaged across
snapshots; interval uses the last snapshot in each bucket.
const breadthNow = await client.hyperliquid.hip3.breadth.current();
const coreBreadthNow = await client.hyperliquid.breadth.current(); // core perps, same shape
const breadthHistory = await client.hyperliquid.hip3.breadth.history({
start: Date.now() - 86400000, // the last 24 hours
end: Date.now(),
interval: '5m',
});
// valuePct is null when no instruments are eligible, not 0.
console.log(breadthNow.valuePct, breadthHistory.nextCursor);HIP-3 Oracle
client.hyperliquid.hip3.oracle reads a builder market's oracle state. externalPrice() returns the latest deployer-pushed external reference price with the mark price; either can be null when not available. discoveryBounds() returns the instantaneous discovery bounds: the reference price (the external price when available, otherwise the mark price, named in referenceSource), the market's max leverage, the fraction applied on each side, and the resulting lower and upper bounds. The full ratcheted range can be wider when deployer-specific reset configuration applies. Both carry the source blockNumber, timestamp (RFC 3339 UTC) and timestampMs (Unix milliseconds).
const px = await client.hyperliquid.hip3.oracle.externalPrice('xyz:SP500');
console.log(px.externalPrice, px.markPrice, px.blockNumber);
const bounds = await client.hyperliquid.hip3.oracle.discoveryBounds('xyz:SP500');
console.log(`${bounds.lowerBound} to ${bounds.upperBound} around ${bounds.referencePrice} (${bounds.referenceSource})`);HIP-4 Outcome Markets
HIP-4 is Hyperliquid's binary outcome-market namespace. Each outcome has 2 sides, and each side is its own coin: # followed by 10 times the outcome id plus the side, so outcome 8226 trades as #82260 (Yes, side 0) and #82261 (No, side 1). Markets are fully collateralized so there are no funding rates or liquidations. Candle history is served from 2026-05-02 08:00 UTC and outcome-side open interest from 2026-05-02 16:51 UTC; OI updates at about 10 seconds. mark_price, midPrice, and candle OHLC values are implied probabilities in [0, 1], not USD prices.
Outcomes settle and new ones are listed every day, so look up a current coin before reading market data; a settled outcome no longer has a live book.
Path encoding: the backend accepts both the bare numeric form ('82260') and the on-chain #-prefixed form ('#82260'). The bare numeric form is the documented primary path. The SDK URL-encodes the # form on the wire (# becomes %23) so it survives fetch parsing; both forms remain accepted.
// Per-side instruments (one row per side coin, settled ones included)
const sides = await client.hyperliquid.hip4.instruments.list();
// An open daily BTC price outcome, Yes side
const yes = sides.find((s) => !s.isSettled && s.side === 0 && s.slug?.startsWith('btc-above-'));
if (!yes) throw new Error('no open BTC outcome right now');
console.log(`${yes.symbol} (outcome ${yes.outcomeId}): ${yes.displayTitle}`);
const coin = yes.symbol.replace('#', ''); // bare numeric form, e.g. '82260'
// Per-outcome aggregates (one row per outcome), cursor paged
const outcomes = await client.hyperliquid.hip4.listOutcomes({ isSettled: false, limit: 50 });
for (const o of outcomes.data) {
console.log(`outcome ${o.outcomeId}: ${o.displayTitle}, sides ${o.sideSpecs?.map((s) => s.coin).join(' / ')}`);
}
// Detail (includes aggregatedOi)
const detail = await client.hyperliquid.hip4.getOutcome(yes.outcomeId);
console.log(detail.aggregatedOi?.outcomeDisplayOpenInterestContracts);
// Slug-based lookup (per-outcome OR per-side slug)
const bySlug = await client.hyperliquid.hip4.getOutcomeBySlug(yes.slug!);
// Slug filter on listOutcomes
const filtered = await client.hyperliquid.hip4.listOutcomes({ slug: yes.slug });
// Questions: a question groups binary outcomes under one ballot, with one
// named outcome per choice plus a fallback outcome that resolves Yes when no
// named choice does. Page with nextCursor.
const questions = await client.hyperliquid.hip4.questions.list({ limit: 100 });
const question = await client.hyperliquid.hip4.questions.get(questions.data[0].questionId);
console.log(question.namedOutcomeIds, question.fallbackOutcomeId, question.settledNamedOutcomes);
// Orderbook. Bare numeric form is recommended.
const ob = await client.hyperliquid.hip4.getOrderbook(coin);
// ob.midPrice is a probability in [0, 1]: the implied probability of Yes.
// Trades, OI, and prices
const trades = await client.hyperliquid.hip4.getTradesRecent(coin, 50);
const oiNow = await client.hyperliquid.hip4.getOpenInterestCurrent(coin);
const prices = await client.hyperliquid.hip4.getPrices(coin, {
start: Date.now() - 3600000,
end: Date.now(),
});
// Candle history (OHLC values are probabilities)
const candles = await client.hyperliquid.hip4.candles.history(coin, {
start: Date.now() - 3600000,
end: Date.now(),
interval: '1m',
});
// Convenience
const summary = await client.hyperliquid.hip4.getSummary(coin);
const fresh = await client.hyperliquid.hip4.getFreshness(coin);
// L4
const l4 = await client.hyperliquid.hip4.getL4Orderbook(coin);
const orders = await client.hyperliquid.hip4.getOrderHistory(coin, {
start: Date.now() - 3600000,
end: Date.now(),
});No HIP-4 funding or liquidations. HIP-4 candles and outcome-side open interest are available through the routes documented above; the SDK intentionally does not expose a HIP-4 funding resource.
Hyperliquid Spot
Spot pairs live at /v1/hyperliquid/spot and client.spot. Symbols are dashed canonical (HYPE-USDC, PURR-USDC); the server resolves the dashed form to Hyperliquid's wire formats (PURR/USDC, @107) internally.
Spot has no funding, open interest, or liquidations. Candle history is served
through GET /v1/hyperliquid/spot/candles/{symbol} and
client.spot.candles.history(), with coverage from 2025-03-22 10:50 UTC.
The candle route accepts 1m, 5m, 15m, 30m, 1h, 4h, 1d, and 1w,
with a maximum limit of 1000 and numeric-string pagination cursors that
callers should pass through unchanged.
// Pairs (one row per dashed symbol)
const pairs = await client.spot.pairs.list();
const hype = await client.spot.pairs.get('HYPE-USDC');
console.log(`${hype.symbol}: mark=${hype.markPrice}, mid=${hype.midPrice}`);
// Orderbook (history from 2026-05-05 19:56 UTC)
const ob = await client.spot.orderbook.get('HYPE-USDC');
console.log(`${ob.coin} mid: ${ob.midPrice}`);
// Orderbook history
const obHistory = await client.spot.orderbook.history('HYPE-USDC', {
start: Date.now() - 3600000,
end: Date.now(),
limit: 100,
});
// Trade history (from 2025-03-22 10:50:22 UTC)
const trades = await client.spot.trades.list('HYPE-USDC', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 1000,
});
// Recent trades (real-time)
const recent = await client.spot.trades.recent('HYPE-USDC', 100);
// Candle history (served from 2025-03-22 10:50 UTC)
const candles = await client.spot.candles.history('HYPE-USDC', {
start: Date.now() - 7 * 86400000,
end: Date.now(),
interval: '1h',
limit: 1000,
});
// L4 reconstruction (from 2026-05-05 22:57 UTC; PURR-USDC from 2026-03-11 01:03 UTC)
const l4 = await client.spot.l4Orderbook.get('HYPE-USDC');
const diffs = await client.spot.l4Orderbook.diffs('HYPE-USDC', {
start: Date.now() - 3600000,
end: Date.now(),
});
// Order lifecycle events
const orders = await client.spot.orders.history('HYPE-USDC', {
start: Date.now() - 86400000,
end: Date.now(),
});
// TWAP statuses by symbol or by user wallet
const bySymbol = await client.spot.twap.bySymbol('HYPE-USDC', {
start: Date.now() - 86400000,
end: Date.now(),
});
const byUser = await client.spot.twap.byUser('0xabc...', {
start: Date.now() - 86400000,
end: Date.now(),
});
// Per-symbol freshness across all spot data types
const fresh = await client.spot.freshness('HYPE-USDC');
console.log(`Orderbook last updated: ${fresh.orderbook.lastUpdated}`);Coverage. Spot candle history is served from 2025-03-22 10:50 UTC through
GET /v1/hyperliquid/spot/candles/{symbol}. The route supports 1m, 5m, 15m, 30m, 1h, 4h, 1d, and 1w intervals, up to 1000 rows per request; numeric-string cursors should be passed back unchanged. Spot trades are served from 2025-03-22 10:50:22 UTC, the earliest spot fills Hyperliquid has published; the archive has no earlier spot trades. Hyperliquid does not publish historical spot order books, so Spot order book, L4, and TWAP history starts when capture began: TWAP from 2026-05-05 13:05 UTC, order book from 2026-05-05 19:56 UTC, and L4 from 2026-05-05 22:57 UTC (PURR-USDC from 2026-03-11 01:03 UTC). REST order history reaches back further for every pair. Spot TWAP statuses are served over REST only (client.spot.twap).
Funding Rates
For Lighter, funding_rate and the SDK's fundingRate are fractional and
non-annualized. Consumers that compensated for the former percent units must
update their conversion.
// Get current funding rate
const current = await client.hyperliquid.funding.current('BTC');
// Get funding rate history (start is required)
const history = await client.hyperliquid.funding.history('ETH', {
start: Date.now() - 86400000 * 7,
end: Date.now()
});
// Get funding rate history with aggregation interval
const hourly = await client.hyperliquid.funding.history('BTC', {
start: Date.now() - 86400000 * 7,
end: Date.now(),
interval: '1h'
});Funding History Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| start | number \| string | Yes | Start timestamp (Unix ms or ISO string) |
| end | number \| string | Yes | End timestamp (Unix ms or ISO string) |
| cursor | number \| string | No | Cursor from previous response for pagination |
| limit | number | No | Max results (default: 100, max: 1000) |
| interval | OiFundingInterval | No | Aggregation interval: '1m', '5m', '15m', '30m', '1h', '4h', '1d'. When omitted, the route's native/default cadence is returned. |
Funding cadence is family-specific: Hyperliquid core is approximately 1 minute, HIP-3 is approximately 10 seconds, and Lighter is approximately 10 seconds. HIP-4 does not expose a funding route.
Open Interest
// Get current open interest
const current = await client.hyperliquid.openInterest.current('BTC');
// Get open interest history (start is required)
const history = await client.hyperliquid.openInterest.history('ETH', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 100
});
// Get open interest history with aggregation interval
const hourly = await client.hyperliquid.openInterest.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
interval: '1h'
});Open Interest History Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| start | number \| string | Yes | Start timestamp (Unix ms or ISO string) |
| end | number \| string | Yes | End timestamp (Unix ms or ISO string) |
| cursor | number \| string | No | Cursor from previous response for pagination |
| limit | number | No | Max results (default: 100, max: 1000) |
| interval | OiFundingInterval | No | Aggregation interval: '1m', '5m', '15m', '30m', '1h', '4h', '1d'. When omitted, the route's native/default cadence is returned. |
Open-interest cadence is family-specific. HIP-4 outcome-side OI is served from 2026-05-02 at ~10s, and Lighter OI updates at approximately 10 seconds. Do not infer a universal one-minute cadence from this shared type.
Liquidations
Get historical liquidation events. Data is available from 2025-12-22 for Hyperliquid and HIP-3.
// Get liquidation history for a coin (Hyperliquid)
const liqWindow = { start: Date.now() - 86400000, end: Date.now(), limit: 1000 };
let liquidations = await client.hyperliquid.liquidations.history('BTC', liqWindow);
// Paginate through all results
const allLiquidations = [...liquidations.data];
while (liquidations.hasMore) {
liquidations = await client.hyperliquid.liquidations.history('BTC', { ...liqWindow, cursor: liquidations.nextCursor });
allLiquidations.push(...liquidations.data);
}
// Get liquidations for a specific user
const userLiquidations = await client.hyperliquid.liquidations.byUser('0x1234...', {
start: Date.now() - 86400000 * 7,
end: Date.now(),
coin: 'BTC' // optional filter
});
// HIP-3 liquidations (case-sensitive coins)
const hip3Liquidations = await client.hyperliquid.hip3.liquidations.history('xyz:SP500', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 100
});Liquidation Volume
Get pre-aggregated liquidation volume in time-bucketed intervals. Returns total, long, and short USD volumes per bucket -- 100-1000x less data than individual liquidation records.
// Get hourly liquidation volume for the last week (Hyperliquid)
const volume = await client.hyperliquid.liquidations.volume('BTC', {
start: Date.now() - 86400000 * 7,
end: Date.now(),
interval: '1h' // 1m, 5m, 15m, 30m, 1h, 4h, 1d
});
for (const bucket of volume.data) {
console.log(`${bucket.timestamp}: total=$${bucket.totalUsd}, long=$${bucket.longUsd}, short=$${bucket.shortUsd}`);
}
// HIP-3 liquidation volume (case-sensitive coins)
const hip3Volume = await client.hyperliquid.hip3.liquidations.volume('xyz:SP500', {
start: Date.now() - 86400000 * 7,
end: Date.now(),
interval: '1h'
});Lighter Liquidations
Both Lighter deployments expose liquidation trades and liquidation volume: client.lighter.liquidations (mainnet) and client.rhLighter.liquidations (Robinhood Chain). Rows are LighterLiquidation records rather than the Hyperliquid Liquidation shape: each names both accounts of the trade (askAccount, bidAccount, as Lighter account indices), the notional (usdAmount, in the deployment's quote asset), and each side's position before the trade. timestamp is an RFC 3339 UTC string and timestampMs the same instant in Unix milliseconds. Volume buckets (LighterLiquidationVolume) carry totalUsd and count, because Lighter does not report a reliable long/short direction on liquidations.
// Liquidation trades, cursor-paginated
const liquidations = await client.rhLighter.liquidations.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 1000
});
for (const liq of liquidations.data) {
console.log(`${liq.symbol} ${liq.size}@${liq.price} ask=${liq.askAccount} bid=${liq.bidAccount}`);
}
// Hourly liquidation volume
const lighterVolume = await client.lighter.liquidations.volume('ETH', {
start: Date.now() - 86400000 * 7,
end: Date.now(),
interval: '1h'
});Robinhood Chain liquidations start at the venue launch, 2026-06-26 20:10:26 UTC, the same floor as its trades. Rows from before live capture were backfilled from the venue's finalized export and have source: 'bucket' and an empty rawJson; rows captured live have source: 'ws' and keep the venue payload in rawJson.
Orders
Access order history, order flow aggregations, and TP/SL (take-profit/stop-loss) orders. Available for Hyperliquid, HIP-3 and HIP-4; Hyperliquid Spot has order history only, without filters. Trigger levels (orders.triggerLevels()) are Hyperliquid and HIP-3 only.
// Get order history for a coin
const orderWindow = {
start: Date.now() - 86400000,
end: Date.now(),
limit: 1000,
user: '0x1234...', // optional: filter by user address
status: 'filled', // optional: filter by status
order_type: 'limit', // optional: filter by order type
};
let orders = await client.hyperliquid.orders.history('BTC', orderWindow);
// Paginate through all results, with the same filters on every page
const allOrders = [...orders.data];
while (orders.hasMore) {
orders = await client.hyperliquid.orders.history('BTC', { ...orderWindow, cursor: orders.nextCursor });
allOrders.push(...orders.data);
}
// Only trigger events (status 'triggered'); false leaves them out
const triggered = await client.hyperliquid.orders.history('BTC', {
start: Date.now() - 3600000,
end: Date.now(),
triggered: true,
});
// Get order flow (aggregated order activity over time), one page of time buckets
const flowWindow = { start: Date.now() - 86400000, end: Date.now(), interval: '1m' }; // interval: 1m (default), 5m, 15m, 1h
let flow = await client.hyperliquid.orders.flow('BTC', flowWindow);
const flowBuckets = [...flow.data];
// A page holds up to `limit` buckets (default 1000, max 10000); follow the
// cursor with the same start, end, and interval while hasMore is true
while (flow.hasMore) {
flow = await client.hyperliquid.orders.flow('BTC', { ...flowWindow, cursor: flow.nextCursor });
flowBuckets.push(...flow.data);
}
// Get TP/SL orders
const tpsl = await client.hyperliquid.orders.tpsl('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
user: '0x1234...', // optional: filter by user
triggered: true, // optional: filter by triggered status
});
// HIP-3 orders (case-sensitive coins)
const hip3Orders = await client.hyperliquid.hip3.orders.history('xyz:SP500', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 1000
});
const hip3Flow = await client.hyperliquid.hip3.orders.flow('xyz:SP500', {
start: Date.now() - 86400000,
end: Date.now(),
interval: '1h'
});
const hip3Tpsl = await client.hyperliquid.hip3.orders.tpsl('xyz:SP500', {
start: Date.now() - 86400000,
end: Date.now()
});L4 Order Book
Access L4 orderbook snapshots, diffs, and history. L4 data includes user attribution (who placed each order). Available for Hyperliquid core, HIP-3, HIP-4 and Spot, from the first L4 checkpoint (see client.capabilities()).
Each resting order in a snapshot (L4OrderBookSnapshot) carries the time it took its place in the queue as timestamp (RFC 3339 UTC) and timestampMs (Unix milliseconds); both are null when the queue time is unknown.
// Get current L4 orderbook snapshot
const l4Ob = await client.hyperliquid.l4Orderbook.get('BTC');
console.log(l4Ob.bids[0]?.userAddress, l4Ob.bids[0]?.timestamp, l4Ob.bids[0]?.timestampMs);
// Get L4 orderbook at a specific timestamp with custom depth
const l4Historical = await client.hyperliquid.l4Orderbook.get('BTC', {
timestamp: Date.now() - 3600000, // one hour ago
depth: 20
});
// Get L4 orderbook diffs (incremental updates)
const diffWindow = { start: Date.now() - 3600000, end: Date.now(), limit: 1000 };
let diffs = await client.hyperliquid.l4Orderbook.diffs('BTC', diffWindow);
// Paginate through diffs
const allDiffs = [...diffs.data];
while (diffs.hasMore) {
diffs = await client.hyperliquid.l4Orderbook.diffs('BTC', { ...diffWindow, cursor: diffs.nextCursor });
allDiffs.push(...diffs.data);
}
// Get L4 orderbook history (full snapshots over time)
const l4History = await client.hyperliquid.l4Orderbook.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 1000
});
// HIP-3 L4 orderbook (case-sensitive coins)
const hip3L4 = await client.hyperliquid.hip3.l4Orderbook.get('xyz:SP500');
const hip3L4Diffs = await client.hyperliquid.hip3.l4Orderbook.diffs('xyz:SP500', {
start: Date.now() - 3600000,
end: Date.now(),
limit: 1000
});
const hip3L4History = await client.hyperliquid.hip3.l4Orderbook.history('xyz:SP500', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 1000
});L3 Order Book (Lighter only)
Access L3 orderbook snapshots and history from Lighter. L3 data contains individual resting orders and is capped at 250 orders per side. It is not an unlimited all-orders book.
// Get current L3 orderbook
const l3Ob = await client.lighter.l3Orderbook.get('BTC');
// Get L3 orderbook at a specific timestamp with custom depth
const l3Historical = await client.lighter.l3Orderbook.get('BTC', {
timestamp: Date.now() - 3600000, // one hour ago
depth: 250
});
// One account's resting orders
const mine = await client.lighter.l3Orderbook.get('BTC', { account: 281474976710654 });
// Get L3 orderbook history (checkpoint snapshots; `account` filters here too)
const l3Window = { start: Date.now() - 86400000, end: Date.now(), limit: 1000 };
let l3History = await client.lighter.l3Orderbook.history('BTC', l3Window);
// Paginate through L3 history
const allL3 = [...l3History.data];
while (l3History.hasMore) {
l3History = await client.lighter.l3Orderbook.history('BTC', { ...l3Window, cursor: l3History.nextCursor });
allL3.push(...l3History.data);
}L2 Order Book (Full-Depth)
Access L2 full-depth orderbook derived from L4 data. Available for Hyperliquid and HIP-3.
// L2 full-depth orderbook
const l2 = await client.hyperliquid.l2Orderbook.get('BTC');
// L2 orderbook at a specific timestamp with depth
const l2Historical = await client.hyperliquid.l2Orderbook.get('BTC', {
timestamp: Date.now() - 3600000, // one hour ago
depth: 50
});
// L2 orderbook history (up to 100 snapshots per page); depth keeps the best N levels per side
const l2History = await client.hyperliquid.l2Orderbook.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
limit: 100,
depth: 50
});
// L2 tick-level diffs
const l2Diffs = await client.hyperliquid.l2Orderbook.diffs('BTC', {
start: Date.now() - 3600000,
end: Date.now(),
limit: 1000
});
// HIP-3 L2 orderbook
const hip3L2 = await client.hyperliquid.hip3.l2Orderbook.get('xyz:SP500');Freshness
Check when each data type was last updated for a specific coin. Useful for verifying data recency before pulling it. Available across venue APIs.
// Hyperliquid
const freshness = await client.hyperliquid.freshness('BTC');
console.log(`Orderbook last updated: ${freshness.orderbook.lastUpdated}, lag: ${freshness.orderbook.lagMs}ms`);
console.log(`Trades last updated: ${freshness.trades.lastUpdated}, lag: ${freshness.trades.lagMs}ms`);
console.log(`Funding last updated: ${freshness.funding?.lastUpdated}`);
console.log(`OI last updated: ${freshness.openInterest.lastUpdated}`);
// Lighter
const lighterFreshness = await client.lighter.freshness('BTC');
// HIP-3 (case-sensitive coins)
const hip3Freshness = await client.hyperliquid.hip3.freshness('xyz:SP500');
// HIP-4 has no funding or liquidations, so those buckets are absent
const hip4Freshness = await client.hyperliquid.hip4.getFreshness('0');
// Hyperliquid Spot reports its own buckets (SpotFreshness): order book, trades,
// L4 checkpoints and diffs, order lifecycle and TWAP
const spotFreshness = await client.spot.freshness('HYPE-USDC');
console.log(spotFreshness.l4Diffs?.lagMs, spotFreshness.twap?.lastUpdated);Summary
Get a combined market snapshot in a single call -- mark/oracle price, funding rate, open interest, 24h volume, and 24h liquidation volumes.
// Hyperliquid (includes volume + liquidation data)
const summary = await client.hyperliquid.summary('BTC');
console.log(`Mark price: ${summary.markPrice}`);
console.log(`Oracle price: ${summary.oraclePrice}`);
console.log(`Funding rate: ${summary.fundingRate}`);
console.log(`Open interest: ${summary.openInterest}`);
console.log(`24h volume: ${summary.volume24h}`);
console.log(`24h liquidation volume: $${summary.liquidationVolume24h}`);
console.log(` Long: $${summary.longLiquidationVolume24h}`);
console.log(` Short: $${summary.shortLiquidationVolume24h}`);
// Lighter (price, funding, OI; no volume or liquidation data)
const lighterSummary = await client.lighter.summary('BTC');
// HIP-3 (includes mid_price; coins are case-sensitive)
const hip3Summary = await client.hyperliquid.hip3.summary('xyz:SP500');
console.log(`Mid price: ${hip3Summary.midPrice}`);Price History
Get mark, oracle, and mid price history over time. Supports aggregation intervals. Data projected from open interest records.
// Hyperliquid: available from 2023-05-20 02:50 UTC
const prices = await client.hyperliquid.priceHistory('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
interval: '1h' // 1m, 5m, 15m, 30m, 1h, 4h, 1d
});
for (const snapshot of prices.data) {
console.log(`${snapshot.timestamp}: mark=${snapshot.markPrice}, oracle=${snapshot.oraclePrice}, mid=${snapshot.midPrice}`);
}
// Lighter
const lighterPrices = await client.lighter.priceHistory('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
interval: '1h'
});
// HIP-3 (case-sensitive coins)
const hip3Prices = await client.hyperliquid.hip3.priceHistory('xyz:SP500', {
start: Date.now() - 86400000,
end: Date.now(),
interval: '1d'
});
// Paginate for larger ranges, with the same window on every page
const priceWindow = { start: Date.now() - 86400000 * 30, end: Date.now(), interval: '4h' as const, limit: 1000 };
let result = await client.hyperliquid.priceHistory('BTC', priceWindow);
while (result.hasMore) {
result = await client.hyperliquid.priceHistory('BTC', { ...priceWindow, cursor: result.nextCursor });
}Candles (OHLCV)
Get historical OHLCV candle data aggregated from trades.
// Get candle history (start is required)
const candles = await client.hyperliquid.candles.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
interval: '1h', // 1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w
limit: 100
});
// Iterate through candles
for (const candle of candles.data) {
console.log(`${candle.timestamp}: O=${candle.open} H=${candle.high} L=${candle.low} C=${candle.close} V=${candle.volume}`);
}
// Cursor-based pagination for large datasets, with the same window on every page
const candleWindow = { start: Date.now() - 86400000, end: Date.now(), interval: '1m' as const, limit: 1000 };
let result = await client.hyperliquid.candles.history('BTC', candleWindow);
const allCandles = [...result.data];
while (result.hasMore) {
result = await client.hyperliquid.candles.history('BTC', { ...candleWindow, cursor: result.nextCursor });
allCandles.push(...result.data);
}
// Lighter candles
const lighterCandles = await client.lighter.candles.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
interval: '15m'
});
// Hyperliquid Spot candles (served from 2025-03-22 10:50 UTC)
const spotCandles = await client.spot.candles.history('HYPE-USDC', {
start: new Date(Date.now() - 7 * 86400000).toISOString(),
end: new Date().toISOString(),
interval: '1h',
limit: 1000,
});Available Intervals
| Interval | Description |
|----------|-------------|
| 1m | 1 minute |
| 5m | 5 minutes |
| 15m | 15 minutes |
| 30m | 30 minutes |
| 1h | 1 hour (default) |
| 4h | 4 hours |
| 1d | 1 day |
| 1w | 1 week |
nextCursor values are returned as numeric strings. Treat each as an opaque
client value and pass it back unchanged as cursor when requesting the next
page. Core Hyperliquid, HIP-3, and Lighter candle routes accept up to 10,000
rows per request; HIP-4 and Spot routes accept up to 1,000. Hyperliquid
candle history starts at 2025-03-22 12:00 UTC (earlier bars are not
served), and Hyperliquid Spot candle history at 2025-03-22 10:50 UTC.
Cumulative Volume Delta (CVD)
client.hyperliquid.cvd and client.hyperliquid.hip3.cvd return taker buy and sell notional per time bucket (buyVolume, sellVolume), their difference (delta), and a running total (cumulativeDelta). Intervals are 1m, 5m, 15m, 30m, 1h (the default), 4h, 1d and 1w. Buckets are labelled by their open time in UTC (timestamp, an RFC 3339 string, and timestampMs, Unix milliseconds) and are omitted when they hold no trades; 4h, 1d and 1w buckets open on UTC epoch boundaries, so weekly buckets open on Thursdays.
A page holds up to limit buckets (default 500, max 10,000). While hasMore is true, pass nextCursor back unchanged as cursor with the same start, end and interval, and stop when hasMore is false. Below 1h a page can hold fewer than limit buckets and still have more to follow, so stop on hasMore, not on a short page. Without start or cursor, the response is the newest limit buckets of the 24 hours before end (or before now), with no cursor.
cumulativeDelta restarts on every page, so rebuild it from delta when joining pages. A response that is one page of several says so in meta.notice.
const window = { start: Date.now() - 86400000, end: Date.now(), interval: '5m' as const };
const buckets = [];
let page = await client.hyperliquid.cvd.history('BTC', window);
buckets.push(...page.data);
while (page.hasMore) {
page = await client.hyperliquid.cvd.history('BTC', { ...window, cursor: page.nextCursor });
buckets.push(...page.data);
}
// One running total across every page
let running = 0;
const cvd = buckets.map((b) => ({ timestamp: b.timestamp, cvd: (running += b.delta) }));
// Latest hourly buckets for a HIP-3 market (symbols keep their prefix and case)
const hip3Cvd = await client.hyperliquid.hip3.cvd.history('xyz:SP500');Lighter on Robinhood Chain
Lighter has two deployments: mainnet (client.lighter, /v1/lighter) and Robinhood Chain (client.rhLighter, /v1/rh-lighter). The Robinhood Chain client has the same resources and methods as the mainnet client except the L3 order book, which is not captured on this deployment, and the L1 account lookup: instruments, orderbook (including granularity history), trades, candles, openInterest, funding, liquidations, positions, freshness(), summary(), and priceHistory().
Markets are quoted in USDG: perpetuals have uppercase symbols (BTC) and spot markets dashed symbols (AAPL-USDG). client.rhLighter.instruments.list() returns the current set, with marketType on each. Symbols are case-insensitive; the SDK sends them uppercase. Funding and open interest are perpetuals only.
| Data | Served from | | --- | --- | | Trades, liquidations | 2026-06-26 20:10:26 UTC (venue launch) | | Candles | 2026-06-26 20:10 UTC | | Order book, open interest, funding | 2026-08-22 18:43 UTC | | L3 order book | Not available |
Trades follow the same two tiers as mainnet: trades.history() (also trades.list()) returns reconciled trades up to meta.finalizedThrough, about a day behind, and trades.recent() serves the preliminary tier.
const instruments = await client.rhLighter.instruments.list();
const perps = instruments.filter((i) => i.marketType === 'perp');
const book = await client.rhLighter.orderbook.get('BTC');
const oi = await client.rhLighter.openInterest.current('BTC');
const funding = await client.rhLighter.funding.history('BTC', {
start: Date.now() - 7 * 86400000,
end: Date.now(),
interval: '1h'
});
// Reconciled trades; the window is clamped to meta.finalizedThrough
const spotTrades = await client.rhLighter.trades.list('AAPL-USDG', {
start: Date.now() - 7 * 86400000,
end: Date.now(),
limit: 1000
});
const candles = await client.rhLighter.candles.history('BTC', {
start: Date.now() - 86400000,
end: Date.now(),
interval: '1h'
});
const freshness = await client.rhLighter.freshness('BTC');Live and replayed Robinhood Chain data over WebSocket uses the rh_lighter_* channels; see Lighter on Robinhood Chain Channels.
Account Positions
Positions, account summaries, and the position change log for Hyperliquid core (client.hyperliquid.positions), HIP-3 (client.hyperliquid.hip3.positions), Lighter mainnet (client.lighter.positions), and Lighter on Robinhood Chain (client.rhLighter.positions).
| | Hyperliquid core | HIP-3 | Lighter mainnet | Lighter on Robinhood Chain |
| --- | --- | --- | --- | --- |
| Key | 0x wallet address | 0x wallet address (optional dex) | account index | account index |
| Change log from | 2025-05-25 | 2025-10-13 | 2025-01-17 | 2026-06-26 |
| Hourly snapshots from | 2026-06-07 | 2026-06-07 | 2025-01-17 | 2026-06-26 |
| Live snapshot | about every 5 minutes | about every 5 minutes | about every 2 minutes | about every 2 minutes |
| Method | Route | Returns |
| --- | --- | --- |
| get(key, { timestamp?, symbol?, dex?, cursor?, limit? }) | /wallets/{address}/positions or /accounts/{account_index}/positions | WalletPositions: positions, account, and accountSeen when empty |
| history(key, { start, end, symbol?, dex?, cursor?, limit? }) | .../positions/history | hourly Position rows over [start, end) |
| changes(key, { start, end, symbol?, dex?, cursor?, limit? }) | .../positions/changes | PositionChange legs over [start, end) |
| account(key), or account(address, { dex? }) on HIP-3 | .../account | AccountSummary[] at the latest live snapshot: the clearinghouse summary on Hyperliquid and HIP-3, position aggregates on Lighter |
| accountHistory(key, { start, end, dex?, cursor?, limit? }) | .../account/history | hourly AccountSummary rows (on Lighter one per hour, at most 744 per page) |
| market(symbol, { hour?, side?, minValue?, includeSystem?, cursor?, limit? }) | /positions/{symbol} | every open position in one market, largest value first; meta.totals on the first page |
| marketSummary(symbol, { start?, end?, cursor?, limit? }) | /positions/{symbol}/summary | MarketPositionsSummary: now, or an hourly series |
| all({ hour, cursor?, limit? }) | /positions | every open position across markets at one hour |
| client.lighter.accounts.byL1(l1Address, { cursor?, limit? }) | /v1/lighter/accounts?l1_address= | account indices owned by an L1 address (mainnet only) |
dex applies to HIP-3 only and includeSystem to the two Lighter deployments only; the SDK refuses either one on any other client before sending, as the API would. Every method returns { data, nextCursor, meta }, and cursor-following iterators walk every page: iterateHistory(), iterateChanges(), iterateAccountHistory(), iterateMarket(), iterateMarketSummary(), iterateAll(), and client.lighter.accounts.iterateByL1().
A summary series cursor is bound to the window it was issued for, and an omitted end means now, so iterateMarketSummary() takes both start and end and sends the same window on every page. To page marketSummary() by hand, pass the same explicit start and end with each cursor; the SDK refuses a cursor without an end.
// Live positions of a wallet (or the state at any instant with `timestamp`)
const { data, meta } = await client.hyperliquid.positions.get('0x1234...');
for (const p of data.positions) {
console.log(`${p.symbol} ${p.side} ${p.size} entry ${p.entryPrice} uPnL ${p.unrealizedPnl}`);
}
console.log(`as of ${meta.asOf} (${meta.source}, quality ${meta.quality}, stale ${meta.stale})`);
if (data.positions.length === 0) console.log(`no positions: ${data.accountSeen}`);
// State as of an instant between snapshots is reconstructed from the change log
const asOf = await client.hyperliquid.positions.get('0x1234...', { timestamp: Date.now() - 90 * 60000 });
// Every change of one HIP-3 position over a week
for await (const leg of client.hyperliquid.hip3.positions.iterateChanges('0x1234...', {
start: Date.now() - 7 * 86400000,
end: Date.now(),
symbol: 'xyz:TSLA',
})) {
console.log(leg.timestamp, leg.eventType, leg.startPosition, '->', leg.endPosition);
}
// Lighter accounts by index; resolve a mainnet L1 address first
const owned = await client.lighter.accounts.byL1('0x1234...');
const lighterPositions = await client.lighter.positions.get(owned.data.accounts[0].accountIndex);
// Lighter account summary (position aggregates): now, and one row per hour
const summary = await client.rhLighter.positions.account(4521);
const hourly = await client.lighter.positions.accountHistory(4521, { start: Date.now() - 86400000, end: Date.now() });
// Largest BTC longs on Robinhood Chain at one hour, with totals for the whole market
const lastFullHour = Math.floor(Date.now() / 3600000) * 3600000 - 3600000;
const longs = await client.rhLighter.positions.market('BTC', {
hour: lastFullHour,
side: 'long',
minValue: 10000,
});
console.log(longs.meta.totals?.longCount, longs.meta.totals?.longTop10ValueShare);How to read a response:
- Numbers are decimal strings (a flat position is
"0"); timestamps are RFC 3339 UTC strings. Request times accept Unix milliseconds, ISO 8601 strings, orDateobjects; the SDK sends Unix milliseconds, and a time without a time zone is UTC.hourmust be an exact UTC hour. - Without
timestamp,get()serves the latest live snapshot. An exact hour with a committed snapshot serves that hour (meta.sourceissnapshot); any other instant is rebuilt from the change log (meta.sourceisreconstructed) with exact size, entry, andopenedAt, marks at that instant, and null snapshot-only fields such as leverage, margin, and funding. meta.asOfis the instant the data describes,meta.snapshotTsthe snapshot it was read from, andmeta.qualitythe snapshot's completeness. Each row also carries its ownquality:complete,partial(for example no mark, so value and PnL are null), ordegraded; Lighter rows can also readpreliminary,unreconciled, orincomplete.meta.staleis true, with ameta.notice, when the latest live snapshot is more than 12 minutes old.meta.builtThroughis how far the change log is built; reads past it are clamped (meta.clampedTo,meta.requestedEnd).meta.finalizedThroughis how far the data is final, with the same meaning as on Lighter trades; rows after it can still change.- An empty wallet read sets
data.accountSeen:flat,never_seen(no activity in the covered history, withmeta.noticeandmeta.coverageFrom), oroutside_coverage. - Hyperliquid cross-margin liquidation prices are not published (
liquidationPriceStatus: 'not_published_cross'). Lighter rows carryaccountIndex,accountKind,initialMarginFraction,allocatedMargin,marginMode,markSource, andfinalized; on Lighter,data.accountholds position aggregates only. - Market listings leave out Lighter settlement, insurance, and other system accounts unless
includeSystem: true. Positions cover perpetual markets only.
Limits and billing: wallet and account routes return up to 5,000 rows per page (default 500), market listings up to 2,000 (default 100), the bulk route up to 2,000 (default 1,000), and summary series up to 168 hours per page. Positions rows are billed like trades, 1,000 rows per credit; the account summary routes are billed the per-request minimum. A market cursor pins its snapshot: a 409 with error.errorCode === 'snapshot_advanced' means that snapshot was replaced, so restart without a cursor.
Wallet Classification
client.hyperliquid.wallets.classify() and client.hyperliquid.hip3.wallets.classify() return precomputed daily behavioral metrics for active wallets: order and fill counts, cancel, fill and maker ratios, order sizes, volume, fees, realized PnL, liquidation count, TWAP, client order id, builder and priority-gas usage, and more. Each response covers one daily snapshot (date, yesterday by default) with the total number of matching wallets (total); page with offset (up to 100,000) and limit (1 to 1,000, default 100).
Parameters use the API's names: min_orders (default 100), min_volume_usd, sort (default total_orders), order (asc or desc), uses_twap, uses_priority_gas, min_cancel_rate, max_cancel_rate (0 to 1), and date (YYYY-MM-DD).
const page = await client.hyperliquid.wallets.classify({
sort: 'total_volume_usd',
min_orders: 1000,
max_cancel_rate: 0.5,
limit: 100,
});
console.log(`${page.total} wallets on ${page.date}`);
for (const wallet of page.wallets) {
console.log(wallet.address, wallet.metrics.totalVolumeUsd, wallet.metrics.makerRatio);
}
// HIP-3 wallets that use TWAP orders
const hip3Twap = await client.hyperliquid.hip3.wallets.classify({ uses_twap: true });Data Quality Monitoring
Monitor data coverage, incidents, latency, and SLA compliance across venue APIs.
// Get overall system health status
const status = await client.dataQuality.status();
console.log(`System status: ${status.status}`);
for (const [exchange, info] of Object.entries(status.exchanges)) {
console.log(` ${exchange}: ${info.status}`);
}
// Get data coverage summary for venue APIs
const coverage = await client.dataQuality.coverage();
for (const exchange of coverage.exchanges) {
console.log(`${exchange.exchange}:`);
for (const [dtype, info] of Object.entries(exchange.dataTypes)) {
console.log(` ${dtype}: ${info.totalRecords.toLocaleString()} records, ${info.completeness}% complete`);
}
}
// Get symbol-specific coverage with gap detection
const btc = await client.dataQuality.symbolCoverage('hyperliquid', 'BTC');
const oi = btc.dataTypes.openInterest;
console.log(`BTC OI completeness: ${oi.completeness}%`);
console.log(`Historical coverage: ${oi.historicalCoverage}%`); // Hour-level granularity
console.log(`Gaps found: ${oi.gaps.length}`);
for (const gap of oi.gaps.slice(0, 5)) {
console.log(` ${gap.durationMinutes} min gap: ${gap.start} -> ${gap.end}`);
}
// Symbols are sent exactly as the venue names them (case-sensitive, URL-encoded)
const sp500 = await client.dataQuality.symbolCoverage('hip3', 'xyz:SP500');
const hip4Side = await client.dataQuality.symbolCoverage('hip4', '#0');
// Check empirical data cadence (when available)
const ob = btc.dataTypes.orderbook;
if (ob.cadence) {
console.log(`Orderbook cadence: ~${ob.cadence.medianIntervalSeconds}s median, p95=${ob.cadence.p95IntervalSeconds}s`);
}
// Time-bounded gap detection (last 7 days)
const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
const btc7d = await client.dataQuality.symbolCoverage('hyperliquid', 'BTC', {
from: weekAgo,
to: Date.now(),
});
// List incidents with filtering
const result = await client.dataQuality.listIncidents({ status: 'open' });
for (const incident of result.incidents) {
console.log(`[${incident.severity}] ${incident.title}`);
}
// Get latency metrics
const latency = await client.dataQuality.latency();
for (const [exchange, metrics] of Object.entries(latency.exchanges)) {
console.log(`${exchange}: OB lag ${metrics.dataFreshness.orderbookLagMs}ms`);
}
// Get SLA compliance metrics for a specific month
const sla = await client.dataQuality.sla({ year: 2026, month: 1 });
console.log(`Period: ${sla.period}`);
console.log(`Uptime: ${sla.actual.uptime}% (${sla.actual.uptimeStatus})`);
console.log(`API P99: ${sla.actual.apiLatencyP99Ms}ms (${sla.actual.latencyStatus})`);
// Account positions freshness, one row per venue
for (const venue of await client.dataQuality.positionsFreshness()) {
console.log(venue.venue, venue.product, venue.liveAgeSeconds, venue.stale, venue.finalizedThrough);
}Data Quality Endpoints
| Method | Description |
|--------|-------------|
| status() | Overall system health and per-exchange status |
| coverage() | Data coverage summary for venue APIs |
| exchangeCoverage(exchange) | Coverage details for a specific exchange |
| symbolCoverage(exchange, symbol, options?) | Coverage with gap detection, cadence, and historical coverage |
| listIncidents(params) | List incidents with filtering and pagination |
| getIncident(incidentId) | Get specific incident details |
| latency() | Curren
