| name | kalshi |
| description | Kalshi is a regulated prediction market exchange. Use this skill to interact with the Kalshi API for market data, trading, portfolio management, WebSocket streaming, and historical data retrieval.
|
| metadata | {"author":"Outsharp Inc.","version":"0.1.0"} |
| compatibility | {"requirements":["Internet access","Python 3.7+ (for SDK or direct API usage)","cryptography library (for RSA-PSS request signing)"],"notes":["Most read endpoints are public and require no authentication.","All write endpoints and WebSocket connections require RSA-PSS signed requests.","Requests and responses are JSON.","Prices are in cents (1–99). Monetary values in some WebSocket channels are in centi-cents (1/10,000th of a dollar)."]} |
| allowed-tools | ["Bash(curl:*)","Bash(jq:*)","Bash(python*:*)","Bash(pip*:*)","Bash(npm*:*)","Bash(npx*:*)"] |
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:
https://docs.kalshi.com/llms.txt
Always consult llms.txt 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. |
Full glossary: https://docs.kalshi.com/getting_started/terms.md
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 elections subdomain, the production URL serves ALL Kalshi markets — economics, weather, tech, entertainment, etc.
Demo environment info: https://docs.kalshi.com/getting_started/demo_env.md
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 |
|---|
KALSHI-ACCESS-KEY | Your API Key ID |
KALSHI-ACCESS-TIMESTAMP | Current Unix timestamp in milliseconds |
KALSHI-ACCESS-SIGNATURE | 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.
Full guide: https://docs.kalshi.com/getting_started/api_keys.md
Python Signing Example
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
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 kalshi-python package is deprecated. Migrate to kalshi_python_sync or kalshi_python_async.
SDK overview: https://docs.kalshi.com/sdks/overview.md
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: CreateOrder, CancelOrder, AmendOrder, DecreaseOrder, BatchCreateOrders, BatchCancelOrders. In batch APIs each item counts as 1 transaction (except BatchCancelOrders where each cancel = 0.2 transactions).
Full details: https://docs.kalshi.com/getting_started/rate_limits.md
Pagination
The API uses cursor-based pagination. Responses include a cursor field; pass it as ?cursor={value} on the next request. An empty/null cursor means no more pages. Default page size is 100 (max typically 1000).
Full guide: https://docs.kalshi.com/getting_started/pagination.md
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 |
|---|
/portfolio/orders | POST | Yes | Create an order. Docs: Create Order |
/portfolio/orders | 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.
Historical data guide: https://docs.kalshi.com/getting_started/historical_data.md
Multivariate Collections
Milestones & Structured Targets
Live Data
Search & Discovery
Exchange & Account
Incentive Programs
| Endpoint | Method | Auth | Description |
|---|
/incentives | 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 (KALSHI-ACCESS-KEY, KALSHI-ACCESS-SIGNATURE, KALSHI-ACCESS-TIMESTAMP) 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
{
"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 heartbeat. Clients must respond with Pong frames. Docs: Connection Keep-Alive
Full WebSocket guide: https://docs.kalshi.com/getting_started/quick_start_websockets.md
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 [price, quantity] sorted ascending. The best bid is the last element.
Spread calculation:
- Best YES ask =
100 - best_no_bid
- Spread = Best YES ask − Best YES bid
Full guide: https://docs.kalshi.com/getting_started/orderbook_responses.md
FIX Protocol
Kalshi also supports the Financial Information eXchange (FIX) protocol for low-latency trading:
Common Patterns
Fetch All Open Markets for a Series
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
curl -s "https://api.elections.kalshi.com/trade-api/v2/markets/KXHIGHNY-24JAN01-T60/orderbook" | jq '.orderbook'
Paginate Through All Results
curl -s "https://api.elections.kalshi.com/trade-api/v2/markets?limit=100" > page1.json
CURSOR=$(jq -r '.cursor' page1.json)
curl -s "https://api.elections.kalshi.com/trade-api/v2/markets?limit=100&cursor=$CURSOR" > page2.json
Usage Tips
- Always check
llms.txt 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
cursor 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:
unopened, open, closed, settled.
- 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 |
Full error code table: https://docs.kalshi.com/getting_started/quick_start_websockets.md
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
From its .env.example:
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
git clone https://gitlab.com/outsharp/shipp/alph-bot.git
cd alph-bot
cp .env.example .env
yarn migrate
./index.ts available-games --sport NBA
./index.ts value-bet -d --game <GAME_ID>
./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 /trade-api/v2. Monitor the API Changelog for updates. SDK versions align with the OpenAPI spec and are generally published weekly.