1. Make your first public request
You do not need an API key to read the public market and order-book endpoints used here. The production base URL is https://external-api.kalshi.com/trade-api/v2. Start with a small request:
curl --fail --max-time 15 'https://external-api.kalshi.com/trade-api/v2/markets?series_ticker=KXHIGHNY&status=open&limit=5'
The response contains a markets array and may include a cursor. KXHIGHNY is the New York daily high-temperature series used in Kalshi’s own quickstart. An empty array means there are no matching open markets at that moment; choose another current series rather than treating missing quotes as zero.
2. Run the Python quickstart
Download kalshi_quickstart.py. It uses Python 3.10+ and the standard library, with no packages or keys to install. Save it, inspect its source below, then run:
python3 kalshi_quickstart.py --series KXHIGHNY --pages 2
The script requests at most two pages of five markets, removes duplicate tickers, reads one order book and prints the current historical cutoffs. Increase --pages up to five for a bounded experiment. more_available: true explicitly means the result is incomplete. This is a learning sample, not an exhaustive data download.
A collector should persist its cursor and deduplication key with each completed batch. Keep the original filters when adding the returned cursor. Our sample stops on a repeated cursor instead of looping, and has a timeout on every request.
3. Understand prices and available depth
Read orderbook_fp.yes_dollars and no_dollars as arrays of price/quantity pairs. Both values are decimal strings. Use decimal arithmetic rather than interpreting "0.4200" as 42 dollars or rounding fractional quantities to integers.
Kalshi returns bids on each outcome. For a binary dollar contract, the implied YES ask is $1 minus the best NO bid. If the best YES bid is $0.42 and the best NO bid is $0.56, the YES ask is $0.44 and the spread is $0.02. The quantity at that NO bid is the displayed quantity behind the implied YES ask.
Our script selects the highest bid, ignores zero-sized levels, rejects non-finite values and returns null for an empty side. A negative spread deserves investigation; do not silently convert it into an arbitrage signal. Quotes can move before execution, and a top-of-book price does not describe the cost of a larger order.
4. Know when authentication becomes necessary
Private portfolio endpoints and order entry require authentication. Kalshi documents three headers: KALSHI-ACCESS-KEY, KALSHI-ACCESS-TIMESTAMP and KALSHI-ACCESS-SIGNATURE. The signature covers the timestamp in milliseconds, the HTTP method and the path, including /trade-api/v2 but excluding the query string.
Use the signing algorithm that matches your registered key: current documentation covers Ed25519 and RSA-PSS with SHA-256. A PEM header alone is insufficient to distinguish them. Check SDK compatibility before selecting a key type, keep the private key on your server and follow the official authenticated quickstart for your environment. This example deliberately contains no signing or order-submission code.
5. Route old data to the historical API
Call GET /historical/cutoff before planning a historical download. Markets, trades, orders and positions have different cutoff fields. An older settled market absent from /markets may be available through /historical/markets; that absence is not proof it never existed.
Use the cutoff matching your dataset and paginate the corresponding historical endpoint. If a requested time range crosses the boundary, combine both datasets using stable identifiers. Preserve the original timestamps, contract rules and raw values so you can audit later transformations.
Common integration failures
- 401 on a private request: check the environment, key ID, key algorithm, clock and exact signed path. Repeating the same invalid signature will not help.
- 429: stop and respect Retry-After when supplied. For a collector, add bounded backoff with jitter and an overall retry budget. Do not assume one permanent requests-per-second allowance for every tier or endpoint.
- Missing older records: inspect the relevant historical cutoff and both cursor chains.
- Unexpected schema: stop the calculation, retain a redacted response and check the changelog. Missing fields should not become zero-valued trades.
- Timeout during an order request: the outcome can be unknown. Reconcile by client/order identifier before considering a retry; a blind retry can create duplicate exposure.
Build on a working data adapter
Next, use the offline prediction-market bot tutorial to test stale quotes, depth limits and a kill switch without connecting an account. For Polymarket discovery and streaming, use our cross-platform API examples. Keep live-data ingestion separate from the strategy and execution layers.