Kalshi API
Kalshi is a CFTC-regulated prediction market exchange where users trade on the outcomes of real-world events.
Check this skill and the
official documentation FREQUENTLY. The canonical machine-readable index of all docs lives at:
Always consult
to discover every available page before building. It is the single source of truth for endpoint references, SDK docs, WebSocket channels, FIX protocol details, and getting-started guides.
Key Concepts (Glossary)
| Term | Definition |
|---|
| Market | A single binary outcome contract (Yes / No) with prices in cents (1–99¢). |
| Event | A collection of related markets representing a real-world occurrence (e.g., an election, a weather reading). |
| Series | A template for recurring events that share the same structure and rules (e.g., "Daily Highest Temp in NYC"). |
| Orderbook | Bids only — in binary markets a YES bid at X¢ is equivalent to a NO ask at (100−X)¢. |
| Fill | A matched trade on one of your orders. |
| Settlement | The final resolution of a market (Yes or No) after determination. |
| Multivariate Event | A combo event created dynamically from a multivariate event collection. |
Base URLs
| Environment | REST API | WebSocket |
|---|
| Production | https://api.elections.kalshi.com/trade-api/v2
| wss://api.elections.kalshi.com/trade-api/ws/v2
|
| Demo | https://demo-api.kalshi.co/trade-api/v2
| wss://demo-api.kalshi.co/trade-api/ws/v2
|
Note: Despite the
subdomain, the production URL serves ALL Kalshi markets — economics, weather, tech, entertainment, etc.
Documentation & References
All detailed examples, request/response schemas, and walkthroughs live in the official docs. Always consult these before building:
Authentication
Kalshi uses RSA-PSS signed requests (not Bearer tokens). Every authenticated request requires three headers:
| Header | Value |
|---|
| Your API Key ID |
| Current Unix timestamp in milliseconds |
| Base64-encoded RSA-PSS signature of {timestamp}{METHOD}{path}
|
Important: When signing, use the path
without query parameters. For example, sign
/trade-api/v2/portfolio/orders
even if the request URL is
/trade-api/v2/portfolio/orders?limit=5
.
Generating API Keys
- Log in → Account Settings → API Keys section.
- Click "Create New API Key" to generate an RSA key pair.
- Store the private key immediately — it cannot be retrieved again.
Python Signing Example
python
import base64, datetime, requests
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
def load_private_key(file_path):
with open(file_path, "rb") as f:
return serialization.load_pem_private_key(f.read(), password=None)
def sign_pss(private_key, text: str) -> str:
sig = private_key.sign(
text.encode("utf-8"),
padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.DIGEST_LENGTH),
hashes.SHA256(),
)
return base64.b64encode(sig).decode("utf-8")
def kalshi_headers(key_id, private_key, method, path):
ts = str(int(datetime.datetime.now().timestamp() * 1000))
path_no_qs = path.split("?")[0]
sig = sign_pss(private_key, ts + method + path_no_qs)
return {
"KALSHI-ACCESS-KEY": key_id,
"KALSHI-ACCESS-SIGNATURE": sig,
"KALSHI-ACCESS-TIMESTAMP": ts,
}
JavaScript Signing Example
javascript
const crypto = require("crypto");
const fs = require("fs");
function signPss(privateKeyPem, text) {
const sign = crypto.createSign("RSA-SHA256");
sign.update(text);
sign.end();
return sign.sign({
key: privateKeyPem,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST,
}).toString("base64");
}
function kalshiHeaders(keyId, privateKeyPem, method, path) {
const ts = Date.now().toString();
const pathNoQs = path.split("?")[0];
const sig = signPss(privateKeyPem, ts + method + pathNoQs);
return {
"KALSHI-ACCESS-KEY": keyId,
"KALSHI-ACCESS-SIGNATURE": sig,
"KALSHI-ACCESS-TIMESTAMP": ts,
};
}
SDKs
Kalshi provides official SDKs. Prefer these for production integrations:
The old
package is
deprecated. Migrate to
or
.
For production applications, consider generating your own client from the
OpenAPI spec.
Rate Limits
| Tier | Read | Write |
|---|
| Basic | 20/s | 10/s |
| Advanced | 30/s | 30/s |
| Premier | 100/s | 100/s |
| Prime | 400/s | 400/s |
Write-limited endpoints:
,
,
,
,
,
. In batch APIs each item counts as 1 transaction (except
where each cancel = 0.2 transactions).
Pagination
The API uses
cursor-based pagination. Responses include a
field; pass it as
on the next request. An empty/null cursor means no more pages. Default page size is 100 (max typically 1000).
REST API Endpoints Overview
Below is a summary organized by domain. For full request/response schemas, see the linked docs or browse
https://docs.kalshi.com/llms.txt.
Markets
Events
Orders (Authenticated)
| Endpoint | Method | Auth | Description |
|---|
| POST | Yes | Create an order. Docs: Create Order |
| GET | Yes | List your orders (resting/canceled/executed). Docs: Get Orders |
/portfolio/orders/{order_id}
| GET | Yes | Get a single order. Docs: Get Order |
/portfolio/orders/{order_id}
| DELETE | Yes | Cancel an order. Docs: Cancel Order |
/portfolio/orders/{order_id}/amend
| POST | Yes | Amend price/count. Docs: Amend Order |
/portfolio/orders/{order_id}/decrease
| POST | Yes | Decrease contract count. Docs: Decrease Order |
/portfolio/orders/{order_id}/queue_position
| GET | Yes | Queue position. Docs: Get Order Queue Position |
/portfolio/orders/queue_positions
| GET | Yes | Queue positions for all resting orders. Docs: Get Queue Positions for Orders |
/portfolio/orders/batched
| POST | Yes | Batch create (up to 20). Docs: Batch Create Orders |
/portfolio/orders/batched
| DELETE | Yes | Batch cancel (up to 20). Docs: Batch Cancel Orders |
Portfolio (Authenticated)
Subaccounts (Authenticated)
Order Groups (Authenticated)
Order groups apply a rolling 15-second contracts limit; when hit, all orders in the group are auto-cancelled.
Communications / RFQ (Authenticated)
Historical Data (Authenticated)
Historical data is for archived markets, orders, and fills that have moved past cutoff timestamps.
Multivariate Collections
Milestones & Structured Targets
Live Data
Search & Discovery
Exchange & Account
Incentive Programs
| Endpoint | Method | Auth | Description |
|---|
| GET | No | List incentives. Docs: Get Incentives |
WebSocket API
A single authenticated WebSocket connection provides real-time streaming. Subscribe to channels by sending JSON commands.
Connection
wss://api.elections.kalshi.com/trade-api/ws/v2 (production)
wss://demo-api.kalshi.co/trade-api/ws/v2 (demo)
Authentication headers (
,
,
) must be included during the handshake. Sign the string
{timestamp}GET/trade-api/ws/v2
.
Available Channels
*The connection itself always requires authentication, even for public channels.
Subscribe Command
json
{
"id": 1,
"cmd": "subscribe",
"params": {
"channels": ["ticker", "orderbook_delta"],
"market_tickers": ["KXHIGHNY-24JAN01-T60"]
}
}
Keep-Alive
Kalshi sends Ping frames every 10 seconds with body
. Clients must respond with Pong frames. Docs:
Connection Keep-Alive
Orderbook Structure
Kalshi orderbooks return bids only (no asks). In binary markets:
- A YES bid at X¢ = a NO ask at (100−X)¢
- A NO bid at Y¢ = a YES ask at (100−Y)¢
Each entry is
sorted ascending. The best bid is the
last element.
Spread calculation:
- Best YES ask =
- Spread = Best YES ask − Best YES bid
FIX Protocol
Kalshi also supports the Financial Information eXchange (FIX) protocol for low-latency trading:
Common Patterns
Fetch All Open Markets for a Series
bash
curl -s "https://api.elections.kalshi.com/trade-api/v2/markets?series_ticker=KXHIGHNY&status=open" | jq '.markets[] | {ticker, title, yes_price, volume}'
Get Orderbook for a Market
bash
curl -s "https://api.elections.kalshi.com/trade-api/v2/markets/KXHIGHNY-24JAN01-T60/orderbook" | jq '.orderbook'
Paginate Through All Results
bash
# First page
curl -s "https://api.elections.kalshi.com/trade-api/v2/markets?limit=100" > page1.json
# Extract cursor for next page
CURSOR=$(jq -r '.cursor' page1.json)
# Next page
curl -s "https://api.elections.kalshi.com/trade-api/v2/markets?limit=100&cursor=$CURSOR" > page2.json
Usage Tips
- Always check first: https://docs.kalshi.com/llms.txt has every endpoint and guide.
- Use the demo environment for testing — credentials are separate from production.
- Never hardcode API keys — use environment variables or secure key storage.
- Prices are in cents (1–99). Monetary values in WebSocket position channels are in centi-cents (divide by 10,000 for dollars).
- Sign paths without query parameters. Strip everything after before signing.
- Handle pagination — always check for a non-null and loop until exhausted.
- Respect rate limits — implement exponential backoff on 429 responses.
- Combine REST + WebSocket for the most accurate state: use REST for initial snapshots and WebSocket for real-time deltas.
- Orderbook is bids-only — derive asks via the 100−price complement.
- Historical vs. Live data: Check cutoff timestamps to know whether to query live or historical endpoints.
- For market status values, use: , , , .
- Batch operations count against per-second write limits per item.
Error Handling
Standard HTTP error codes apply. The API returns JSON error bodies with descriptive messages. Implement retry with backoff for 429 (rate limited) and 5xx (server errors).
WebSocket Error Codes
| Code | Meaning |
|---|
| 1 | Unable to process message |
| 2 | Params required |
| 3 | Channels required |
| 5 | Unknown command |
| 8 | Unknown channel name |
| 9 | Authentication required |
| 14 | Market ticker required |
| 16 | Market not found |
| 17 | Internal error |
| 18 | Command timeout |
Example Project: Alph Bot
Alph Bot is an open-source automated trading bot that demonstrates a production-quality integration of the Kalshi API alongside
Shipp for real-time sports data and Claude AI for probability estimation.
How Alph Bot Uses Kalshi
- Market discovery — Searches for Kalshi event contracts related to a live sports game (e.g., NBA point spreads, totals).
- Orderbook reading — Fetches orderbook data to determine current market-implied probabilities (prices in cents map directly to implied %).
- Edge detection — Compares Kalshi market prices against AI-estimated probabilities powered by Claude + Shipp real-time game data.
- Order execution — Places limit orders when sufficient edge is found, using Kelly Criterion for position sizing.
- Risk management — Enforces circuit breakers (max daily loss), position size limits, single-market exposure caps, and minimum account balance thresholds.
Alph Bot's Kalshi Configuration
ALPH_BOT_KALSHI_API_KEY_ID=abc123
ALPH_BOT_KALSHI_PRIVATE_KEY_PATH=./keys/kalshi-private.pem
# Strategy
ALPH_BOT_MIN_EDGE_PCT=5
ALPH_BOT_MIN_CONFIDENCE=medium
ALPH_BOT_KELLY_FRACTION=0.25
# Risk controls
ALPH_BOT_MAX_TOTAL_EXPOSURE_USD=10000
ALPH_BOT_MAX_POSITION_SIZE_USD=1000
ALPH_BOT_MAX_SINGLE_MARKET_PERCENT=20
ALPH_BOT_MAX_DAILY_LOSS_USD=500
ALPH_BOT_MAX_DAILY_TRADES=50
ALPH_BOT_MIN_ACCOUNT_BALANCE_USD=100
Try It
bash
git clone https://gitlab.com/outsharp/shipp/alph-bot.git
cd alph-bot
cp .env.example .env
# Add your Kalshi, Shipp, and Anthropic API keys
yarn migrate
# Find a game to trade on
./index.ts available-games --sport NBA
# Run value betting in demo mode (uses Kalshi demo environment)
./index.ts value-bet -d --game <GAME_ID>
# Run in paper mode (no real orders executed)
./index.ts value-bet --paper --game <GAME_ID>
Warning: Trading on Kalshi involves real money when not in demo/paper mode. Always start with a
demo account.
See the
Alph Bot README for full setup instructions.
Versioning
The current API version is
v2 under
. Monitor the
API Changelog for updates. SDK versions align with the
OpenAPI spec and are generally published weekly.