Candles
Hyperliquid candles, derived from executed fills.
GET https://data.vike.io/v1/hyperliquid/ohlcvHyperliquid candles, derived from executed fills.
# the last three hourly BTC perp candles
curl -s "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=1h&limit=3" \
-H "X-API-KEY: $VIKE_API_KEY"
# a day of 15-minute bars: with no start, the window reaches back limit bars from now
curl -s "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=15m&limit=96" \
-H "X-API-KEY: $VIKE_API_KEY"
# a pinned month for a backtest: 744 hourly bars (end is exclusive)
curl -s "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=1h&start=2026-07-01T00:00:00Z&end=2026-08-01T00:00:00Z&limit=744" \
-H "X-API-KEY: $VIKE_API_KEY"
# a spot token by name
curl -s "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=HYPE&market=spot&interval=1h&limit=168" \
-H "X-API-KEY: $VIKE_API_KEY"
# a HIP-3 builder-DEX market: the dex-prefixed symbol, and its dex
curl -s "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=xyz:PLATINUM&dex=XYZ&interval=1h&limit=168" \
-H "X-API-KEY: $VIKE_API_KEY"
# 100-trade bars are built from raw fills. With no start the window is the 24 hours before end and limit
# keeps the OLDEST bars, so name the slice you want: here the last hour of a pinned day
curl -s "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=100t&start=2026-08-17T23:00:00Z&end=2026-08-18T00:00:00Z&limit=500" \
-H "X-API-KEY: $VIKE_API_KEY"
# past one page there is no cursor: save the first page, then restart one bar after its last candle
curl -s "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=1m&start=2026-08-17T00:00:00Z&limit=5000" \
-H "X-API-KEY: $VIKE_API_KEY" \
-o page1.json
# page 2 starts one minute after page 1's last candle: start accepts epoch milliseconds
START=$(( $(jq '.candles[-1].ts' page1.json) + 60000 ))
curl -s "https://data.vike.io/v1/hyperliquid/ohlcv?symbol=BTC&interval=1m&start=$START&limit=5000" \
-H "X-API-KEY: $VIKE_API_KEY" \
-o page2.jsonsymbolqueryrequiredBTC), spot token (HYPE) or raw index (@107)intervalqueryoptional1m | 5m | 15m | 30m | 1h | 4h | 1d, or Nt for N-trade bars. Default 1hmarketqueryoptionalperp | spot. Default perpdexqueryoptionalXYZ. Default HL. Builder DEXs are added over time, so do not hard-code a liststartqueryoptionalendqueryoptionallimitqueryoptional{
"symbol": "BTC",
"market": "perp",
"dex": "HL",
"interval": "1h",
"tz": "UTC",
"source": "1h fills rollup",
"candles": [
{
"ts": 1788415200000,
"open": 77800.0,
"high": 77839.0,
"low": 77679.0,
"close": 77822.0,
"volume": 742.5236199999999,
"volume_usd": 57737530.938200004,
"n_trades": 11927
},
{
"ts": 1788418800000,
"open": 77823.0,
"high": 78177.0,
"low": 77569.0,
"close": 77635.0,
"volume": 2354.81572,
"volume_usd": 183533988.69679,
"n_trades": 23209
},
{
"ts": 1788422400000,
"open": 77636.0,
"high": 78019.0,
"low": 77636.0,
"close": 77993.0,
"volume": 398.0436600000001,
"volume_usd": 31002407.180790003,
"n_trades": 3884
}
]
}There is no cursor. The engine returns one page clamped to 5000 bars; page by moving
start/end yourself.
Without start, the first bar is partial and the newest is left out
With no start the window opens limit bars before now, part way into a bar, and the bars come back oldest first,
cut at limit. So the first candle covers only part of its bar and the bar in progress is dropped. It shows most on
interval=1d: symbol=BTC&interval=1d&limit=2, asked at 17:15 UTC on 2026-10-24, returned a 2026-10-22 candle of
$452M of volume against $2.17B for the whole of 2026-10-23, and nothing for 2026-10-24. For whole days pin start to
00:00 UTC.
A HIP-3 symbol needs its dex, or the answer is empty
dex defaults to HL, the core venue. symbol=xyz:PLATINUM without dex=XYZ asks for that market on the core
venue, where it does not trade, and comes back 200 with an empty candles list, not an error. Pass the dex that
the symbol's prefix names.
Do not hard-code the dex list
The accepted dex set is not fixed. A list such as HL | XYZ | PARA | MKTS | HYNA is a partial one: builder DEXs are deployed
permissionlessly, so the accepted set is refreshed from the live deployments (within 10 minutes)
rather than fixed. An earlier three-hour sample saw only five of the nine DEXs a static list would
have carried — which is exactly how a hard-coded list 400s a venue that is live and trading. An
unknown dex returns a 400 naming the known set; ask for one and read the answer.
An unsupported interval is a 400, never a default
A bad interval is refused rather than replaced with a default. Tick bars (Nt, 1 to 100,000
trades) and time bars are not interchangeable downstream: time bars come from the pre-aggregated
minute/hour rollups, tick bars have to walk the raw fill history, which is retained 12 months
where the rollups are not. The response's source field names which of the two answered, so a
series that stopped early is distinguishable from an asset that stopped trading.
This is the API's crypto candle surface — Hyperliquid's own bars, off the fills our node sees.
/ohlcv/export streams the same single page as NDJSON.