Kalshi API Reference
Kalshi's prediction-market exchange — binary YES/NO contracts on NBA games (winner, spread, and total markets) from the 2025-26 season onward, with event-driven price candles, the public trade tape, and on-exchange settlement results.
Main
series
kalshi.seriesFamilies of related Kalshi binary markets organized around a common theme — all NBA game-winner markets, all NBA spread markets, all NFL totals markets, election markets, weather markets. Tracks series-level metadata and sync state.
GET/api/v1/kalshi/seriesList series for Kalshi
Parameters
limitqueryintegeroptionaldefault 50Page size. Defaults to 50; max 200.
from_idquerybigintoptionalReturn rows with id strictly greater than this value; page using the previous response's `next_from_id`. Omit on the first page.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/series?limit=3'Responses
200series rows matching the declared filter set, wrapped in { series, limit, next_from_id }. next_from_id is the last row's id on a full page — pass it back via ?from_id= to walk the full result; null marks the terminal page.application/jsonshow example ▸
400No declared filter set was satisfied — response body matches MissingRequiredFiltersError; pick one combo from the accepted-sets hint and resend.
application/jsonGET/api/v1/kalshi/series/{id}Get a single sery by id
Parameters
idpathbigintrequiredPrimary key (id) of the sery row.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/series/{pk_value}'Responses
200Single sery row.application/jsonshow example ▸
404Row not found.
events
kalshi.eventsA real-world event that anchors a set of Kalshi markets — for sports, a specific game or matchup; for politics, an election or vote; for finance, a price level on a target date. E.g., MEM@POR game-winner event has 2 markets (MEM wins, POR wins).
GET/api/v1/kalshi/eventsList events for Kalshi
Requires one of:
series_id or league_code or competition_id — requests satisfying none of these return 400.Parameters
series_idquerybigintoptionalFilter to events within a single Kalshi series (e.g., one row of `series` ⇒ all KXNBAGAME events).
competition_idquerybigintoptionalFilter to events linked to a specific competition (cross-schema game or golf tournament; resolved during sync via league_code).
league_codequerystringoptionalFilter to all events for a league (e.g. league_code=nba) — the league-level entry point, mirroring polymarket.events.
limitqueryintegeroptionaldefault 50Page size. Defaults to 50; max 200.
from_idquerybigintoptionalReturn rows with id strictly greater than this value; page using the previous response's `next_from_id`. Omit on the first page.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/events?series_id=1'Responses
200events rows matching the declared filter set, wrapped in { events, limit, next_from_id }. next_from_id is the last row's id on a full page — pass it back via ?from_id= to walk the full result; null marks the terminal page.application/jsonshow example ▸
400No declared filter set was satisfied — response body matches MissingRequiredFiltersError; pick one combo from the accepted-sets hint and resend.
application/jsonGET/api/v1/kalshi/events/{id}Get a single event by id
Parameters
idpathbigintrequiredPrimary key (id) of the event row.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/events/{pk_value}'Responses
200Single event row.application/jsonshow example ▸
404Row not found.
markets
kalshi.marketsAn individual binary contract on Kalshi — a YES/NO question with a defined resolution date and rule, priced between 0 and 100 cents. Stores latest known state (overwritten on sync).
GET/api/v1/kalshi/marketsList markets for Kalshi
Requires one of:
event_id or competition_id — requests satisfying none of these return 400.Parameters
event_idquerybigintoptionalFilter to all markets that belong to a single event (e.g., MEM@POR game-winner event ⇒ two markets, MEM wins and POR wins).
series_idquerybigintoptionalFilter to all markets in a single series (denormalized for direct queries).
competition_idquerybigintoptionalFilter to markets linked to a specific competition — all of its markets in one call.
limitqueryintegeroptionaldefault 50Page size. Defaults to 50; max 200.
from_idquerybigintoptionalReturn rows with id strictly greater than this value; page using the previous response's `next_from_id`. Omit on the first page.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/markets?event_id=1'Responses
200markets rows matching the declared filter set, wrapped in { markets, limit, next_from_id }. next_from_id is the last row's id on a full page — pass it back via ?from_id= to walk the full result; null marks the terminal page.application/jsonshow example ▸
400No declared filter set was satisfied — response body matches MissingRequiredFiltersError; pick one combo from the accepted-sets hint and resend.
application/jsonGET/api/v1/kalshi/markets/{id}Get a single market by id
Parameters
idpathbigintrequiredPrimary key (id) of the market row.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/markets/{pk_value}'Responses
200Single market row.application/jsonshow example ▸
404Row not found.
Markets
market_statuses
kalshi.market_statusesThe trading-status period log for each Kalshi market — one row per state change with start/end timestamps, recording when the market was open, closed, settled, etc. Sparse coverage — captured 2025-10 through 2026-02 for ~1,500 markets; not currently updating.
GET/api/v1/kalshi/market_statusesList market_statuses for Kalshi
Requires one of:
market_id — requests satisfying none of these return 400.Parameters
market_idquerybigintoptionalFilter to status periods for a single Kalshi market by numeric id (resolves to ticker via JOIN to kalshi.markets).
limitqueryintegeroptionaldefault 50Page size. Defaults to 50; max 200.
from_idquerybigintoptionalReturn rows with id strictly greater than this value; page using the previous response's `next_from_id`. Omit on the first page.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/market_statuses?market_id=1'Responses
200market_statuses rows matching the declared filter set, wrapped in { market_statuses, limit, next_from_id }. next_from_id is the last row's id on a full page — pass it back via ?from_id= to walk the full result; null marks the terminal page.application/jsonshow example ▸
400No declared filter set was satisfied — response body matches MissingRequiredFiltersError; pick one combo from the accepted-sets hint and resend.
application/jsonGET/api/v1/kalshi/market_statuses/{id}Get a single market_statuse by id
Parameters
idpathbigintrequiredPrimary key (id) of the market_statuse row.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/market_statuses/{pk_value}'Responses
200Single market_statuse row.application/jsonshow example ▸
404Row not found.
candles
kalshi.candlesOHLC candlestick price summaries for Kalshi markets — the open, high, low, and close prices over standard time bins (1 minute, 5 minute, 1 hour, 1 day), with traded volume per bin. Flattened columns (not JSON) for SQL queryability.
GET/api/v1/kalshi/candlesList candles for Kalshi
Requires one of:
market_id — requests satisfying none of these return 400.Parameters
market_idquerybigintoptionalFilter to candles for a single Kalshi market.
period_intervalqueryintegeroptionalBin width in seconds. Currently every row is period_interval=1 (event-driven captures at up-to-1s resolution, irregular spacing) — resample client-side for fixed OHLC bins.
limitqueryintegeroptionaldefault 50Page size. Defaults to 50; max 200.
from_idquerybigintoptionalReturn rows with id strictly greater than this value; page using the previous response's `next_from_id`. Omit on the first page.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/candles?market_id=1'Responses
200candles rows matching the declared filter set, wrapped in { candles, limit, next_from_id }. next_from_id is the last row's id on a full page — pass it back via ?from_id= to walk the full result; null marks the terminal page.application/jsonshow example ▸
400No declared filter set was satisfied — response body matches MissingRequiredFiltersError; pick one combo from the accepted-sets hint and resend.
application/jsonGET/api/v1/kalshi/candles/{id}Get a single candle by id
Parameters
idpathbigintrequiredPrimary key (id) of the candle row.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/candles/{pk_value}'Responses
200Single candle row.application/jsonshow example ▸
404Row not found.
public_trades
kalshi.public_tradesEvery executed trade on Kalshi — price, size, side (YES or NO), and timestamp, comprising the public market tape. Represents completed market trades across all users.
GET/api/v1/kalshi/public_tradesList public_trades for Kalshi
Requires one of:
market_id — requests satisfying none of these return 400.Parameters
market_idquerybigintoptionalFilter to trades on a single Kalshi market.
limitqueryintegeroptionaldefault 50Page size. Defaults to 50; max 200.
from_idquerybigintoptionalReturn rows with id strictly greater than this value; page using the previous response's `next_from_id`. Omit on the first page.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/public_trades?market_id=1'Responses
200public_trades rows matching the declared filter set, wrapped in { public_trades, limit, next_from_id }. next_from_id is the last row's id on a full page — pass it back via ?from_id= to walk the full result; null marks the terminal page.application/jsonshow example ▸
400No declared filter set was satisfied — response body matches MissingRequiredFiltersError; pick one combo from the accepted-sets hint and resend.
application/jsonGET/api/v1/kalshi/public_trades/{id}Get a single public_trade by id
Parameters
idpathbigintrequiredPrimary key (id) of the public_trade row.
Restores the documented defaults (trial keys only accept the unchanged defaults).
Request
curl -sS --compressed \
-H 'Authorization: Bearer YOUR_API_KEY' \
'https://api.stat-api.com/api/v1/kalshi/public_trades/{pk_value}'Responses
200Single public_trade row.application/jsonshow example ▸
404Row not found.