Market data
Candles (OHLCV bars) for OKX spot instruments at three resolutions, plus the catalogue of instruments they cover. Authentication, errors and conventions are on the overview.
Coverage
- Venue and product: OKX spot is what is collected. Collectors for OKX perpetuals, Bitget and Hyperliquid exist in the code but none is switched on or has instruments configured, so no data from them is served.
- Instruments: a short curated list, not OKX's whole market. The initial list is
OKX:SPOT:SOL-USDCandOKX:SPOT:BTC-USDT.GET /v1/finance/market/instrumentsis the list of what is enabled now. - Initial history depth: about 2 days of 1-minute bars, 30 days of 1-hour bars and 5 years of daily bars. These are starting depths and can be deepened later; the range you actually get is whatever is stored, and an empty range says
empty. - Freshness: bars are polled from the venue, not streamed. Only confirmed (closed) bars are stored, so the newest bar you see is the last one that has closed, at most a poll interval plus the venue's confirmation delay behind.
- Terms: this is venue data. The venue's terms apply to it, and Aggre does not grant rights in it beyond what the venue allows.
Candles
GET /v1/finance/market/candles_1m · candles_1h · candles_1d
The daily bar is a UTC day. The dataset ids are finance.market.candles_1m, _1h and _1d.
| Parameter | Required | Meaning |
|---|---|---|
instrument_id | yes | Such as OKX:SPOT:SOL-USDC. |
from | no | Unix ms, inclusive lower bound on the bar open time. |
to | no | Unix ms, exclusive upper bound. |
limit | no | 1 to 1000, default 100. |
order | no | asc or desc, default desc (newest first). |
curl -H "Authorization: Bearer $AGGRE_API_KEY" \
"https://api.aggre.org/v1/finance/market/candles_1h?instrument_id=OKX:SPOT:SOL-USDC&limit=24"
curl -H "Authorization: Bearer $AGGRE_API_KEY" \
"https://api.aggre.org/v1/finance/market/candles_1d?instrument_id=OKX:SPOT:BTC-USDT&from=1730419200000&to=1733011200000&order=asc"Response
{
"data": [
{
"instrument_id": "OKX:SPOT:SOL-USDC",
"venue": "OKX", "product": "SPOT", "symbol": "SOLUSDC",
"ts": <integer, bar open, Unix ms UTC>,
"open": <number>, "high": <number>, "low": <number>, "close": <number>,
"volume": <number, base asset>,
"quote_volume": <number | null>,
"version": <integer, bar close time, Unix ms>
}
],
"meta": { "source": "okx", "status": "ok" | "stale" | "empty",
"fetchedAt": "<RFC 3339>", "dataDate": "<RFC 3339 | null>", "message": null },
"next_cursor": null
}tsis the bar's open time;versionis its close time (tsplus the interval).meta.dataDateis the open time of the newest bar returned.meta.statusisstalewhen the newest stored bar is more than one closed bar behind now; this is judged only when you do not setto.emptymeans no bar matched.- Paging: there is no cursor yet;
next_cursoris alwaysnull. To read a long range, movefromandtoforward in windows of at most 1000 bars. - Schema: candles.json.
Instruments
GET /v1/finance/market/instruments
Optional filters: venue and product. Returns the enabled instruments: instrument_id, venue, product, symbol (native name without separators, uppercase), native, base, quote, kind, tick_size (a decimal string), display_name and enabled. Schema: instruments.json. There is no cursor yet.
If the catalogue store is unavailable the route answers 503 store_unavailable while candles may still be served.
Funding rates and open interest (no data yet)
Nothing flows into these two datasets yet. The storage, the read routes and the collectors exist, but the collectors are not switched on and no perpetual instrument is configured. A valid request succeeds, but it returns an empty list with meta.status = "empty". They are documented so that you can see the shape that is coming; do not build on data that is not there.
GET /v1/finance/market/funding_rates · GET /v1/finance/market/open_interest
Datasets finance.market.funding_rates and finance.market.open_interest. The query is the same as for candles: instrument_id is required and must be a perpetual or futures id (PERP or FUTURES, for example OKX:PERP:BTC-USDT-SWAP), plus from, to (on ts), limit and order. The envelope is the same; meta.dataDate is the ts of the newest row returned.
- Funding rate: one row is one settled payment.
rateis that period's fraction as the venue reports it (0.0001 is 0.01%): not annualised and not normalised, and the period differs by venue and instrument.meta.statusisstalewhen the newest row is older than 24 hours (judged only whentois not set). Schema: funding_rates.json. - Open interest: a snapshot, because venues publish only the current value, so history starts the day collection starts.
open_interestis in base-asset units;open_interest_usdappears only where the venue states it and is never computed by Aggre.staleafter 30 minutes. Schema: open_interest.json.
Latest tickers
Collection is partial and has not been run against the live venues. The OKX collector writes the configured spot instruments. Collectors for Bitget and Hyperliquid exist but are not switched on, so those venues return nothing. Where nothing is stored the route answers an empty list with meta.status = "empty".
GET /v1/finance/market/tickers
Dataset finance.market.tickers_latest. Optional exact filters: venue, product and instrument_id (which must agree with the other two when they are given). It returns one row per enabled instrument, the latest only: no history, no from or to, no cursor.
priceis the last traded price (price_basislast) or, where the venue publishes none in its bulk answer (Hyperliquid), its mark price (mark).open_24h,high_24h,low_24h,volume_24handquote_volume_24hare the venue's rolling 24 hours ending atts, not a UTC day, and arenullwhere the venue does not send them. Aggre never computes them.tsis the venue's timestamp, or the collector's clock when the venue sends none.meta.statusisstalewhen the newest row is more than 5 minutes old, so check each row's owntsper instrument. Schema: tickers_latest.json.