Skip to main content

Overview

Full order book event stream with individual price-level updates and periodic snapshots. Each row is either a price-level update or a full snapshot, distinguished by the message_type column. Available as both CSV (gzip-compressed) and Parquet (zstd-compressed).

Columns

Column
CSV typeParquet typeDescription
exchangestringstringAlways kalshi
tickerstringstringMarket ticker
local_timestampintegerint64Capture timestamp (nanoseconds since epoch)
exchange_timestampstringtimestamp_micros (nullable)Exchange timestamp
message_typestringstringprice_level_update or snapshot
price_level_update_pricedecimalfloat64 (nullable)Price level (update rows only)
price_level_update_quantitydecimalfloat64 (nullable)New quantity at this level (update rows only)
price_level_update_sidestringstring (nullable)bid or ask (update rows only)
snapshot_bid_pricesstringstring (nullable)Comma-separated bid prices (snapshot rows only)
snapshot_bid_sizesstringstring (nullable)Comma-separated bid sizes (snapshot rows only)
snapshot_ask_pricesstringstring (nullable)Comma-separated ask prices (snapshot rows only)
snapshot_ask_sizesstringstring (nullable)Comma-separated ask sizes (snapshot rows only)

Fetching Data

Use the path from the list response. The download endpoint returns a 302 redirect to a signed URL; follow it with curl -L or equivalent.
import requests

def download_complete(path, api_key):
    url = f"https://api.predictiondata.dev/v2/datasets{path}"
    headers = {"x-auth-token": api_key}

    response = requests.get(url, headers=headers, allow_redirects=True)
    response.raise_for_status()

    filename = path.split("/")[-1]
    with open(filename, "wb") as f:
        f.write(response.content)

    print(f"Downloaded to {filename}")

if __name__ == "__main__":
    api_key = "YOUR_API_KEY"
    path = "/kalshi/KXSB-26-NE/complete/2026-02-03.csv.gz"

    download_complete(path, api_key)

Notes

  • Each row is either a price_level_update (one level changed) or a snapshot (full book state). Columns for the other type will be null.
  • The orderbook is the YES orderbook. Bids are the raw YES bids from Kalshi. Asks are calculated by taking 1 - price of the NO bids. If you need the raw, unconverted data, contact calder@predictiondata.dev.
  • Prices and quantities are rounded to 4 decimal places.
  • local_timestamp is nanoseconds since Unix epoch (when our servers captured the message).
  • exchange_timestamp is when the event occurred on Kalshi. It is null for orderbook snapshots. In CSV it is an RFC 3339 string; in Parquet it is stored as TimestampMicros.
  • Each export covers one UTC day (00:00:00 to 23:59:59).