Crypto API

39 endpoints · General · Tool · Alpha · Raw data

Last updated 2026-10
Base URL
https://api.blave.org
Auth
api-key + secret-key headers on every request
Access
API plan or Blave Agent plan
Rate Limit
500 requests / 5 min per key and per IP

Conventions

Shared by every crypto get_alpha / get_exposure endpoint:

  • period — bar size, {n}min / {n}h / {n}d ({n}m is read as minutes). Documented values are 5min, 15min, 1h, 4h, 8h, 1d; indicators with a coarser minimum say so in their block. A missing or unparseable period is a 403 {"error": "period is required"} (a 400 on unusual_movement and liquidation).
  • start_date / end_date — YYYY-MM-DD (UTC). end_date defaults to today; start_date defaults to end_date − 365 days. A range longer than 365 days is silently clamped (start_date moved to end_date − 365 days). A malformed date is not validated and ends in a 500 — always send YYYY-MM-DD.
  • symbol — USDT perpetual symbol, e.g. BTCUSDT; BTC, btc, BTC/USDT, BTC-USDT are also accepted (a bare token gets USDT appended). The get_symbols endpoints list the covered symbols.
  • Only closed bars are returned — the still-forming last bar is dropped.
  • Response is {"data": {"timestamp": [...], "alpha": [...], ...}} — parallel arrays, one element per bar. timestamp is Unix seconds (UTC), the bar label.
  • For history beyond 365 days, send one request per year and concatenate.

stat object — returned by indicators whose block lists it. A model estimate of the next-24h price move given the latest indicator value — not a win rate:

FieldTypeDescription
up_probfloatProbability of a 24h up move given the latest indicator value (0–1)
avg_up_returnfloatMean 24h return over past up moves (decimal, 0.02 = +2%)
avg_down_returnfloatMean 24h return over past down moves (decimal, negative)
return_ratiofloatSize of the average up move relative to the average down move (above 1 = up moves are larger)
exp_valuefloatExpected 24h return (decimal): up probability × average up move + down probability × average down move
is_data_sufficientboolfalse when the symbol does not have enough history — do not rely on the other fields then

When there is no data the object falls back to up_prob 0.5 and zeros.

Current Price

GET/price
Data From
Snapshot only (no history)
Update
Server cache 5 s

Parameters

NameDescriptionAllowedDefault
symbol
string · queryRequired
Token or USDT pairBTCUSDT or BTC (case-insensitive)

Example

Python
response = requests.get(f"{BASE_URL}/price", headers=headers, params={"symbol": "BTCUSDT"}, timeout=30)print(response.json())# {"symbol": "BTC", "price": 75838.2, "change_24h": -0.01739}

Response

A flat object.

FieldTypeUnitDescription
symbolstring—The token without USDT (e.g. BTC, even when BTCUSDT was sent)
pricefloatUSDTLatest price
change_24hfloatdecimal24h change as a fraction (0.025 = +2.5%)

Errors

StatusBodyWhen
400{"error": "symbol is required"}symbol missing
404{"error": "symbol <SYMBOL> not found"}No price for that token

Notes

  • Price source, in fallback order: Binance USDT-M perpetual → Binance spot → BingX perpetual.
  • change_24h normally comes from the same venue as price, but the two are cached separately (5 s each), so they can briefly differ.

Alpha Table

GET/alpha_table
Data From
Snapshot only (latest value per symbol)
Update
Every 5 minutes

Parameters

None.

Example

Python
response = requests.get(f"{BASE_URL}/alpha_table", headers=headers, timeout=60)body = response.json()row = body["data"]["0G"]   # one token out of the 716 keys this response carried# {"holder_concentration": {"-": 0.9267}, "holder_concentration_chg": {"15min": -0.0118, "1h": 0.0075, "24h": 0.4723, "3d": -0.1852, "30d": "", ...},#  "funding_rate": {"binance": 0.005, "bybit": 0.005, "okx": 0.005, "pionex": "", ...},#  "liquidation": {"15min": 0.0, "1h": -0.2665, "24h": -0.5637, "1min": "", ...},#  "market_cap": {"-": 42204386.29}, "market_cap_percentile": {"-": 56.55},#  "price": {"-": 0.1832}, "price_change": {"15min": -0.00215, "24h": -0.05792, ...},#  "statistics": {"up_prob": 0.4277, "exp_value": -0.00478, "is_data_sufficient": false, ...}, ...}# (shape captured from a live response; `""` marks insufficient data)

Response

{"data": {<TOKEN>: {...}}, "fields": [...], "note": {...}}.

data is keyed by token (BTC, 1INCH, …). Each token maps indicator name → {param: value} ("-" when the indicator has no parameter). "" = insufficient data. Besides the indicators:

KeyDescription
statisticsup_prob (prob. of a 24h up move), exp_value (expected return), avg_up_return, avg_down_return, return_ratio, is_data_sufficient
price{"-": 70000} — current price
price_change{"15min": ..., "1h": ..., "24h": ...} — % change
market_cap{"-": 1234567890} — USD market cap
market_cap_percentile{"-": 85.3} — percentile among all listed coins
funding_rate{"binance": -0.01, ...} — per exchange
oi_imbalance{"-": 0.12} — OI imbalance (full detail: /oi_imbalance/get_overview_data)

fields — one entry per indicator: id, name (key used in data), param (parameter name or null), name_en, name_zh.

note — keyed by indicator id: a list of value bands {min, max, note: {en, zh}, direction: {en, zh}, color, background_color} used to label a value (e.g. max: -3 → "Overly Bearish").

Errors

Shared errors only.

Notes

  • Use this first for any multi-coin screen or ranking — one request covers every symbol.
  • Always check statistics.is_data_sufficient before using statistics.
  • Always fetch fresh; do not reuse an earlier response.

Kline (OHLCV)

GET/kline
Data From
2020-01-01, or the contract's listing date if later
Update
Within about a minute of each bar close

Coverage. Every Binance USDⓈ-M perpetual whose symbol ends in USDT — 740 contracts as of October 2026, including tokenized stocks, commodities and other TradFi USDT perpetuals. All 740 have their full 1-minute history stored server-side, from 2020-01-01 or the listing date. A newly listed perpetual becomes queryable about 5–10 minutes after listing.

Not covered: contracts quoted in USDC, USD1, U or BTC (e.g. BTCUSDC, ETHBTC) and quarterly delivery contracts — these return the 400 unknown symbol or no data error below. Delisted contracts are not guaranteed: one may answer with whatever history is still stored or with that same 400 (those delisted before October 2026 have no 1min–4min history).

Parameters

NameDescriptionAllowedDefault
symbol
string · queryRequired
Binance USDⓈ-M USDT perpetual. A bare token gets USDT appended; a bare token that only exists with a multiplier prefix resolves to it (PEPE → 1000PEPEUSDT)BTCUSDT; also BTC, btc, BTC/USDT, BTC-USDT
period
string · queryRequired
Bar size. Any whole-minute size is accepted, not only the listed examples{n}min / {n}h / {n}d, minimum 1min (e.g. 1min, 3min, 15min, 2h, 1d, 7d). {n}m is read as minutes (15m = 15min)
start_date
string · query
First day, inclusiveYYYY-MM-DD (UTC)end_date − 365 days (period ≥ 5min); end_date − 30 days (period < 5min)
end_date
string · query
Last day, inclusive (bars through the end of that UTC day)YYYY-MM-DD (UTC)now

Per-request window: period ≥ 5min → at most 365 days; a longer range is silently clamped (start_date moved to end_date − 365 days, no error). Period < 5min → at most 30 days; a longer range is a 400.

Example

Python
params = {"symbol": "BTCUSDT", "period": "1h", "start_date": "2026-10-01", "end_date": "2026-10-02"}response = requests.get(f"{BASE_URL}/kline", headers=headers, params=params, timeout=60)data = response.json()# [{"time": 1790812800.0, "open": 83576.8, "high": 83612.6, "low": 83370.0, "close": 83460.0, "volume": 3123.991}, ...]

Response

A bare JSON array (not wrapped in {"data": ...}), ascending by time.

FieldTypeUnitDescription
timefloatUnix seconds (UTC)Bar open time
open / high / low / closefloatquote currency (USDT)Prices, per contract: on a multiplier contract the price is for the contract's unit (1000PEPEUSDT = per 1000 PEPE, 1MBABYDOGEUSDT = per 1,000,000 BABYDOGE)
volumefloat | nullbase assetTraded volume; null when the source has no volume for that bar

Errors

StatusBodyWhen
403{"error": "symbol is required"}symbol missing
403{"error": "period is required"}period missing or not parseable
400{"error": "minimum supported period is 1min"}period below one minute
400{"error": "periods below 5min must be a whole number of minutes"}e.g. 90s
400{"error": "date range exceeds max 30 days for periods below 5min"}Period < 5min and range > 30 days
400{"error": "invalid date format, expected YYYY-MM-DD"}Malformed start_date / end_date
400{"error": "unknown symbol or no data: <symbol>"}Symbol not covered (see Not covered) or not a real contract, e.g. BTCUSDC, ETHBTC, a typo. <symbol> echoes the value you sent. Not transient — do not retry

Notes

  • A window entirely before the listing date of a covered contract returns 200 with [], not an error.
  • At 1min every bar returned is closed. A longer period can end in a partial bar when end_date is today — it is built from the bars closed so far (at 07:09 UTC the 07:00 1h bar holds 07:00–07:05); drop it if you need closed bars only.
  • For history beyond one window, send one request per window and concatenate (e.g. 3 years of 5min = 3 requests; 1 year of 1min = 13 requests of ≤30 days).
  • All 740 USDT perps have full 1-minute history on disk, so a deep request is answered from stored data — there is no slow first fetch.
  • The start date applies to every interval, 1min included.
  • The latest closed 1-minute bar is usually available within the next minute; in rare degraded cases the newest bars can lag about 5–10 minutes.
  • Server cache: 30 s (1min), 300 s (1h / 4h / 1d), 60 s (every other period); only 5 s when the latest closed bar is not in yet.

Market Direction

GET/market_direction/get_alpha
Data From
2024-12-27
Update
Every 5 minutes

Parameters

No symbol: alpha is a single market-wide series, not a per-coin one. See Crypto indicator conventions.

NameDescriptionAllowedDefault
period
string · queryRequired
Bar size1h, 4h, 8h, 1d (minimum 1h)
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"period": "1h", "start_date": "2026-09-13", "end_date": "2026-09-15"}response = requests.get(f"{BASE_URL}/market_direction/get_alpha", headers=headers, params=params, timeout=60)# {"data": {"alpha": [-0.5195979478976323, -0.5223392571665055, -0.5612490182062327, ...],#           "timestamp": [1789257600.0, 1789261200.0, 1789264800.0, ...]}}   # 72 bars

Response

{"data": {"timestamp": [...], "alpha": [...]}}. No stat.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Market direction. No upper or lower bound: around 0 is the normal level, and the larger the absolute value, the more unusual. Beyond ±2 is rare and beyond ±3 extreme, on the same scale for every coin. Scan your thresholds with a backtest.

Errors

StatusBodyWhen
403{"error": "period is required"}period missing or unparseable

Notes

  • One market-wide series with no symbol dimension; 2024-12-27 is the earliest 1d bar returned.

Screener Saved Conditions

GET/screener/get_saved_conditions
Data From
—
Update
Live

Parameters

None.

Example

Python
response = requests.get(f"{BASE_URL}/screener/get_saved_conditions", headers=headers, timeout=30)conditions = response.json()["data"]

Response

{"data": {<condition_id>: {...}}}, keyed by condition id (a JSON string key, e.g. "12"; send it back as the integer condition_id). Only this account's own conditions.

FieldTypeDescription
filtersobject[]The condition's filters, all ANDed: indicator_id (int), indicator_name ({"en", "zh"}), param (string; "-" = the indicator's default), operator_id (int), operator_symbol (string, e.g. >), value (threshold)
notestringThe name you gave the condition when you saved it
name_en / name_zhstring | nullSet only on official / community conditions; on your own conditions expect empty or null and read note instead
description_en / description_zhstring | nullSet only on official / community conditions; may be empty or null

Errors

StatusBodyWhen
403{"error": "unsupported api feature"}Key not tied to a user account

Notes

  • Each request reads the account's saved conditions live.

Screener Condition Result

GET/screener/get_saved_condition_result
Data From
Snapshot (current alpha values)
Update
Every 5 minutes

Parameters

NameDescriptionAllowedDefault
condition_id
int · queryRequired
Condition to runAn id from get_saved_conditions

Example

Python
response = requests.get(f"{BASE_URL}/screener/get_saved_condition_result", headers=headers,                        params={"condition_id": 12}, timeout=60)

Response

{"data": {"alpha_names": [...], "symbols": [...]}}.

FieldTypeDescription
alpha_namesobject[]One per distinct filter indicator, in filter order: en / zh (display name, with the parameter in parentheses when there is one), name (indicator key), type, url; plus value_format, value_decimals, polarity when the indicator defines them
symbolsobject[]Tokens matching every filter
symbols[].symbolstringToken without USDT (e.g. BTC)
symbols[].idintToken id (0 when unknown)
symbols[].user_selectedboolToken is on the account's watchlist
symbols[].pricefloatLatest price in USDT (same feed as /price; 0 when unavailable)
symbols[].24h_chgfloat24h change as a fraction (0.025 = +2.5%)
symbols[].alphasfloat[]The token's value for each filter indicator, parallel to alpha_names
symbols[].alpha_notesobject[]Per indicator: indicator_id, color, direction, note (plus background_color when a rule matched; color null and empty strings when none did)

Errors

StatusBodyWhen
400{"error": "Missing parameter: condition_id is required."}Missing
400{"error": "Invalid parameter: condition_id must be an integer."}Not an integer
404{"error": "Invalid condition_id: <id> not found for user."}Not one of this account's conditions
403{"error": "unsupported api feature"}Key not tied to a user account

Holder Concentration Symbols

GET/holder_concentration/get_symbols
Data From
—
Update
Server cache 10 min

Parameters

None.

Example

Python
symbols = requests.get(f"{BASE_URL}/holder_concentration/get_symbols", headers=headers, timeout=30).json()["data"]

Response

{"data": ["BNBUSDT", "BTCUSDT", ...]}, sorted.

Errors

Shared errors only.

Notes

  • Every */get_symbols crypto endpoint currently returns the same USDT perpetual symbol list.

Holder Concentration

GET/holder_concentration/get_alpha
Data From
2021-05-11 (BTCUSDT)
Update
Every 5 minutes

Parameters

See Crypto indicator conventions.

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
period
string · queryRequired
Bar size5min, 15min, 1h, 4h, 8h, 1d
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"symbol": "BTCUSDT", "period": "1h", "start_date": "2026-09-13", "end_date": "2026-09-15"}response = requests.get(f"{BASE_URL}/holder_concentration/get_alpha", headers=headers, params=params, timeout=60)# {"data": {"alpha": [-1.1931909718306861, -1.2035898186867282, -1.2037004015202886, ...],#           "timestamp": [1789257600.0, 1789261200.0, 1789264800.0, ...],#           "stat": {"up_prob": 0.509739818557561, "exp_value": -0.00051954905018229,#                    "avg_up_return": 0.015512131150026753, "avg_down_return": -0.017188220228787618,#                    "return_ratio": 0.9024861762037658, "is_data_sufficient": true}}}   # 72 bars

Response

{"data": {"timestamp": [...], "alpha": [...], "stat": {...}}}.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Holder concentration: above 0 = whale longs more concentrated than usual, below 0 = whale shorts more concentrated than usual. No upper or lower bound: around 0 is the normal level, and the larger the absolute value, the more unusual. Beyond ±2 is rare and beyond ±3 extreme, on the same scale for every coin. Scan your thresholds with a backtest.
statobjectSee stat object

Errors

StatusBodyWhen
403{"error": "symbol is required"} / {"error": "period is required"}Missing parameter

Notes

  • 2021-05-11 is BTCUSDT's first 1d bar; other symbols can start later.

Funding Rate

GET/funding_rate/get_alpha
Data From
2025-09-30 (BTCUSDT)
Update
Every 5 minutes

Parameters

See Crypto indicator conventions.

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbol (Binance form, whichever exchange)e.g. BTCUSDT
period
string · queryRequired
Bar size5min, 15min, 1h, 4h, 8h, 1d
exchange
string · query
Whose perp funding rate to read; any other value is 400binance, okx, bingx, bybitbinance
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"symbol": "BTCUSDT", "period": "1h", "start_date": "2026-09-13", "end_date": "2026-09-15"}response = requests.get(f"{BASE_URL}/funding_rate/get_alpha", headers=headers, params=params, timeout=60)# {"data": {"timestamp": [1789257600.0, 1789261200.0, 1789264800.0, ...],#           "alpha": [0.005064, 0.006165, 0.007765, ...],#           "close": [77239.5, 77285.5, 77263.9, ...],#           "stat": {"up_prob": 0.5009438427095587, "exp_value": -0.0008769555139270298,#                    "is_data_sufficient": false, ...}}}   # 72 bars

Response

{"data": {"timestamp": [...], "alpha": [...], "close": [...], "stat": {...}}}.

FieldTypeUnitDescription
timestampfloat[]Unix seconds (UTC)Bar label
alphafloat[]percentFunding rate × 100 (0.01 = 0.01%); positive = longs pay shorts
closefloat[]USDTPerpetual close price
statobject—See stat object

Errors

StatusBodyWhen
403{"error": "symbol is required"} / {"error": "period is required"}Missing parameter
400{"error": "exchange must be one of binance, okx, bingx, bybit"}exchange outside the list

Notes

  • 2025-09-30 is BTCUSDT's first 1d bar; other symbols can start later, and exchange=bybit starts later — read the first timestamp.

Market Sentiment Symbols

GET/market_sentiment/get_symbols
Data From
—
Update
Server cache 10 min

Parameters

None.

Example

Python
symbols = requests.get(f"{BASE_URL}/market_sentiment/get_symbols", headers=headers, timeout=30).json()["data"]

Response

{"data": ["BNBUSDT", "BTCUSDT", ...]}, sorted.

Errors

Shared errors only.

Notes

  • Same USDT perpetual symbol list as every other */get_symbols crypto endpoint.

Market Sentiment

GET/market_sentiment/get_alpha
Data From
2020-01-01 (BTCUSDT)
Update
Every 5 minutes

Parameters

See Crypto indicator conventions.

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
period
string · queryRequired
Bar size5min, 15min, 1h, 4h, 8h, 1d
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"symbol": "BTCUSDT", "period": "1h", "start_date": "2025-01-01", "end_date": "2025-03-01"}response = requests.get(f"{BASE_URL}/market_sentiment/get_alpha", headers=headers, params=params, timeout=60)

Response

{"data": {"timestamp": [...], "alpha": [...], "stat": {...}}}.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Market sentiment: above 0 = more optimistic than usual, below 0 = more pessimistic than usual. No upper or lower bound: around 0 is the normal level, and the larger the absolute value, the more unusual. Beyond ±2 is rare and beyond ±3 extreme, on the same scale for every coin. Scan your thresholds with a backtest.
statobjectSee stat object

Errors

StatusBodyWhen
403{"error": "symbol is required"} / {"error": "period is required"}Missing parameter

Notes

  • 2020-01-01 is BTCUSDT's first 1d bar; other symbols can start later.

Capital Shortage

GET/capital_shortage/get_alpha
Data From
2023-12-09
Update
Every 5 minutes

Parameters

No symbol; market-wide. See Crypto indicator conventions.

NameDescriptionAllowedDefault
period
string · queryRequired
Bar size — 5min and 15min both return data5min, 15min, 1h, 4h, 8h, 1d
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"period": "1h", "start_date": "2025-01-01", "end_date": "2025-03-01"}response = requests.get(f"{BASE_URL}/capital_shortage/get_alpha", headers=headers, params=params, timeout=60)

Response

{"data": {"timestamp": [...], "alpha": [...], "stat": {...}}}.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Capital shortage: above 0 = more leverage than usual and tighter funds, below 0 = less leverage and looser funds. No upper or lower bound: around 0 is the normal level, and the larger the absolute value, the more unusual. Beyond ±2 is rare and beyond ±3 extreme, on the same scale for every coin. Scan your thresholds with a backtest.
statobjectSee stat object (computed against BTC)

Errors

StatusBodyWhen
403{"error": "period is required"}Missing parameter

Notes

  • One market-wide series with no symbol dimension; 2023-12-09 is the first 1d bar.

Sector Rotation History

GET/sector_rotation/get_history_data
Data From
Trailing 365 days (daily)
Update
About hourly

Parameters

None.

Example

Python
response = requests.get(f"{BASE_URL}/sector_rotation/get_history_data", headers=headers, timeout=60)# {"data": {"alpha": {"AI": {"data": [0.0, 0.04377017039444864, 0.04922749428543449, ...],#                           "name_en": "AI", "name_zh": "人工智能"},#                     "BNB Eco": {"data": [0.0, 0.008847752133756215, ...],#                                 "name_en": "BNB Eco", "name_zh": "BNB 生態"}, ...},#           "timestamp": [1757980800.0, 1758067200.0, 1758153600.0, ...]}}   # 51 sectors, 366 points

Response

{"data": {"alpha": {<sector>: {"data": [...], "name_en": ..., "name_zh": ...}}, "timestamp": [...]}}. timestamp sits next to alpha at the top of data, not inside each sector; it is the shared time axis for every sector series.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC), one per point — 366 daily points in the observed response
alpha.<sector>.datafloat[]The sector series, same length and order as timestamp (366); the first element is 0.0
alpha.<sector>.name_en / name_zhstringSector display name

Errors

Shared errors only.

Notes

  • The series is a trailing one-year daily window (366 daily points), and every sector starts at 0.0. There are no parameters, and each rebuild recomputes only the trailing 365 days, so no longer history exists.
  • Rebuilt by a scheduled job, with rebuilds landing 50–60 minutes apart; served from the job's output with no extra server cache.

Sector Rotation Overview

GET/sector_rotation/get_overview_data
Data From
Snapshot
Update
About hourly

Parameters

None.

Example

Python
data = requests.get(f"{BASE_URL}/sector_rotation/get_overview_data", headers=headers, timeout=60).json()["data"]# {"AI": {"name_en": "AI", "name_zh": "人工智能",#         "data": {"1h": {"pct_change": 0.0076}, "8h": ..., "90d": ...},#         "symbols": {"0G": {"id": 38337, "data": {"1h": {"pct_change": 0.0061}, ...}}, ...}}, ...}

Response

{"data": {<sector>: {"name_en", "name_zh", "data", "symbols"}}} (~48 sectors).

FieldDescription
data{<timeframe>: {"pct_change": float}} for 1h, 8h, 24h, 3d, 7d, 30d, 90d; pct_change is a decimal (0.0061 = +0.61%)
symbols{<token>: {"id": int, "data": {<timeframe>: {"pct_change": float}}}} — per-token breakdown

Errors

Shared errors only.

Notes

  • Rebuilt by a scheduled job, with rebuilds landing 50–60 minutes apart; served from the job's output with no extra server cache.

OI Imbalance

GET/oi_imbalance/get_overview_data
Data From
Snapshot
Update
Every 5 minutes

Parameters

None.

Example

Python
data = requests.get(f"{BASE_URL}/oi_imbalance/get_overview_data", headers=headers, timeout=60).json()["data"]# [{"token": "TSLA", "token_id": 39618, "token_price": 313.33, "token_chg": 0.031,#   "market_cap": 40415.98, "oi_total": 59916616.78, "alpha": 1482.5}, ...]

Response

{"data": [...]}, sorted by alpha descending.

FieldTypeUnitDescription
tokenstring—Token
token_idint—Blave token id
token_pricefloatUSDPrice
token_chgfloatdecimalPrice change
market_capfloatUSDMarket cap
oi_totalfloatUSDFutures OI summed across Binance / OKX / BingX
alphafloatratiooi_total / market_cap — high = OI crowded relative to size (squeeze / volatility risk)

Errors

Shared errors only.

Notes

  • /alpha_table's oi_imbalance carries only the final alpha; this endpoint has the full table.
  • Server cache: 5 minutes.

Whale Hunter Symbols

GET/whale_hunter/get_symbols
Data From
—
Update
Server cache 10 min

Parameters

None.

Example

Python
symbols = requests.get(f"{BASE_URL}/whale_hunter/get_symbols", headers=headers, timeout=30).json()["data"]

Response

{"data": ["BNBUSDT", "BTCUSDT", ...]}, sorted.

Errors

Shared errors only.

Notes

  • Same USDT perpetual symbol list as every other */get_symbols crypto endpoint.

Whale Hunter

GET/whale_hunter/get_alpha
Data From
2021-12-01 (BTCUSDT)
Update
Every 5 minutes

Parameters

See Crypto indicator conventions.

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
period
string · queryRequired
Bar size5min, 15min, 1h, 4h, 8h, 1d
timeframe
string · query
Time window the reading covers15min, 1h, 4h, 8h, 24h, 3d24h
score_type
string · query
Open-interest change or volumescore_oi, score_volumescore_oi
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"symbol": "BTCUSDT", "period": "1h", "timeframe": "24h", "score_type": "score_oi"}response = requests.get(f"{BASE_URL}/whale_hunter/get_alpha", headers=headers, params=params, timeout=60)

Response

{"data": {"timestamp": [...], "alpha": [...], "stat": {...}}}.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Whale hunter over timeframe: above 0 = open interest (or volume) higher or busier than usual, below 0 = lower or quieter. No upper or lower bound: around 0 is the normal level, and the larger the absolute value, the more unusual. Beyond ±2 is rare and beyond ±3 extreme, on the same scale for every coin. Scan your thresholds with a backtest.
statobjectSee stat object

Errors

StatusBodyWhen
403{"error": "symbol is required"} / {"error": "period is required"}Missing parameter
403{"error": "Invalid score_type"}score_type not allowed

Notes

  • timeframe is not validated server-side. One value outside the list was tried, 2h, and it returned 200 with data. That is a single observation — it does not establish that any {n}h works. Stay on the listed values unless you verify the one you need.
  • 2021-12-01 is BTCUSDT's first 1d bar; other symbols can start later.

Taker Intensity Symbols

GET/taker_intensity/get_symbols
Data From
—
Update
Server cache 10 min

Parameters

None.

Example

Python
symbols = requests.get(f"{BASE_URL}/taker_intensity/get_symbols", headers=headers, timeout=30).json()["data"]

Response

{"data": ["BNBUSDT", "BTCUSDT", ...]}, sorted.

Errors

Shared errors only.

Notes

  • Same USDT perpetual symbol list as every other */get_symbols crypto endpoint.

Taker Intensity

GET/taker_intensity/get_alpha
Data From
2020-01-01 (BTCUSDT)
Update
Every 5 minutes

Parameters

See Crypto indicator conventions.

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
period
string · queryRequired
Bar size5min, 15min, 1h, 4h, 8h, 1d
timeframe
string · query
Rolling window15min, 1h, 4h, 8h, 24h, 3d24h
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"symbol": "BTCUSDT", "period": "1h", "timeframe": "24h", "start_date": "2025-01-01", "end_date": "2025-03-01"}response = requests.get(f"{BASE_URL}/taker_intensity/get_alpha", headers=headers, params=params, timeout=60)

Response

{"data": {"timestamp": [...], "alpha": [...], "stat": {...}}}.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Taker intensity over timeframe: above 0 = more aggressive longs than usual, below 0 = more aggressive shorts than usual. No upper or lower bound: around 0 is the normal level, and the larger the absolute value, the more unusual. Beyond ±2 is rare and beyond ±3 extreme, on the same scale for every coin. Scan your thresholds with a backtest.
statobjectSee stat object

Errors

StatusBodyWhen
403{"error": "symbol is required"} / {"error": "period is required"}Missing parameter

Notes

  • 2020-01-01 is BTCUSDT's first 1d bar; other symbols can start later.

Unusual Movement Symbols

GET/unusual_movement/get_symbols
Data From
—
Update
Server cache 10 min

Parameters

None.

Example

Python
symbols = requests.get(f"{BASE_URL}/unusual_movement/get_symbols", headers=headers, timeout=30).json()["data"]

Response

{"data": ["BNBUSDT", "BTCUSDT", ...]}, sorted.

Errors

Shared errors only.

Notes

  • Same USDT perpetual symbol list as every other */get_symbols crypto endpoint.

Unusual Movement

GET/unusual_movement/get_alpha
Data From
2020-01-02 (BTCUSDT)
Update
Every 5 minutes

Parameters

See Crypto indicator conventions.

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
period
string · queryRequired
Bar size5min, 15min, 1h, 4h, 8h, 1d
timeframe
string · query
Window the move is measured over15min, 1h, 4h, 8h, 24h, 3d, 7d24h
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"symbol": "BTCUSDT", "period": "1h", "timeframe": "24h"}response = requests.get(f"{BASE_URL}/unusual_movement/get_alpha", headers=headers, params=params, timeout=60)

Response

{"data": {"timestamp": [...], "alpha": [...], "close": [...], "stat": {...}}}.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Unusual movement over timeframe: above 0 = a rarer rise than usual, below 0 = a rarer drop than usual. No upper or lower bound: around 0 is the normal level, and the larger the absolute value, the more unusual. Beyond ±2 is rare and beyond ±3 extreme, on the same scale for every coin. Scan your thresholds with a backtest.
closefloat[]Close price (USDT)
statobjectSee stat object

Errors

StatusBodyWhen
400{"error": "symbol is required"} / {"error": "period is required"}Missing parameter
500server errortimeframe outside the allowed list

Notes

  • 2020-01-02 is BTCUSDT's first 1d bar; other symbols can start later.

Squeeze Momentum Symbols

GET/squeeze_momentum/get_symbols
Data From
—
Update
Server cache 10 min

Parameters

None.

Example

Python
symbols = requests.get(f"{BASE_URL}/squeeze_momentum/get_symbols", headers=headers, timeout=30).json()["data"]

Response

{"data": ["BNBUSDT", "BTCUSDT", ...]}, sorted.

Errors

Shared errors only.

Notes

  • Same USDT perpetual symbol list as every other */get_symbols crypto endpoint.

Squeeze Momentum

GET/squeeze_momentum/get_alpha
Data From
2020-02-09 (BTCUSDT)
Update
Daily bars

Parameters

No period; fixed to 1d. See Crypto indicator conventions.

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"symbol": "BTCUSDT", "start_date": "2025-01-01", "end_date": "2025-03-01"}response = requests.get(f"{BASE_URL}/squeeze_momentum/get_alpha", headers=headers, params=params, timeout=60)# {"data": {"alpha": [-0.2256, ...], "scolor": ["black", ...], "timestamp": [...], "stat": {...}}}

Response

{"data": {"timestamp": [...], "alpha": [...], "scolor": [...], "stat": {...}}}.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC), daily
alphafloat[]Momentum value
scolorstring[]black = squeeze on (Bollinger Bands inside Keltner Channels), grey = squeeze off
statobjectSee stat object

Errors

StatusBodyWhen
403{"error": "symbol is required"}Missing parameter

Notes

  • Covers Binance only — USDT-M perpetual price.
  • The series is padded: BTCUSDT rows exist from 2020-01-01, but alpha is 0.0 until 2020-02-09. A request starting earlier than the Data from date returns those padded rows — they are filler, not signal. Drop leading zeros, or start at the Data from date.
  • 2020-02-09 is the first non-zero alpha for BTCUSDT; other symbols can start later.

Blave Top Trader Exposure

GET/blave_top_trader/get_exposure
Data From
2025-03-03
Update
Every 5 minutes

Parameters

No symbol: alpha is a single market-wide series, not a per-coin one. BTCUSDT is used internally only to align the bars; it is not returned and does not change alpha. See Crypto indicator conventions.

NameDescriptionAllowedDefault
period
string · queryRequired
Bar size1h, 4h, 8h, 1d
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"period": "1h", "start_date": "2025-05-01", "end_date": "2025-07-01"}response = requests.get(f"{BASE_URL}/blave_top_trader/get_exposure", headers=headers, params=params, timeout=60)# {"data": {"alpha": [34.32, 40.52, ...], "timestamp": [1747130400.0, ...]}}

Response

{"data": {"timestamp": [...], "alpha": [...]}}. No stat.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Net exposure of Blave's top traders (top 10% by account assets) — the median, across those traders, of each trader's net notional position ÷ own assets, ×100 (positive = net long). A raw ratio, not a Blave score — do not reuse other indicators' thresholds

Errors

StatusBodyWhen
403{"error": "period is required"}Missing parameter

Notes

  • One market-wide series covering all coins these traders hold; there is no symbol dimension.

Liquidation Symbols

GET/liquidation/get_symbols
Data From
—
Update
Server cache 10 min

Parameters

None.

Example

Python
symbols = requests.get(f"{BASE_URL}/liquidation/get_symbols", headers=headers, timeout=30).json()["data"]

Response

{"data": ["BNBUSDT", "BTCUSDT", ...]}, sorted.

Errors

Shared errors only.

Notes

  • Same USDT perpetual symbol list as every other */get_symbols crypto endpoint.

Liquidation

GET/liquidation/get_alpha
Data From
2023-01-01 for BTC/ETH; other symbols may start later
Update
Every 5 minutes

Parameters

See Crypto indicator conventions.

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
period
string · queryRequired
Bar size5min, 15min, 1h, 4h, 8h, 1d
timeframe
string · query
Rolling window15min, 1h, 4h, 8h, 24h, 3d24h
start_date
string · query
First dayYYYY-MM-DDend_date − 365 days
end_date
string · query
Last dayYYYY-MM-DDtoday

Example

Python
params = {"symbol": "BTCUSDT", "period": "1h", "timeframe": "24h"}response = requests.get(f"{BASE_URL}/liquidation/get_alpha", headers=headers, params=params, timeout=60)

Response

{"data": {"timestamp": [...], "alpha": [...], "stat": {...}}}.

FieldTypeDescription
timestampfloat[]Unix seconds (UTC)
alphafloat[]Liquidation imbalance over timeframe, and how unusual the gap is. Positive means more short liquidations, negative means more long liquidations; 0 is not this coin's normal level.
statobjectSee stat object

Errors

StatusBodyWhen
400{"error": "symbol is required"} / {"error": "period is required"}Missing parameter

Notes

  • The series is padded: BTCUSDT rows exist from 2020-01-01, but alpha is 0.0 until 2023-01-01. A request starting earlier than the Data from date returns those padded rows — they are filler, not signal. Drop leading zeros, or start at the Data from date. Symbols other than BTC/ETH turn non-zero later still, so check per symbol.

Liquidation Map

GET/liquidation/get_map
Data From
Snapshot
Update
Server cache 5 s

Parameters

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
price_max
float · query
Upper bound of the price axispriceserver-chosen range
price_min
float · query
Lower bound of the price axispriceserver-chosen range

Example

Python
response = requests.get(f"{BASE_URL}/liquidation/get_map", headers=headers, params={"symbol": "BTCUSDT"}, timeout=60)# {"data": {"price": 77554.1, "labels": [54287.9, ...], "oi_value": [57693.86, ...],#           "cumsum": [1543109619.0, ...], "liquidation": {"24h": {"buy_liq": [...], "sell_liq": [...]}}}}

Response

{"data": {"price", "labels", "oi_value", "cumsum", "liquidation"}}.

FieldTypeUnitDescription
pricefloatUSDTCurrent price
labelsfloat[]USDT200 price buckets
oi_valuefloat[]USDEstimated open interest at each bucket (model estimate, not real positions)
cumsumfloat[]USDCumulative liquidation exposure across buckets
liquidationobjectUSD{"24h": {"buy_liq": [...], "sell_liq": [...]}} — liquidations that happened over the last 24 h per bucket, extrapolated to a market-wide estimate: buy_liq = short liquidations, sell_liq = long liquidations

Errors

StatusBodyWhen
400{"error": "symbol is required"}Missing parameter

Liquidation Map Change

GET/liquidation/get_map_change
Data From
Last 24 hours
Update
Computed per request

Parameters

NameDescriptionAllowedDefault
symbol
string · queryRequired
Symbole.g. BTCUSDT
price_max
float · query
Upper bound of the price axispriceserver-chosen range
price_min
float · query
Lower bound of the price axispriceserver-chosen range

Example

Python
response = requests.get(f"{BASE_URL}/liquidation/get_map_change", headers=headers, params={"symbol": "BTCUSDT"}, timeout=60)# {"data": {"price": 77554.1, "labels": [54287.9, ...], "hist_0_1h": [0.0, ...], "hist_1_8h": [...], "hist_8_24h": [...]}}

Response

{"data": {"price", "labels", "hist_0_1h", "hist_1_8h", "hist_8_24h"}}.

FieldTypeUnitDescription
pricefloatUSDTCurrent price
labelsfloat[]USDT200 price buckets (lower edges)
hist_0_1hfloat[]USDNew estimated liquidation exposure over the last 0–1 h, per bucket — an estimate, not actual liquidations
hist_1_8hfloat[]USDLast 1–8 h
hist_8_24hfloat[]USDLast 8–24 h

Errors

StatusBodyWhen
400{"error": "symbol is required"}Missing parameter

Liquidation by Coin

GET/liquidation/get_coin
Data From
Snapshot (last 24 h)
Update
Every 5 minutes

One coin's forced liquidations across every exchange feed Blave collects: four rolling windows with the per-exchange split, an hourly 24-point series, and each feed's coverage notes. This is real liquidation flow, not the model estimate behind get_map.

Parameters

NameDescriptionAllowedDefault
symbol
string · queryRequired
Coin. The quote suffix is stripped; the response symbol is the normalised coin nameBTC, BTCUSDT, btc, BTC-USDT-SWAP, BTC_USDT (≤ 32 chars)

Example

Response

{"data": {"symbol", "rank", "updated_at", "windows", "exchanges", "detail_complete", "series"}}.

FieldTypeUnitDescription
symbolstring—Normalised coin name, e.g. BTC
rankint / null—Position among the top 50 coins by 24 h total across exchanges; null outside the top 50 or with no event
updated_atstring / nullISO 8601 UTCTime of the latest 5-minute bucket used
windowsobject—Keys are the strings "1", "4", "12", "24" (hours). Each is a rolling window ending at the latest 5-minute bucket, with the fields below
windows.<h>.total_liq_usd / long_liq_usd / short_liq_usdfloatUSDSummed across exchanges; long = long positions liquidated (price fell), short = shorts liquidated (price rose)
windows.<h>.long_pct / short_pctfloat / nullratio 0–1Share of the window total; null when the window total is 0
windows.<h>.covered_hoursfloathHow many hours of the window actually have buckets (< h right after a collector restart)
windows.<h>.by_exchangeobjectUSD{exchange: {total_liq_usd, long_liq_usd, short_liq_usd}}. An exchange with no event in the window has no key — read exchanges[] to tell "feed alive, this coin quiet" from "feed absent"
exchanges[]object[]—One row per feed (six today, present even with no event), sorted by 24 h total desc, then roster order
exchanges[].exchangestring—binance, bybit, gate, okx, htx, bitfinex
exchanges[].listedbool / null—Whether that exchange lists a USDT-margined perpetual for the coin; null when the contract list could not be fetched (Bitfinex always null)
exchanges[].last_event_atstring / nullISO 8601 UTCLatest bucket seen from that feed (any coin); null if never seen
exchanges[].price_basisstring—Price used for USD conversion: trade_avg, bankruptcy, unverified
exchanges[].coveragestring—Feed completeness: full, full_unstated, sampled_1s, aggregated_1s, sampled_undisclosed
exchanges[].time_basisstring—event — bucketed by the event's own timestamp
detail_completebool—false when the coin may have been cut from a full per-bucket detail list (feeds keep the top 100 coins per 5-minute bucket): windows can then under-count. Top-50 coins are almost always true
series.bucket_secondsintsAlways 3600
series.pointsobject[]—Always 24 entries, oldest → newest, on clock hours; the last is the current hour up to updated_at (the snapshot is rebuilt every 5 min, so it can trail the request by a few minutes). Each {ts, long_liq_usd, short_liq_usd}; hours with no event are 0, never missing

windows["24"] is the same rolling frame as the exchange matrix, so the same coin shows the same 24 h number there. series is on clock hours, so Σ points ≠ windows["24"] by design: take totals from windows, timing from series.

Errors

StatusBodyWhen
400{"error": "symbol is required"}symbol missing, blank, longer than 32 chars, or nothing left after the quote suffix is stripped (e.g. symbol=USDT)
404{"error": "<SYMBOL> is not a collected symbol"}No exchange lists the coin and no feed reported it in the last 24 h — an answer, not a transient
503{"error": "liquidation data unavailable"}Upstream buckets did not answer — retry later; never read as "0 liquidations"

Notes

  • Covers the liquidation feeds of Binance, Bybit, Gate.io, OKX, HTX and Bitfinex.
  • Snapshot only: no start_date / end_date, and nothing older than 24 h. For history use get_alpha (a Blave score of the long/short imbalance, not USD amounts).
  • Symbol handling differs from the other liquidation endpoints: get_alpha / get_map need the USDT perpetual symbol (BTCUSDT); here BTC and BTCUSDT are the same coin.
  • Server cache: 5 minutes.
  • USD notional is converted at collection time, so exchanges can be summed.

Liquidation Exchange Matrix

GET/liquidation/get_exchanges
Data From
Rolling window, 5-minute aligned (default last 24 h)
Update
Every 5 minutes

Whole-market forced liquidations, aggregated per exchange and as a coin × exchange matrix — the market-wide companion to /liquidation/get_coin. Same rolling 5-minute-aligned frame, so a coin's 24 h total is the same number on both.

Parameters

NameDescriptionAllowedDefault
hours
int · query
Window length. Outside the range → 400 (it is not clamped); a non-integer value silently falls back to the default1–16824
top_n
int · query
How many coins to list individually; the rest go to others. Same range / non-integer rules as hours1–5010

Example

Response

{"data": {"exchanges", "coins", "others", "total", "buckets", "covered_hours", "window_hours", "window_start", "window_end", "updated_at"}}.

FieldTypeUnitDescription
exchanges[]object[]—One row per feed, sorted by total desc: exchange, total_liq_usd, long_liq_usd, short_liq_usd, long_pct, short_pct, events, last_event_at. Every feed is always listed: amounts null = no data received from that feed in the window (sorted last), 0.0 = connected but no liquidations
exchanges[].price_basis / .coverage / .time_basisstring—How comparable that row is: trade_avg / bankruptcy / unverified; full, full_unstated, sampled_1s, aggregated_1s, sampled_undisclosed; event. Keep them when re-publishing the numbers — a sampled feed is not a full one
coins[]object[]—The top top_n by cross-exchange total: token, token_id (0 when the symbol has no token id), total_liq_usd, long_liq_usd, short_liq_usd, by_exchange{name: {total/long/short_liq_usd}}. by_exchange is sparse — a feed with nothing for that coin has no key; read it as 0 when that feed's exchanges[] total is not null
othersobject—Everything top_n cut off, same fields plus coin_count, so coins[] + others adds back to each exchange's total
totalobjectUSD / ratiototal_liq_usd, long_liq_usd, short_liq_usd, long_pct, short_pct
covered_hoursfloathHours of the window that actually have buckets (< hours right after a collector restart)
bucketsint—Number of 5-minute buckets aggregated
window_hours / window_start / window_endint / stringh / ISO 8601 UTCThe window as the server resolved it
updated_atstringISO 8601 UTCLatest bucket used

long_liq_usd = long positions liquidated (price fell); short_liq_usd = shorts liquidated (price rose).

Errors

StatusBodyWhen
400{"error": "hours must be between 1 and 168"} / {"error": "top_n must be between 1 and 50"}Out-of-range parameter

Notes

  • Covers the liquidation feeds of Binance, Bybit, Gate.io, OKX, HTX and Bitfinex.
  • No data at all (feeds down, or the data source unreachable) is still a 200 with the same shape and every amount null, buckets: 0 — never a table of zeros. Check total.total_liq_usd before using the numbers.
  • Totals only — no time series. Hourly shape for one coin is /liquidation/get_coin; a long-history Blave score is /liquidation/get_alpha.
  • The window is rolling, not a calendar day, and it is the same frame /liquidation/get_coin uses for windows["24"].
  • Server cache: 5 minutes.
  • USD notional is converted at collection time, so exchanges can be summed.

Long/Short Ratio Table

GET/long_short_ratio/get_table
Data From
Snapshot (latest cross-section)
Update
5-minute buckets

Every collected coin × every long/short-ratio source, as of now. Ten sources: Binance, OKX and Gate.io each publish three kinds — all accounts, top-trader accounts, top-trader positions — and Bybit publishes accounts only. Rows are ordered by Binance open-interest notional. Only coins that resolve to an entry in Blave's token list are listed; the API-key response is the full table (full: true), the anonymous studio twin only the rows of its 30-coin whitelist.

Parameters

None.

Example

Collection start (first stored bucket, measured on BTC 2026-09-22)

Source keyCollecting since
binance_account2021-05-11
binance_top_account / binance_top_position2026-08-22
okx_account / okx_top_account / okx_top_position2025-02-18
gate_account / gate_top_account / gate_top_position2026-08-12
bybit_account2026-08-12

Every source is now older than the 7 days this dataset serves, so none of them limits a query — the dates matter only if you are told a source "has no history".

Response

{"data": {"coins", "sources", "summary", "tokens_shown", "tokens_total", "full", "updated_at"}}.

FieldTypeUnitDescription
coins[]object[]—One row per coin: token, token_id, plus one value per source key
coins[].<source key>float / nullratioLong accounts (or positions) ÷ short. null = that exchange has no such feed for the coin. Long share = r / (1 + r) — the API does not precompute it
sources[]object[]—The ten feeds, in column order. Read this, never a hard-coded key list
sources[].keystring—<exchange>_<type>, e.g. binance_top_position — the key used in coins[]
sources[].exchange / .typestring—binance / okx / gate / bybit; account / top_account / top_position
sources[].last_atstringISO 8601 UTCNewest sample from that feed
sources[].stalebool—That feed's newest sample is over 1 hour old (measured against now). Top-level updated_at is the newest source and says nothing about any single one — judge a source by its own last_at / stale
summary.binance_tokens / .binance_long_majorityint—Coins with a Binance account ratio / of those, how many are above 1. Computed over the whole table, not the rows shown
tokens_shown / tokens_totalint—Rows returned / rows in the table. Equal on an API key
fullbool—true on an API key; false on the anonymous studio twin
updated_atstringISO 8601 UTCNewest bucket across sources

"Top trader" is a different population at each exchange — do not compare the levels across exchanges.

ExchangeWho counts as a top trader (official wording)
Binance"the top 20% users with the highest margin balance"
OKX"the top 5% of traders with the largest open position value"
Gate.ioNever published — the docs only name the fields

So binance_top_account above okx_top_account says nothing about which venue's big traders are more long. Compare each source against its own history instead.

Errors

StatusBodyWhen
503{"error": "long short ratio data unavailable"}No fresh snapshot — retry later; never read as an empty market

Notes

  • A cross-section, not history. For a series use /long_short_ratio/get_coin (7 days) — there is no long-history endpoint for this dataset.
  • Granularity is 5 minutes, but each source publishes on its own clock — do not describe it as "updates every 5 minutes".
  • The snapshot is the latest bucket each source has published; Gate.io and OKX buckets land about 10 minutes late.

Long/Short Ratio by Coin

GET/long_short_ratio/get_coin
Rate Limit
200 / hour per key, plus the shared 500 / 5 min per key + per IP
Data From
Last 7 days, hourly + the latest 5-minute point
Update
5-minute buckets

One coin, all ten sources: the latest 5-minute value of each, a 7-day hourly series per source, and the Binance perp close on the same frame.

Parameters

NameDescriptionAllowedDefault
symbol
string · queryRequired
Coin. The quote suffix is stripped; the response symbol is the normalised coin nameBTC, BTCUSDT, btc (≤ 32 chars)

Example

Response

{"data": {"latest", "series", "sources", "symbol", "token_id", "updated_at"}}.

FieldTypeUnitDescription
latest.<source key>object / null—{value, ts} — that source's newest 5-minute sample; null when the source does not list the coin
series.bucket_seconds / .daysints / d3600 / 7
series.timestampint[]epoch s168 slots, oldest → newest, one per hour
series.<source key>float[] / nullratioLast sample of each hour; null for an hour with no sample. The whole field is a single null (not an array) for a source that does not list the coin
series.pricefloat[] / nullUSDBinance perp close on the same frame. A single null (with price_symbol / price_multiplier also null) when the coin has no Binance perp
series.price_symbol / .price_multiplierstring / int—Which perp the price came from and its contract multiplier (1000PEPEUSDT → 1000; price ÷ price_multiplier = price per coin)
series.provisional_fromint / nullepoch sFirst slot that can still change (sources finalise up to ~10 min late); null when no source has data
sources[]object[]—The full roster, same fields as the table plus listed
sources[].listedbool—false = that exchange has no such feed for this coin; its latest and series entries are null
symbol / token_id / updated_at——As in the table

Errors

StatusBodyWhen
400{"error": "symbol is required"}symbol missing, blank, over 32 chars, or nothing left after the quote suffix is stripped
404{"error": "<SYMBOL> is not a collected symbol"}No source collects the coin — an answer, not a transient
503{"error": "long short ratio data unavailable"}A listed source could not be read. null only ever means "that venue does not list it"

Notes

  • Covers the long/short-ratio feeds of Binance, OKX, Gate.io and Bybit.
  • The cross-exchange "top trader" caveat on /long_short_ratio/get_table applies here too.
  • 7 days is the whole history this endpoint serves; there is no start_date / end_date.
  • Rate limit — 200 / hour per key. Each call rebuilds seven days of history across ten feeds, so this endpoint has its own lower limit. The 168-slot series changes once an hour; only latest moves in between. For every coin's latest value, call /long_short_ratio/get_table once instead of looping get_coin over coins. Every call with your key counts, including ones that come back 404 — drop symbols that 404 rather than retrying them.
  • About the "anonymous studio twin" in every capture on this page's raw-data endpoints: the studio pages (/studio/charts/...) serve the same payload from the same builder without a key, which is where these examples were taken. They are not a substitute for the API-key endpoints: the tables are cut to 30 coins (full: false), and a coin outside the studio whitelist answers 403 {"error_code": "ERR001", ..., "anon_whitelist": [...]} instead of data. The API-key endpoints documented here have no whitelist and no row cut.
  • Gate.io and OKX buckets land about 10 minutes late.

Open Interest Table

GET/oi_imbalance/get_table
Data From
Snapshot (latest cross-section)
Update
About every 15 minutes

Every collected coin × five exchanges, in USD notional. Basis: USDT-margined perpetuals only, USD notional, one side. An exchange that reports both sides is halved (exchanges[].side_factor, Gate.io = 0.5). Because every value is already USD notional, multiplied contracts (1000PEPE and friends) add across exchanges with no rescaling.

Parameters

None.

Example

Collection start (first stored bucket, measured on BTC 2026-09-22)

ExchangeCollecting since
binance2021-12-01
bingx2025-04-15
gate2026-08-12
okx2026-09-21
bybit2026-09-21

OKX and Bybit are why n_full_7d is 3 of 5 and why their chg_24h was still null on 2026-09-22 — read exchanges[].since / full_7d rather than these dates, which age out.

Response

{"data": {"coins", "exchanges", "total", "summary", "tokens_shown", "tokens_total", "full", "updated_at"}}.

FieldTypeUnitDescription
coins[].token / .token_idstring / int—Coin
coins[].oi_totalfloatUSDSummed across the five exchanges
coins[].chg_1h / .chg_4h / .chg_24hfloat / nullfractionDecimal change (0.0675 = +6.75 %). Each window counts only the exchanges that have a baseline at that window's start, numerator and denominator over the same set; null when none does
coins[].market_capfloat / nullUSDMarket cap; null when there is no usable one
coins[].oi_mcapfloat / nullratiooi_total ÷ market_cap; null when the token has no market cap
coins[].by_exchangeobject—{exchange: {oi, chg_1h, chg_4h, chg_24h}}, one key per exchange; null when the coin is not listed there. A per-window null means that exchange had no baseline that far back — a feed younger than the window
exchanges[]object[]—binance, okx, bingx, bybit, gate — whole-market oi, side_factor, since, full_7d, last_at, stale
exchanges[].since / .full_7dstring / booldateThe feed's first day when it has under 7 days of history (full_7d: false), else null / true. Informational on this table (it has no 7-day window); on /oi_imbalance/get_coin such a feed has no 7 d baseline and is left out of series.total
totalobject—Whole-market oi, chg_1h/4h/24h, n_exchanges, n_full_7d
summary.oi_mcap_leader / _valuestring / float—Highest OI ÷ market cap among the top 100 coins by OI
tokens_shown / tokens_total / full / updated_at——As in the long/short-ratio table

Not the same number as the OI 失衡 indicator. /oi_imbalance/get_overview_data (and the oi_imbalance alpha behind screener conditions and alerts) is a three-exchange aggregate — Binance + OKX + BingX. This table is five exchanges on the basis above. The two oi_total values differ, so a threshold tuned on one does not carry over to the other.

Errors

StatusBodyWhen
503{"error": "open interest data unavailable"}The job has no fresh result (missing or over an hour old) — never a table of zeros

Notes

  • chg_24h: null on OKX / Bybit in the capture above is the young-feed rule, not a gap in the market: those two started on 2026-09-21, so they had no 24 h baseline yet.
  • A cross-section, not history. One coin's last 7 days (hourly, all five exchanges) is /oi_imbalance/get_coin; backtest-length history for one coin on one exchange is /oi_imbalance/get_history.
  • The snapshot carries 1 h / 4 h / 24 h changes. It is rebuilt by a scheduled job about every 15 minutes from 5-minute source buckets; Gate.io and OKX buckets land about 10 minutes late.

Open Interest by Coin

GET/oi_imbalance/get_coin
Rate Limit
200 / hour per key, plus the shared 500 / 5 min per key + per IP
Data From
Last 7 days, hourly + current values
Update
5-minute buckets

One coin's open interest per exchange, on the same basis as the table: current value and share, four change windows with the exchanges each counted, and a 7-day hourly total line.

Parameters

symbol, exactly as in /long_short_ratio/get_coin.

Example

Response

{"data": {"exchanges", "windows", "series", "oi_total", "market_cap", "oi_mcap", "oi_mcap_rank", "tokens_total", "symbol", "token_id", "updated_at"}}.

FieldTypeUnitDescription
exchanges[]object[]—The full five-exchange roster: key, oi (USD), share (of oi_total), chg_1h/4h/24h/7d, side_factor, listed, since, full_7d, last_at, stale
exchanges[].listedbool—false = the coin is not listed there; its values are null
oi_total / market_cap / oi_mcapfloatUSD / ratioAs in the table
oi_mcap_rank / tokens_totalint / null—Rank by oi_mcap in the table job's last round; null when that job has no fresh result
windows.<1h|4h|24h|7d>.chg / .chg_usdfloat / nullfraction / USDChange of the counted exchanges' total
windows.<w>.exchangesstring[]—Which exchanges were counted in that window — a young feed is absent, so 24 h / 7 d can count fewer exchanges than 1 h
series.timestampint[]epoch s168 hourly slots, oldest → newest
series.totalfloat[] / nullUSDTotal OI per slot — only the series.total_exchanges (the full_7d feeds) are in this line, so it is not comparable in level to oi_total. A slot is null when any of those exchanges has no sample that hour; the whole field is null when no exchange is full_7d for the coin
series.total_exchangesstring[]—Which exchanges the line adds up
series.price / .price_symbol / .price_multiplier / .provisional_from——As in /long_short_ratio/get_coin

Errors

400 / 404 / 503 exactly as /long_short_ratio/get_coin, with {"error": "open interest data unavailable"} on 503.

Notes

  • Covers open interest on Binance, OKX, BingX, Bybit and Gate.io.
  • Rate limit — 200 / hour per key, for the same reason as /long_short_ratio/get_coin. For every coin's current open interest, call /oi_imbalance/get_table once instead of looping get_coin over coins.
  • windows["1h"]["exchanges"] having five entries while windows["24h"] has three is the young-feed rule, not missing data — read that list before comparing windows.
  • The OI 失衡 caveat from /oi_imbalance/get_table applies to this oi_total too.
  • Seven days only. For a longer series to backtest on, use /oi_imbalance/get_history (one exchange, coins rather than USD — a different basis from oi_total).
  • Gate.io and OKX buckets land about 10 minutes late.

Open Interest History

GET/oi_imbalance/get_history
Data From
binance 2021-12-01; bybit 2025-08-21; gate 2026-03-28
Update
5-minute buckets

One coin's open interest on one exchange, as a time series you can backtest on — the same basis as the Studio dashboard 未平倉量 card. alpha is one-sided open interest in coins, not USD. Multiplied contracts are converted back to coins (1000PEPE returns a PEPE count). Each bucket is the last reading of its period — open interest is a stock, never summed.

Parameters

NameDescriptionAllowedDefault
symbol
string · queryRequired
Coin, same rule as /oi_imbalance/get_coinBTC, BTCUSDT, btc
period
string · queryRequired
Bucket size. 1w is a 400 (unit not supported); 1m is read as 1min, so it is a 400 for being below 5min{n}min / {n}h / {n}d, minimum 5min (e.g. 5min, 1h, 4h, 1d)
start_date
string · query
First day, inclusiveYYYY-MM-DD (UTC)end_date − 365 days
end_date
string · query
Last day, inclusiveYYYY-MM-DD (UTC)today
oi_exchange
string · query
Whose open interest to readbinance, bybit, gate (case-insensitive)binance

Per-request window: at most 365 days; a longer range is silently clamped (start_date moved to end_date − 365 days, no error), as in /kline.

Example

Response

{"data": {"timestamp", "alpha", "close", "exchanges"}}, parallel arrays, oldest → newest.

FieldTypeUnitDescription
timestampfloat[]Unix seconds (UTC)Bucket start
alphafloat[]coinsOne-sided open interest on oi_exchange, last reading of the bucket
closefloat[]USDTBinance USDT-M perpetual price — per contract unit, so per 1000 coins for 1000PEPE
exchangesstring[]—The exchange actually read, e.g. ["binance"]

alpha × close is not USD open interest on a multiplied contract. close there is the price per contract unit (per 1000 coins for 1000PEPE) while alpha is in single coins — divide close by the multiplier first. For non-multiplied contracts such as BTC, alpha × close ≈ USD open interest.

Gate.io: always send start_date ≥ 2026-03-28 — the default window (end_date − 365 days) starts before Gate's history and is a 400.

Not the same number as /oi_imbalance/get_table / get_coin (five exchanges summed, USD) and not the OI 失衡 indicator (/oi_imbalance/get_overview_data).

Errors

StatusBodyWhen
400{"error": "symbol is required"} / {"error": "period is required"}Missing (a 400 here, not the 403 of the indicator endpoints)
400{"error": "period must be at least 5min, in min / h / d units"}period below 5min (including 1m, read as 1min) or in a unit other than min / h / d (1w)
400{"error": "invalid date format, expected YYYY-MM-DD"}Malformed start_date / end_date
400{"error": "start_date must not be after end_date"}start_date > end_date
400{"error": "oi_exchange must be one of binance, bybit, gate"}oi_exchange outside the list
400{"error": "no <exchange> open interest for <TOKEN> at start_date; this exchange's history may start later — try a later start_date"}The window starts before that exchange's history (see Data from). Without start_date, oi_exchange=gate always hits this until its history passes 365 days (≈ 2027-03) — for Gate always send start_date ≥ 2026-03-28
404{"error": "<TOKEN> is not a collected symbol on <exchange>"}That exchange does not list the coin, the coin has no Binance perpetual, or it is delisted — an answer, not a transient
503{"error": "<exchange> open interest data unavailable for <TOKEN>"}Data could not be read right now — retry

Notes

  • Covers open interest on Binance, Bybit and Gate.io; close is the Binance USDT-M perpetual price.
  • 200 with empty arrays means no bucket in that window (e.g. the coin listed after it) — do not cache it as a permanent "no data".
  • The last bucket keeps moving until its period closes when end_date is today.
  • For history beyond 365 days, send one request per year and concatenate.
  • Resolution is 5 minutes. Each exchange's series starts at the Data from date, or at the coin's listing date on that exchange if later. Currently listed contracts only.

CVD Table

GET/taker_intensity/get_cvd_table
Data From
Snapshot (rolling 1 h / 4 h / 24 h windows)
Update
About every 15 minutes

Taker (market-order) buy and sell turnover per coin, in USD, across three exchanges: Binance from the 5-minute kline's taker-buy quote volume (sell = the bar's total minus it), OKX from its USD taker volume, Gate.io from taker contracts × the same row's multiplier and mark price. Perpetuals only — no spot — and aggregated from 5-minute bars, not from trade-by-trade prints. Each exchange's own reported turnover is used; volume is never multiplied by a price borrowed from another venue.

Parameters

None.

Example

Python
data = requests.get(f"{BASE_URL}/taker_intensity/get_cvd_table", headers=headers, timeout=30).json()["data"]buying = sorted((c for c in data["coins"] if c["net_24h"] is not None), key=lambda c: -c["net_24h"])[:10]print(data["total"]["net_24h"], [(c["token"], c["net_24h"]) for c in buying])# Live capture 2026-09-22 (abridged with ...; anonymous studio twin, same inner shape):# {"coins": [{"token": "BTC", "token_id": 1, "buy_24h": 24607245298.03, "sell_24h": 23128502231.73,#             "net_1h": -212647361.27, "net_4h": -207128163.51, "net_24h": 1478743066.31,#             "by_exchange": {"binance": {"buy_24h": 12663681424.94, "sell_24h": 12135756153.44,#                                         "net_1h": -191133129.94, "net_4h": -217337267.5, "net_24h": 527925271.5},#                             "gate": {...}, "okx": {...}}}, ...],#  "exchanges": [{"key": "binance", "buy_24h": 34978603608.55, "sell_24h": 35112588381.38,#                 "net_24h": -133984772.74, "last_at": "2026-09-22T05:25:00+00:00", "stale": false}, ... 3 rows],#  "total": {"buy_24h": 63543431942.93, "sell_24h": 62491177680.21, "net_24h": 1052254262.8},#  "tokens_shown": 30, "tokens_total": 591, "full": false, "updated_at": "2026-09-22T05:25:00+00:00"}

Collection start (first stored bucket, measured on BTC 2026-09-22)

ExchangeSource fieldCollecting since
binance5-minute kline (taker-buy quote volume)2020-01-01
gatecontract_stats2026-08-12
okxtaker_volume_usd2026-09-21

OKX is additionally capped by the venue keeping only 5 days, so it stays full_7d: false until a week after that date. This table carries no since / full_7d (it has no 7-day window) — read them per coin from /taker_intensity/get_cvd_coin's exchanges[], not from these dates.

Response

{"data": {"coins", "exchanges", "total", "tokens_shown", "tokens_total", "full", "updated_at"}}.

FieldTypeUnitDescription
coins[].token / .token_idstring / int—Coin
coins[].buy_24h / .sell_24hfloat / nullUSDTaker buy / sell turnover over the rolling 24 h, summed over the coin's non-stale exchanges; null when all of them are stale
coins[].net_1h / .net_4h / .net_24hfloat / nullUSDbuy − sell over each rolling window (same null rule)
coins[].by_exchangeobject—{exchange: {buy_24h, sell_24h, net_1h, net_4h, net_24h}}, one key per exchange; null when the coin is not listed there or that exchange's data for it is stale
exchanges[]object[]—binance, okx, gate — whole-market buy_24h, sell_24h, net_24h, last_at, stale
exchanges[].stalebool—That feed's last bar is over an hour old: its windows come back null and it is left out of the totals rather than contributing a sum that silently covers less than the window
totalobjectUSDWhole-market buy_24h, sell_24h, net_24h over the fresh exchanges
tokens_shown / tokens_total / full / updated_at——As in the other raw tables

Errors

StatusBodyWhen
503{"error": "cvd data unavailable"}The job has no fresh result — never zeros

Notes

  • Not the same as the taker_intensity alpha (/taker_intensity/get_alpha), which is a Blave score with years of history. This is raw USD turnover, now.
  • Windows are rolling and end at the last closed 5-minute bar, so net_24h is not a calendar day.
  • Rebuilt by a scheduled job about every 15 minutes from 5-minute source buckets; Gate.io and OKX buckets land about 10 minutes late.

CVD by Coin

GET/taker_intensity/get_cvd_coin
Data From
Last 7 days, hourly + rolling windows
Update
5-minute buckets

One coin's taker buy / sell / net per exchange (same basis as the table) plus a 7-day hourly net and its running cumulative — the CVD line itself.

Parameters

symbol, exactly as in /long_short_ratio/get_coin.

Example

Response

{"data": {"exchanges", "windows", "series", "symbol", "token_id", "updated_at"}}.

FieldTypeUnitDescription
windows.<1h|4h|24h|7d>objectUSD{buy, sell, net} summed over the fresh exchanges
exchanges[]object[]—The full roster: key, listed, windows (same four, per exchange), since, full_7d, last_at, stale
exchanges[].full_7dbool—false = under 7 days of history for this coin there: its 7 d window is null and it is excluded from the 7 d total and from the series. OKX keeps only 5 days, so it is false until a week after the feed's start
series.timestampint[]epoch s168 hourly slots, oldest → newest
series.netfloat[]USDNet taker flow per clock hour, summed over series.exchanges; null for an hour with no data. When series.exchanges is empty every slot is null and cvd stays flat at 0 — the line carries no information then
series.cvdfloat[]USDRunning total of net; cvd[0] = 0 — the line is a shape, not an absolute level
series.exchangesstring[]—Which exchanges the line adds up
series.price / .price_symbol / .price_multiplier / .provisional_from——As in /long_short_ratio/get_coin

Errors

400 / 404 / 503 exactly as /long_short_ratio/get_coin, with {"error": "cvd data unavailable"} on 503.

Notes

  • Covers taker flow on Binance, OKX and Gate.io.
  • series.exchanges being shorter than exchanges[] is the full_7d rule — compare the series against itself, not against windows["24h"], which counts more venues.
  • cvd[0] = 0 by construction: only the slope and the turning points carry information.
  • Gate.io and OKX buckets land about 10 minutes late.

CME Bitcoin / Ether Futures Commitments of Traders (latest)

GET/cme_cot/get_latest
Data From
Latest report only
Update
Weekly, Friday 15:30 US Eastern

The latest weekly CFTC row for each of the four CME crypto futures, plus standard + micro summed in coins per asset. Same shape as one row of /cme_cot/get_history, without price.

Parameters

None.

Example

Python
data = requests.get(f"{BASE_URL}/cme_cot/get_latest", headers=headers, timeout=60).json()["data"]btc = next(c for c in data["contracts"] if c["key"] == "btc")# Live capture 2026-10-07 (abridged):# {"key": "btc", "name": "Bitcoin Futures (CME)", "cftc_code": "133741", "coin": "BTC", "coin_per_contract": 5,#  "latest": {"date": "2026-09-29", "open_interest": 19596, "open_interest_change": -2719,#             "tff": {"leveraged_funds": {"long": 4980, "short": 11836, "spread": 538, "net": -6856,#                                         "long_change": 235, "short_change": -862, "spread_change": -2187, "net_change": 1097},#                     "asset_manager": {"long": 5069, "short": 1483, "spread": 297, "net": 3586, ...}, ...},#             "legacy": {"non_commercial": {...}, "commercial": {...}, "nonreportable": {...}}}}# data["source_updated"] == "Fri, 02 Oct 2026 19:30:08 GMT", data["stale"] == False

Response

{"data": {"contracts": [...], "combined": [...], "report", "units", "source", "source_updated", "fetched_at", "stale"}}

FieldDescription
contracts[]One per contract: key (btc, micro_btc, eth, micro_eth), name, cftc_code, coin, coin_per_contract (5 / 0.1 / 50 / 0.1), latest (a row, see get_history; null if the contract has no rows)
combined[]btc_combined, eth_combined: name, coin, components, units, micro_since, note, latest (a combined row, in coins)
reportfutures_only
unitsUnit of contracts[].latest positions: contracts (× coin_per_contract for coins)
sourceCFTC attribution line — show it with any figure you publish
source_updatedWhen CFTC last updated the dataset
fetched_atWhen Blave fetched it (UTC)
staletrue = CFTC was unreachable and the last stored copy is served

Errors

StatusBodyWhen
503{"error": "CFTC data unavailable. Please retry shortly."}CFTC unreachable and no stored copy

Notes

  • For history use /cme_cot/get_history.
  • Positions are as of Tuesday (Monday when Tuesday is a US holiday) and are published by the CFTC on that week's Friday 15:30 US Eastern; a federal holiday Wednesday–Friday moves the release to the next business day, and a government shutdown delays it by weeks.
  • Server cache: 1 hour.

CME Bitcoin / Ether Futures Commitments of Traders (history)

GET/cme_cot/get_history
Data From
2018-04-10 (btc); other contracts later
Update
Weekly, Friday 15:30 US Eastern

One contract's weekly positioning by trader category. Rows are dated by the report date — the day the positions are as of, usually a Tuesday (a Monday when Tuesday is a US holiday). The data became public later: normally that week's Friday 15:30 ET; a federal holiday Wednesday–Friday moves the release to the next business day, and a government shutdown delays it by weeks (the 2018-12-24 … 2019-02-26 reports came out 2019-02-01 … 03-05; the 2025-09-30 … 2026-01-20 reports 2025-11-19 … 2026-01-23 — CFTC Releases 7864-19 and 9138-25). A backtest must not act on a row before its release.

Parameters

NameDescriptionAllowedDefault
contract
string · query
Single contracts are in contracts; *_combined = standard + micro summed in coinsbtc, micro_btc, eth, micro_eth, btc_combined, eth_combined (case-insensitive)btc
start_date
string · query
First report date, inclusive. Omitted = last year only — pass an early date (e.g. 2018-01-01) for full historyYYYY-MM-DDtoday (UTC) − 365 days
end_date
string · query
Last report date, inclusiveYYYY-MM-DDlatest

Example

Response

{"data": {"contract": {...}, "rows": [...], "price_source", "report", "units", "source", "source_updated", "fetched_at", "stale"}}, rows oldest → newest.

contract: key, name, coin, and cftc_code + coin_per_contract (single contract) or components + micro_since + note (combined).

Each row:

FieldTypeDescription
datestringReport date — usually a Tuesday, a Monday when Tuesday is a US holiday
open_interest / open_interest_changenumberTotal open interest and its week-over-week change
tffobjectGroups dealer, asset_manager, leveraged_funds, other_reportables, nonreportable
legacyobject | nullGroups non_commercial, commercial, nonreportable; null if CFTC has no Legacy row for that week
pricefloat | nullBinance spot BTCUSDT / ETHUSDT UTC daily close on the report date; null when unavailable
includedstring[]Combined contracts only: which contracts this row sums (["btc"] before micro_since)

Each group: long, short, spread (not for nonreportable / commercial), net (= long − short), and long_change, short_change, spread_change, net_change. Units: contracts for a single contract, coins for a combined one. The *_change fields are CFTC's own week-over-week figures, not row-to-row differences — CFTC skips weeks (e.g. government shutdowns), so never diff rows yourself.

Errors

StatusBodyWhen
400{"error": "contract must be one of btc, micro_btc, eth, micro_eth, btc_combined, eth_combined"}Unknown contract
400{"error": "Invalid start_date, expected YYYY-MM-DD"} (or end_date) / {"error": "start_date must not be after end_date"}Bad date / reversed range
503{"error": "CFTC data unavailable. Please retry shortly."}CFTC unreachable and no stored copy

Notes

  • *_combined has a break at micro_since: the week micro joins, the totals step up and that week's *_change includes micro's whole first position. Start a combined backtest after micro_since, or use the single btc / eth contract.
  • Full BTC history is ~440 weekly rows (~0.5 MB) — one request, no paging.
  • Licence: CFTC data is public domain, but CFTC asks to be acknowledged — keep source next to any figure you show. Not endorsed by the CFTC.
  • Start date per contract: btc 2018-04-10, micro_btc 2021-05-04, eth 2021-04-06, micro_eth 2021-12-14. CME's own BTC futures enter the COT on 2018-04-10, not at their 2017-12 launch.
  • Server cache: 1 hour.
  • price is the Binance spot UTC daily close.