Overview
As trading activity on Kalshi grows, so does the volume of settled markets, completed trades, and fulfilled orders. To keep the live API fast and responsive, Kalshi partitions exchange data into live and historical tiers. Live endpoints return current and recent data: open and recently closed markets, active orders, and recent fills. Older data that is no longer actively referenced is made available through a separate set of historical endpoints. This separation means older data can move from live endpoints to historical endpoints. For positions, the move happens after a buffered, whole-event handoff, so use both position endpoints for a complete history. The partitioning happens for markets, market_candlesticks, trades, orders, and market_positions. Old Events and Series will always still be available through their original endpoints.How It Works
The archive publishes cutoff timestamps throughGET /historical/cutoff. For positions, this is the backfill horizon, not the exact moment a copied position becomes visible in the historical API. A settled position can remain in the live data set while the safety buffer or a market in the same event prevents its handoff.
The cutoff timestamps will be regularly updated, advancing forward over time. Each data type has its own cutoff and the windows differ, so read the field for the data you need rather than assuming one shared window.
Cutoff Timestamps
Resting (active) orders are unaffected and always appear in
GET /portfolio/orders, regardless of the cutoff. Unsettled positions always appear in GET /portfolio/positions. That endpoint defaults to unsettled positions; set settlement_status=settled for settled positions still live, or settlement_status=all for both live states.Historical Endpoints
Impacted Live Endpoints
The following live endpoints stop returning records after those records move to historical storage:Migration Guide
- Fetch the cutoff: call
GET /historical/cutoffto get the current timestamps. - Route queries accordingly: for positions, query both
GET /portfolio/positions?settlement_status=all&subaccount=<number>andGET /historical/positions?subaccount=<number>. The positions endpoints default to subaccount 0, so repeat for each subaccount you need. - Combine results if needed: for positions, page through the live endpoint first, then the historical endpoint. Positions move in that direction during archival, so this order reduces the chance of missing a row that moves between reads. The two reads are not one snapshot: deduplicate by subaccount and ticker, and repeat reconciliation near the handoff if exact completeness matters. An overlap can persist until a handoff retry if the job stops after making the historical copy visible. For fills and other partitioned records, query the corresponding live and historical endpoints.
GET /portfolio/settlements reads only settled positions still in the live data set. After archival, GET /historical/positions provides position, realized P&L, and fee data, but there is currently no historical endpoint with the same settlement-record fields.
The historical endpoints support the same cursor-based pagination as their live counterparts.