Kalshi is a CFTC-regulated prediction market exchange where you can trade event contracts on politics, economics, weather, and more. Unlike Polymarket (which runs on Polygon), Kalshi is a traditional exchange with USD accounts, bank transfers, and regulatory oversight.
This guide takes you from zero to a working Kalshi trading bot. By the end, you will have a verified account, funded balance, working API credentials, and a minimal bot placing automated trades.
What You Will Learn
- How to create and verify a Kalshi account (including KYC)
- How to fund your account via bank transfer
- How to generate scoped API keys
- How to install and use Kalshi’s Python SDK
- How to write a minimal bot that fetches events and places orders
- How to test on Kalshi’s demo environment before going live
Prerequisites
- US residency. Kalshi requires US citizenship or permanent residency for KYC verification. Non-US traders should use the Polymarket setup guide instead.
- Government-issued ID and SSN. Required for KYC verification.
- A US bank account. For funding via ACH transfer.
- Python 3.10 or later installed on your machine.
- Basic Python knowledge — comfortable with pip, HTTP requests, and JSON parsing.
Step-by-Step Instructions
Step 1: Create Your Kalshi Account and Complete KYC
Go to kalshi.com and create an account. You will need:
- Email address and password
- Full legal name (must match your ID exactly)
- Date of birth
- Social Security Number
- A photo of your government-issued ID (driver’s license, passport, or state ID)
KYC verification typically completes within 1-2 business days. The automated check sometimes clears in minutes. You cannot access the API or trade until KYC is approved.
While waiting for KYC, you can explore Kalshi’s demo environment at demo.kalshi.com with paper money to familiarize yourself with the platform and API.
Step 2: Fund Your Account
Once KYC is approved, add funds via:
- ACH bank transfer (recommended). Free, takes 1-3 business days. Link your bank account in Settings > Funding.
- Wire transfer. Faster (same-day or next-day) but your bank may charge $15-30 for outgoing wires.
- Debit card. Instant but typically has a small fee and lower limits.
Start with $100-500. You can always add more later. The minimum to place a single trade is technically $0.01 (one contract at the lowest price), but practical automated trading needs at least $50-100.
Step 3: Generate API Keys
Navigate to Settings > API Keys in your Kalshi account. Create a new API key with these permissions:
- Read: Enabled (fetch markets, positions, balances)
- Trade: Enabled (place and cancel orders)
- Withdraw: Disabled (never grant to a bot)
Save the API Key ID and Private Key securely. You will not be able to see the private key again after creation.
Store credentials in a .env file:
# .env — do not commit this file
KALSHI_API_KEY_ID=your_api_key_id
KALSHI_PRIVATE_KEY_PATH=/path/to/your/kalshi_private_key.pem
# Or inline:
KALSHI_API_SECRET=your_api_secret
Add to .gitignore:
echo ".env" >> .gitignore
echo "*.pem" >> .gitignore
Step 4: Install Dependencies and Test Connectivity
Install the required Python packages:
pip install requests python-dotenv cryptography
Verify your API connection:
import os
import time
import requests
from dotenv import load_dotenv
load_dotenv()
KALSHI_API_BASE = "https://api.elections.kalshi.com/trade-api/v2"
API_KEY_ID = os.getenv("KALSHI_API_KEY_ID")
API_SECRET = os.getenv("KALSHI_API_SECRET")
def get_authenticated_session():
"""Authenticate with Kalshi and return a session with token."""
session = requests.Session()
resp = session.post(
f"{KALSHI_API_BASE}/login",
json={"email": API_KEY_ID, "password": API_SECRET}
)
if resp.status_code == 200:
token = resp.json()["token"]
session.headers.update({"Authorization": f"Bearer {token}"})
return session
else:
raise Exception(f"Login failed: {resp.status_code} - {resp.text}")
# Test connection
session = get_authenticated_session()
balance = session.get(f"{KALSHI_API_BASE}/portfolio/balance")
print(f"Connected to Kalshi successfully")
print(f"Available balance: ${balance.json()['balance'] / 100:.2f}")
If this prints your balance, you are connected and ready to proceed.
Step 5: Fetch Markets and Understand the Structure
Kalshi organizes contracts by events (a question like “Will inflation exceed 3% in March 2026?”) and markets (specific contracts within that event). Familiarize yourself with the structure:
def fetch_active_events(session, limit=10):
"""Fetch active events from Kalshi."""
resp = session.get(
f"{KALSHI_API_BASE}/events",
params={"status": "open", "limit": limit}
)
events = resp.json().get("events", [])
return events
def fetch_markets_for_event(session, event_ticker):
"""Fetch all markets for a specific event."""
resp = session.get(
f"{KALSHI_API_BASE}/events/{event_ticker}"
)
return resp.json()
# List active events
events = fetch_active_events(session)
for event in events[:5]:
print(f"Event: {event['title']}")
print(f" Ticker: {event['event_ticker']}")
print(f" Category: {event.get('category', 'N/A')}")
print()
# Dive into a specific event
if events:
event_detail = fetch_markets_for_event(session, events[0]["event_ticker"])
for market in event_detail.get("markets", []):
print(f" Market: {market['title']}")
print(f" Ticker: {market['ticker']}")
print(f" Yes bid: ${market.get('yes_bid', 0) / 100:.2f}")
print(f" Yes ask: ${market.get('yes_ask', 0) / 100:.2f}")
print()
Step 6: Write Your Minimal Trading Bot
Here is a complete minimal bot that monitors a market and places an order when the price meets your criteria:
import os
import time
import requests
from dotenv import load_dotenv
load_dotenv()
KALSHI_API_BASE = "https://api.elections.kalshi.com/trade-api/v2"
API_KEY_ID = os.getenv("KALSHI_API_KEY_ID")
API_SECRET = os.getenv("KALSHI_API_SECRET")
# Configuration
MARKET_TICKER = "your-target-market-ticker" # e.g., "FED-RATE-26MAR-T5.25"
MAX_PRICE_CENTS = 45 # buy YES if price <= $0.45
ORDER_SIZE = 10 # number of contracts
PAPER_MODE = True # set False to trade for real
def authenticate():
session = requests.Session()
resp = session.post(
f"{KALSHI_API_BASE}/login",
json={"email": API_KEY_ID, "password": API_SECRET}
)
token = resp.json()["token"]
session.headers.update({"Authorization": f"Bearer {token}"})
return session
def get_market_price(session, ticker):
"""Get current YES ask price for a market."""
resp = session.get(f"{KALSHI_API_BASE}/markets/{ticker}")
market = resp.json().get("market", {})
return market.get("yes_ask", None)
def place_order(session, ticker, side, price_cents, count):
"""Place a limit order on Kalshi."""
order_payload = {
"ticker": ticker,
"action": "buy",
"side": side, # "yes" or "no"
"type": "limit",
"count": count,
"yes_price": price_cents, # in cents
}
resp = session.post(
f"{KALSHI_API_BASE}/portfolio/orders",
json=order_payload
)
return resp.json()
def run():
session = authenticate()
print(f"Bot started. Monitoring {MARKET_TICKER}")
print(f"Will buy YES at <= ${MAX_PRICE_CENTS / 100:.2f}")
print(f"Mode: {'PAPER' if PAPER_MODE else 'LIVE'}")
print()
while True:
try:
yes_ask = get_market_price(session, MARKET_TICKER)
if yes_ask is None:
print(f"[{time.strftime('%H:%M:%S')}] Market not found or no asks")
elif yes_ask <= MAX_PRICE_CENTS:
print(f"[{time.strftime('%H:%M:%S')}] Signal: YES ask ${yes_ask/100:.2f} <= ${MAX_PRICE_CENTS/100:.2f}")
if PAPER_MODE:
print(f" [PAPER] Would buy {ORDER_SIZE} YES @ ${yes_ask/100:.2f}")
else:
result = place_order(session, MARKET_TICKER, "yes", yes_ask, ORDER_SIZE)
print(f" Order result: {result}")
else:
print(f"[{time.strftime('%H:%M:%S')}] YES ask ${yes_ask/100:.2f} — too expensive")
except requests.exceptions.RequestException as e:
print(f"[{time.strftime('%H:%M:%S')}] Network error: {e}")
# Re-authenticate in case token expired
try:
session = authenticate()
except Exception:
pass
except Exception as e:
print(f"[{time.strftime('%H:%M:%S')}] Error: {e}")
time.sleep(30)
if __name__ == "__main__":
run()
Step 7: Test on the Demo Environment First
Kalshi provides a demo environment. Switch your bot to demo mode by changing the base URL:
# For demo/paper trading on Kalshi's sandbox
KALSHI_API_BASE = "https://demo-api.kalshi.co/trade-api/v2"
# For production
# KALSHI_API_BASE = "https://api.elections.kalshi.com/trade-api/v2"
Run the bot against the demo API for 1-3 days. Verify that orders place correctly, fills report accurately, and the bot handles edge cases (market not found, rate limits, session expiry).
Step 8: Go Live and Set Up Monitoring
When demo testing is satisfactory, switch to the production URL, set PAPER_MODE = False, and start with small order sizes (5-10 contracts):
python kalshi_bot.py
For production operation, add basic logging and auto-restart:
import logging
logging.basicConfig(
filename="kalshi_bot.log",
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s"
)
# In your run loop, replace print() with logging.info()
logging.info(f"YES ask ${yes_ask/100:.2f} — order placed")
Use a process manager for auto-restart:
# Using systemd on Linux
sudo cat > /etc/systemd/system/kalshi-bot.service << 'EOF'
[Unit]
Description=Kalshi Trading Bot
After=network.target
[Service]
Type=simple
User=your_username
WorkingDirectory=/home/your_username/kalshi-bot
ExecStart=/usr/bin/python3 kalshi_bot.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable kalshi-bot
sudo systemctl start kalshi-bot
Common Mistakes and How to Avoid Them
Skipping the demo environment. Kalshi is one of the few prediction markets that offers a proper sandbox. Use it. There is no reason to test with real money when a free demo exists.
Granting withdrawal permissions to API keys. A bot never needs to withdraw funds. Scope your API key to read and trade only.
Not handling session expiry. Kalshi API tokens expire. Your bot must detect 401 responses and re-authenticate automatically. The code example above includes this pattern.
Trading illiquid markets. Some Kalshi events have very thin order books. If your bot places a large order on an illiquid market, you will get filled at a poor price. Filter markets by daily volume (minimum $10,000 recommended).
Ignoring Kalshi’s fee structure. Kalshi charges per-contract fees that vary by market. At the maximum ($0.07/contract), your strategy must generate more than $0.07 per contract in expected profit to be viable. Factor fees into every trading decision.
Cost Breakdown
| Cost Category | Typical Range | Notes |
|---|---|---|
| Kalshi account | Free | KYC required (US residents only) |
| Account funding | $100-500 to start | Via ACH (free) or wire ($15-30 bank fee) |
| Python SDK | Free | requests + standard libraries |
| Kalshi trading fees | $0.01-0.07/contract | Varies by market |
| VPS (optional) | $5-15/month | For 24/7 operation |
| Demo environment | Free | Paper trading with demo money |
| Total first-month cost | $110-550 | Mostly initial capital deposit |
Kalshi’s cost structure is different from Polymarket — there are no gas fees or blockchain costs, but per-contract trading fees are explicit and can add up on high-volume strategies.
Next Steps and Related Guides
- Kalshi API Guide — Complete API reference for advanced bot development.
- How to Automate Prediction Market Trading — Platform-agnostic overview covering Kalshi, Polymarket, and more.
- How to Buy a Market-Making Bot for Kalshi — If you want to buy a pre-built bot instead of building from scratch.
- Prediction Market API Reference — Cross-platform API comparison including Kalshi.
- Kalshi Agents Platform Guide — Everything about the Kalshi bot ecosystem.
- Agent Betting Stack — How Kalshi bots fit into the four-layer agent architecture.