Endpoint limits quoted from OKX’s API docs and measured against BTC-USDT-SWAP on November 5, 2026. OKX’s docs remain the authority.
Funding rate history
GET /api/v5/public/funding-rate-historyContract open interest history
GET /api/v5/rubik/stat/contracts/open-interest-historyFunding history came back as 283 settlements, 8 hours apart, from August 3 to November 5, 2026. That matches the three months the docs promise.
Open interest history always came back as the latest 1,440 points, so the bar size decides how far back you get: 5 days of 5-minute bars (October 31 to November 5) and about 60 days of hourly bars (from September 6). Daily bars stopped at 1,041 points, on January 1, 2024, which is the start date the docs give for period=1D. If you need 5-minute open interest from more than 5 days ago, this endpoint doesn’t have it.
One trap with the daily bars: 1D bars open at midnight UTC+8, which is 16:00 UTC. Ask for 1Dutc if you want UTC days, or every daily row will sit 8 hours off a UTC price series.
Delisted swaps vanish from both endpoints. On November 5, 2026, FTT-USDT-SWAP, MATIC-USDT-SWAP and EOS-USDT-SWAP all came back as “Instrument ID doesn’t exist”. So any universe you build from these endpoints is missing the contracts that died, which is the survivorship bias a backtest is supposed to avoid.
import time
import httpx
BASE = "https://www.okx.com/api/v5"
def okx_funding_history(inst_id: str) -> list[dict]:
"""Every funding settlement OKX still serves for one swap, newest first."""
rows, after = [], None
while True:
params = {"instId": inst_id, "limit": 400}
if after:
params["after"] = after
page = httpx.get(f"{BASE}/public/funding-rate-history", params=params).json()["data"]
if not page:
return rows
rows += page
after = page[-1]["fundingTime"]
time.sleep(0.2) # 10 requests per 2 seconds
def okx_open_interest_history(inst_id: str, period: str = "1H") -> list[list[str]]:
"""[ts, oi, oiCcy, oiUsd] rows, newest first: at most 1,440 of them."""
rows, end = [], None
while True:
params = {"instId": inst_id, "period": period, "limit": 100}
if end:
params["end"] = end
page = httpx.get(f"{BASE}/rubik/stat/contracts/open-interest-history", params=params).json()["data"]
if not page:
return rows
rows += page
end = page[-1][0]
time.sleep(0.2)
funding = okx_funding_history("BTC-USDT-SWAP")
open_interest = okx_open_interest_history("BTC-USDT-SWAP", "1H")OKX’s historical market data page offers funding rate files from March 2022 onwards, along with trade history from September 2021, candlesticks from July 2023 and L2 order book data from March 2023. It lists no open interest files.
The open interest and funding datasets come as parquet bars from 1 minute to 1 day, timestamped by the exchange or by when each update reached us, and we never recalculate a bar after publishing it. Open interest comes with its change, volatility and ratio to the price move in each bar. Funding comes as the rate in each bar plus how often it updated.
One request returns links to every monthly or daily file in your date range, so a year of 5-minute bars is one call instead of a paging loop. Pro has high rate limits and 5 years of history. Prime has no rate limits and the full history (pricing). You can try it on real history for free: a free account gets every metric for 2025 on BTC, ETH, SOL and 10 RWA perps, on all three venues, open interest and funding included (catalog).
from datetime import date
from aperiodic import get_metrics
# 2022 at 5 minutes, a year OKX's endpoints no longer serve
oi = get_metrics(
api_key="YOUR_KEY",
metric="open_interest",
exchange="okx-perps",
symbol="perpetual-BTC-USDT:USDT",
interval="5m",
timestamp="exchange",
start_date=date(2022, 1, 1),
end_date=date(2022, 12, 31),
)Also: Binance open interest history API · open interest, every venue · funding rates, every venue