https://partner-api.bravadotrade.com/market-data/v1. Start with generation discovery and coverage; a market being listed on Kalshi does not mean its history is available here.
Access and signing
Use a Data API credential withanalytics.read, an active Data endpoint and an explicit Kalshi read-only data grant for your organisation. A Trade or Market Data WebSocket credential does not substitute for it. Contact Bravado if the Kalshi data grant is missing; creating a key does not grant venue access.
Sign each GET using HMAC authentication and the signing helpers. Send X-BRAVADO-API-KEY, X-BRAVADO-TIMESTAMP and X-BRAVADO-SIGNATURE. Include the exact canonical path and sorted query in the signature and hash an empty request body. Keep the secret on your server. Normal analytics quotas, key restrictions and credit accounting apply, including discovery reads.
Discover before querying
- Read
/capabilitiesfor the dataset’s supported operations and limits. This endpoint describes stored history, not WebSocket availability. - Read
/generations, followingnext_afterunchanged. Select a valid generation; a published entry or catalog quality alone does not establish query readiness. Some discovery entries require qualification before data reads can succeed. - Read
/coverage?generation=<generation>and/instruments?generation=<generation>. Choose a ticker and a valid anchored capture interval actually reported there. - Query
/books/<ticker>or/history/<ticker>using that generation. Keep it fixed across pages so the dataset cannot change underneath your request.
/instruments response.
Endpoints and query parameters
All paths below start with/market-data/v1. Unknown query parameters are rejected. URL-encode values and sign the resulting canonical path.
Use generation names returned by discovery (1–80 letters, digits,
_ or -). Tickers are case-sensitive, start with an uppercase letter or digit and contain only uppercase letters, digits, . and - (maximum 256 characters).
at, from and until are UTC collector capture-time strings, with up to nine fractional digits: YYYY-MM-DDTHH:mm:ss.nnnnnnnnnZ. Keep them as strings; do not round to milliseconds or send Unix nanoseconds as a JSON number. They are not exchange matching-engine timestamps. from must be at or before until.
Book lookup
/books/{ticker}?generation=<generation> returns that generation’s final retained book, not today’s live book. Add at=<capture-time> for the last observed state on or before that time within an available anchored interval. The returned as_of can precede your requested time; it does not invent an update at that time. Out-of-range, unanchored or gap intervals are refused.
The retained depth represents native YES and NO bid levels. Preserve decimal prices and contract quantities as exact strings. Do not treat a NO bid as a separately observed YES ask, or confuse quantities with dollar volume.
History pages
/history/{ticker} returns initial_book plus points, each containing an observation ordinal and book. The initial state is queried at from, so initial_book.as_of may precede it. Update points cover (from, until]; each book’s as_of is its capture time.
Copy the returned next_after unchanged into after while keeping the generation, ticker and window fixed. For Kalshi history, next_after: 0 means finished; omit after on the first page. For generation and instrument catalogs, an empty next_after means finished. Discovery generation cursors can be opaque and filter-bound: retain the same instrument filter on every page.
Pages have a 2 MiB response bound and can contain fewer entries than limit. This is a paged REST export, not streaming replay.
Coverage and data quality
Coverage is reported per generation, ticker and capture interval. Use/generations and /coverage for the current available dataset rather than assuming one start date or continuous coverage for every market.
Input-digest checks verify retained input integrity. They do not establish complete exchange history or verified upstream manifests. A point observation does not establish a continuous interval around it. Additional archived captures become queryable when their verified generation and index are published.
Errors
An unavailable response is not an empty book. Handle the HTTP status and returnedcode/reason explicitly.
For qualification pending/busy, honor the returned
Retry-After rather than repeatedly polling. Do not substitute a cached book as current data when a query fails.
For live delivery status, see Kalshi coverage. This historical surface does not provide a current native REST book, live trade tape, candles, order placement or a guarantee of every open market.