Market Data (Public)
Symbols, ticker, depth, klines, funding rate, leaderboard.
All endpoints in this section are public — no X-API-KEY and no
signature required. Responses are CDN-cacheable.
GET /v2/symbols
Active futures symbols.
{ "ok": true, "symbols": ["BTCUSDT", "ETHUSDT"] }Example
curl "$BASE_URL/v2/symbols"const { symbols } = await fetch(`${BASE_URL}/v2/symbols`).then((r) => r.json());symbols = requests.get(f"{BASE_URL}/v2/symbols").json()["symbols"]res, _ := http.Get(BaseURL + "/v2/symbols")
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)let symbols = reqwest::get(format!("{BASE_URL}/v2/symbols")).await?.json::<Value>().await?;$symbols = json_decode(file_get_contents(BASE_URL . '/v2/symbols'), true);GET /v2/ticker/24hr
24-hour ticker statistics.
Query (optional)
symbol— single symbol; omit for all cached tickers.
Response — always returns a tickers array (single-element when filtered):
{
"ok": true,
"tickers": [
{
"symbol": "BTCUSDT",
"lastPrice": "30100",
"priceChange": "150",
"priceChangePercent": "0.5",
"highPrice": "30500",
"lowPrice": "29800",
"volume": "12345.67",
"quoteVolume": "370000000"
}
]
}There is no singular ticker field — even a single-symbol query returns
an array. Code defensively for the array shape.
Example
curl "$BASE_URL/v2/ticker/24hr?symbol=BTCUSDT"const { tickers } = await fetch(
`${BASE_URL}/v2/ticker/24hr?symbol=BTCUSDT`,
).then((r) => r.json());tickers = requests.get(f"{BASE_URL}/v2/ticker/24hr",
params={"symbol": "BTCUSDT"}).json()["tickers"]res, _ := http.Get(BaseURL + "/v2/ticker/24hr?symbol=BTCUSDT")let tickers = reqwest::get(format!("{BASE_URL}/v2/ticker/24hr?symbol=BTCUSDT"))
.await?.json::<Value>().await?;$tickers = json_decode(file_get_contents(
BASE_URL . '/v2/ticker/24hr?symbol=BTCUSDT'
), true);GET /v2/depth
Top-of-book order book.
Query
symbol(required)limit(default 100) — top N bids and asks.
Response — top-level bids / asks; no lastUpdateId (driven by the venue cache):
{
"ok": true,
"bids": [
["78011.9", "3.4272"],
["78011.8", "0.3876"]
],
"asks": [
["78012.0", "0.5123"],
["78012.1", "1.2456"]
]
}Each entry is a [price, quantity] string array.
Example
curl "$BASE_URL/v2/depth?symbol=BTCUSDT&limit=20"const depth = await fetch(
`${BASE_URL}/v2/depth?symbol=BTCUSDT&limit=20`,
).then((r) => r.json());depth = requests.get(f"{BASE_URL}/v2/depth",
params={"symbol": "BTCUSDT", "limit": 20}).json()res, _ := http.Get(BaseURL + "/v2/depth?symbol=BTCUSDT&limit=20")let depth = reqwest::get(format!("{BASE_URL}/v2/depth?symbol=BTCUSDT&limit=20"))
.await?.json::<Value>().await?;$depth = json_decode(file_get_contents(
BASE_URL . '/v2/depth?symbol=BTCUSDT&limit=20'
), true);GET /v2/trades
Recent market trades.
Query — symbol (required), limit (default 20).
{
"ok": true,
"trades": [
{
"id": 0,
"price": "78012.0",
"qty": "0.695",
"time": 1777217777950,
"isBuyerMaker": false
}
]
}Example
curl "$BASE_URL/v2/trades?symbol=BTCUSDT&limit=20"const trades = await fetch(
`${BASE_URL}/v2/trades?symbol=BTCUSDT&limit=20`,
).then((r) => r.json());trades = requests.get(f"{BASE_URL}/v2/trades",
params={"symbol": "BTCUSDT", "limit": 20}).json()res, _ := http.Get(BaseURL + "/v2/trades?symbol=BTCUSDT&limit=20")let trades = reqwest::get(format!("{BASE_URL}/v2/trades?symbol=BTCUSDT&limit=20"))
.await?.json::<Value>().await?;$trades = json_decode(file_get_contents(
BASE_URL . '/v2/trades?symbol=BTCUSDT&limit=20'
), true);GET /v2/funding-rate
Current funding rate.
Query — symbol (required).
Response
{ "ok": true, "symbol": "BTCUSDT", "fundingRate": "0.0001" }If the rate is not yet cached:
{ "ok": true, "symbol": "BTCUSDT", "fundingRate": null }Example
curl "$BASE_URL/v2/funding-rate?symbol=BTCUSDT"const fr = await fetch(`${BASE_URL}/v2/funding-rate?symbol=BTCUSDT`)
.then((r) => r.json());fr = requests.get(f"{BASE_URL}/v2/funding-rate",
params={"symbol": "BTCUSDT"}).json()res, _ := http.Get(BaseURL + "/v2/funding-rate?symbol=BTCUSDT")let fr = reqwest::get(format!("{BASE_URL}/v2/funding-rate?symbol=BTCUSDT"))
.await?.json::<Value>().await?;$fr = json_decode(file_get_contents(
BASE_URL . '/v2/funding-rate?symbol=BTCUSDT'
), true);GET /v2/klines
OHLCV candles.
| Parameter | Format |
|---|---|
symbol | string, required |
interval | 1m 3m 5m 15m 30m 1h 2h 4h 6h 8h 12h 1d 3d 1w 1M |
limit | default 300 |
The legacy startTime / endTime query params are accepted by the
validator but silently ignored — the upstream venue cache does not
support time-range queries on klines. Always paginate by limit from
the most-recent candle backwards. Server-side fix tracked under the
known-limitations page.
Response
{
"ok": true,
"data": [
[
1714123456789,
"30000",
"30100",
"29950",
"30050",
"1234.56",
1714123516789,
"37000000",
100,
"600",
"18000000",
"0"
]
]
}Positional array (Binance-compatible shape):
[ openTime, open, high, low, close, volume, closeTime, quoteVolume, trades, takerBuyBase, takerBuyQuote, ignore ]Example
curl "$BASE_URL/v2/klines?symbol=BTCUSDT&interval=1m&limit=200"const { data } = await fetch(
`${BASE_URL}/v2/klines?symbol=BTCUSDT&interval=1m&limit=200`,
).then((r) => r.json());klines = requests.get(f"{BASE_URL}/v2/klines",
params={"symbol": "BTCUSDT", "interval": "1m", "limit": 200}).json()["data"]res, _ := http.Get(BaseURL + "/v2/klines?symbol=BTCUSDT&interval=1m&limit=200")let klines = reqwest::get(format!(
"{BASE_URL}/v2/klines?symbol=BTCUSDT&interval=1m&limit=200"
)).await?.json::<Value>().await?;$klines = json_decode(file_get_contents(
BASE_URL . '/v2/klines?symbol=BTCUSDT&interval=1m&limit=200'
), true);GET /v2/leaderboard
Query
type—volume|referrals|commissionlimit— default 20, max 100period—7d|30d|all(defaultall)
period only accepts 7d, 30d, or all. Sending daily, weekly,
or monthly (the old enum) returns 400 from validation.
Response — entry shape varies by type:
// type=volume
{
"ok": true,
"type": "volume",
"period": "all",
"data": [
{ "rank": 1, "accountId": "cmnw...", "walletAddress": "0x...", "volume": "1234567.89" }
]
}
// type=referrals
{
"ok": true,
"type": "referrals",
"period": "all",
"data": [
{ "rank": 1, "userId": "cmus...", "walletAddress": "0x...", "referralCount": 42 }
]
}
// type=commission
{
"ok": true,
"type": "commission",
"period": "all",
"data": [
{ "rank": 1, "userId": "cmus...", "walletAddress": "0x...", "totalCommission": "5400.25" }
]
}Note the per-type field set: volume exposes accountId + volume, the
other two expose userId + their own metric. Wallet address is included
on every variant.
Example
curl "$BASE_URL/v2/leaderboard?type=volume&period=7d&limit=20"const lb = await fetch(
`${BASE_URL}/v2/leaderboard?type=volume&period=7d&limit=20`,
).then((r) => r.json());lb = requests.get(f"{BASE_URL}/v2/leaderboard",
params={"type": "volume", "period": "7d", "limit": 20}).json()res, _ := http.Get(BaseURL + "/v2/leaderboard?type=volume&period=7d&limit=20")let lb = reqwest::get(format!(
"{BASE_URL}/v2/leaderboard?type=volume&period=7d&limit=20"
)).await?.json::<Value>().await?;$lb = json_decode(file_get_contents(
BASE_URL . '/v2/leaderboard?type=volume&period=7d&limit=20'
), true);GET /v2/platform/tokens
(chainId, asset) → decimals registry, used when building EIP-712 signatures.
{
"ok": true,
"hash": "6c280be2f623082e",
"tokens": [
{ "chainId": 56, "asset": "USDT", "decimals": 18, "contractAddress": "0x55d3..." },
{ "chainId": 1, "asset": "USDT", "decimals": 6, "contractAddress": "0xdAC1..." }
]
}Headers — ETag: "<hash>", Cache-Control: public, max-age=300 (5-minute cache + revalidate).
Example
curl "$BASE_URL/v2/platform/tokens"const { tokens } = await fetch(`${BASE_URL}/v2/platform/tokens`)
.then((r) => r.json());tokens = requests.get(f"{BASE_URL}/v2/platform/tokens").json()["tokens"]res, _ := http.Get(BaseURL + "/v2/platform/tokens")let tokens = reqwest::get(format!("{BASE_URL}/v2/platform/tokens"))
.await?.json::<Value>().await?;$tokens = json_decode(file_get_contents(BASE_URL . '/v2/platform/tokens'), true);GET /v2/platform/status
Feature flags.
{
"ok": true,
"features": {
"referral": true,
"trading": true,
"deposits": true,
"withdrawals": true
}
}Example
curl "$BASE_URL/v2/platform/status"const { features } = await fetch(`${BASE_URL}/v2/platform/status`)
.then((r) => r.json());features = requests.get(f"{BASE_URL}/v2/platform/status").json()["features"]res, _ := http.Get(BaseURL + "/v2/platform/status")let status = reqwest::get(format!("{BASE_URL}/v2/platform/status"))
.await?.json::<Value>().await?;$status = json_decode(file_get_contents(BASE_URL . '/v2/platform/status'), true);GET /health
Liveness probe.
{ "ok": true, "service": "api" }Example
curl "$BASE_URL/health"const health = await fetch(`${BASE_URL}/health`).then((r) => r.json());health = requests.get(f"{BASE_URL}/health").json()res, _ := http.Get(BaseURL + "/health")let health = reqwest::get(format!("{BASE_URL}/health")).await?.json::<Value>().await?;$health = json_decode(file_get_contents(BASE_URL . '/health'), true);