Skip to content
Recording 4 venues

How to get Kalshi historical data

Kalshi's API gives you past trades, one-minute candles and settled markets, free and without an API key. It does not give you past order books: the order book endpoint shows only the book as it is now.

Checked against Kalshi's API on October 31, 2026.

What Kalshi's API has

DataEndpointWhat you get
MarketsGET /markets, /events, /seriesTickers, rules, open and close times, results. Markets that settled before the cutoff move to GET /historical/markets.
TradesGET /markets/tradesEvery trade: YES price, contracts, the taker's side, trade id and time. Up to 1,000 a page with a cursor; filter by ticker, min_ts and max_ts. Older trades are in GET /historical/trades.
CandlesGET /series/{series}/markets/{ticker}/candlesticks1-minute, 1-hour or 1-day bars (period_interval 1, 60 or 1440) of the YES bid, YES ask and traded price, with volume and open interest. Settled markets past the cutoff: GET /historical/markets/{ticker}/candlesticks.
Order bookGET /markets/{ticker}/orderbookThe book right now: YES bids and NO bids. Nothing from the past.
CutoffGET /historical/cutoffWhen markets, trades and orders move from the live endpoints to the historical ones.

Every path is under https://external-api.kalshi.com/trade-api/v2. A live endpoint stops returning a record once it moves to the historical ones, so a full history reads both.

Every trade in a market

import time
import requests

API = "https://external-api.kalshi.com/trade-api/v2"

def pages(path, key, **params):
    """Every row of a paged endpoint, following the cursor to the end."""
    params["limit"] = 1000
    while True:
        r = requests.get(f"{API}{path}", params=params, timeout=30)
        if r.status_code == 429:  # rate limited: wait, then ask again
            time.sleep(1)
            continue
        r.raise_for_status()
        body = r.json()
        yield from body[key]
        params["cursor"] = body.get("cursor")
        if not params["cursor"]:
            break

ticker = "KXBTC15M-26OCT311945-45"
trades = [
    *pages("/historical/trades", "trades", ticker=ticker),  # before the cutoff
    *pages("/markets/trades", "trades", ticker=ticker),     # after it
]

One-minute candles for the same market, from 7:30 to 7:45 PM Eastern:

candles = requests.get(
    f"{API}/series/KXBTC15M/markets/{ticker}/candlesticks",
    params={"start_ts": 1793489400, "end_ts": 1793490300, "period_interval": 1},
    timeout=30,
).json()["candlesticks"]

for c in candles:
    print(c["end_period_ts"], c["yes_bid"]["close_dollars"], c["yes_ask"]["close_dollars"])

What the API leaves out

  • Past order books. The depth, spread and size at each price at any past moment are gone once the book changes.
  • Top of book between minutes. Candles give the YES bid and ask once a minute, not every change.

Order book history

Kalshi Eye records Kalshi's market feed around the clock: every order book change on every market, every trade and every settlement, 28 billion rows so far. Each UTC day is published the next morning as Parquet files.

  • book_l2: every book change, to rebuild the whole book at any moment.
  • book_snap_1s: the top ten levels each second.
  • bbo and bbo_1m: every top-of-book change, and minute bars.
  • trades and settlements.
from kalshieye import Client, replay_book  # pip install kalshieye

kx = Client()  # reads KALSHIEYE_API_KEY
book = kx.load("book_l2", "2026-10-13", "2026-10-13", tickers=["KXBTC15M-26OCT131200-00"])
for ts, ticker, bids, asks in replay_book(book):
    ...  # the whole book after every change

Questions

Does Kalshi have historical order book data?

Not through its API. GET /markets/{ticker}/orderbook returns the book as it is now. Past books exist only where someone recorded the feed as it changed.

Do I need an API key for Kalshi's market data?

No. Markets, trades, candles and the current order book answer without one. Placing orders and reading your own fills, orders and positions need a key.

How do I get minute-by-minute Kalshi prices?

Call the candlesticks endpoint with period_interval=1. Each candle has the open, high, low and close of the YES bid, the YES ask and the traded price for that minute.

Next