kalshi
Kalshi prediction markets: binary event contracts on politics, economy, sports, weather. Use when trading or browsing US regulated event markets (e.g. CPI above 3%, NHL Edmonton vs Florida, jobs report > 200k, election odds).
What this skill does
# Kalshi API
Trade and query the first CFTC-regulated prediction market exchange. Binary yes/no contracts on real-world events priced 1-99 cents.
**Base URL:** `https://external-api.kalshi.com/trade-api/v2`
**Demo URL:** `https://external-api.demo.kalshi.co/trade-api/v2`
Get your API key at https://kalshi.com/account/api-keys (Premier or Market Maker tier required)
## Key Concepts
### Hierarchy: Series > Events > Markets
- **Series** — recurring event templates (e.g., "Monthly Jobs Report", "Weekly Jobless Claims")
- **Events** — specific instances within a series (e.g., "May 2026 Jobs Report")
- **Markets** — individual binary outcomes within an event (e.g., "Will jobs added be above 200k?")
### Binary Contract Pricing
- Prices are in **cents** (1-99), representing implied probability
- A Yes contract at 65c = market implies 65% probability
- Yes bid at price X is equivalent to No ask at (100 - X) — orderbooks show Yes bids and No bids only
- Settlement: pays $1.00 (100 cents) if Yes, $0 if No
- **All monetary values (balance, prices, settlements) are in cents**
### Ticker Format
- **Series:** `KXBTC`, `KXJOBLESS`, `KXINX`
- **Event:** `KXBTC-25MAY30` (series + date)
- **Market:** `KXBTC-25MAY30-T100000` (event + threshold/outcome)
**Sports game tickers** follow a different pattern: `{SERIES}-{YYMONDD}{TEAM1}{TEAM2}-{TEAM}`
- Example: `KXNHLGAME-25MAY12EDMORL-EDM` (NHL, May 12 2025, Edmonton vs Orlando, Edmonton to win)
- Each game event has **two mutually exclusive YES markets** — one per team
### CRITICAL: Series-Based Market Navigation
**DO NOT use `/markets?keyword=` for sports, elections, or any series-based category.** It only surfaces multi-game parlay bundles, not actual game-level markets. Searching "NHL", "Fulham", "Premier League" etc. returns zero or irrelevant results.
**Always navigate: Series → Events → Markets.** Game-level markets live under the series/event hierarchy and must be accessed via `/events?series_ticker=KXXX`. Also, `/markets/{ticker}` may return 404 for game markets — bid/ask prices only appear in the event endpoint response (`/events/{event_ticker}` with `with_nested_markets=true`).
This pattern applies to **all series-based categories**, not just sports:
- **Sports games** — NHL, NBA, NFL, MLB, EPL, etc.
- **Political races** — individual candidate markets within multi-candidate events
- **Company-specific markets** — earnings, CEO changes within a series
- **Recurring economic data** — jobs reports, jobless claims, CPI, etc.
**Known Sports Series Tickers:**
| Sport | Series Ticker | Example |
|-------|---------------|---------|
| NHL | `KXNHLGAME` | `KXNHLGAME-25MAY12EDMORL` |
| NBA | `KXNBAGAME` | `KXNBAGAME-25MAY12BOSLAL` |
| NFL | `KXNFLGAME` | `KXNFLGAME-25SEP07KCDET` |
| MLB | `KXMLBGAME` | `KXMLBGAME-25MAY12NYYLAD` |
| EPL (Premier League) | `KXEPLGAME` | `KXEPLGAME-25MAY12FULARS` |
**Correct workflow for sports:**
```bash
# 1. List open games for a sport
curl -s "https://external-api.kalshi.com/trade-api/v2/events?series_ticker=KXNHLGAME&status=open&with_nested_markets=true"
# 2. Get specific game with live bid/ask
curl -s "https://external-api.kalshi.com/trade-api/v2/events/KXNHLGAME-25MAY12EDMORL?with_nested_markets=true"
# WRONG — do not do this:
# curl -s "https://external-api.kalshi.com/trade-api/v2/markets?keyword=NHL" ← returns parlays, not games
```
## How to Call
Kalshi uses **RSA key-pair signature authentication**. Three headers are required on authenticated requests:
| Header | Value |
|--------|-------|
| `KALSHI-ACCESS-KEY` | API key ID (`$KALSHI_ACCESS_KEY`) |
| `KALSHI-ACCESS-SIGNATURE` | RSA-PSS signature of `timestamp + method + path` |
| `KALSHI-ACCESS-TIMESTAMP` | Unix timestamp (ms) |
**Public GET endpoints** (markets, events, orderbooks) can be called without auth headers.
```bash
# Public endpoint — no auth needed
curl -s "https://external-api.kalshi.com/trade-api/v2/markets?limit=10&status=open"
```
For authenticated endpoints, use direct RSA-PSS signing (**not** the `kalshi_python` SDK — it doesn't work):
```python
import os, time, base64, requests
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
from dotenv import load_dotenv
load_dotenv('/data/workspace/.env')
BASE_URL = "https://api.elections.kalshi.com"
def kalshi_headers(method: str, path: str) -> dict:
import re
raw = os.environ["KALSHI_PRIVATE_KEY"]
# Decode literal escape sequences first (some input channels save '\n' as
# two chars backslash+n instead of a real newline).
raw = (raw.replace('\\r\\n', '\n').replace('\\n', '\n')
.replace('\\r', '\n').replace('\\t', ' '))
# Strip PEM markers if present, then strip ALL whitespace and rewrap.
body = re.sub(r'-----BEGIN[^-]+-----', '', raw)
body = re.sub(r'-----END[^-]+-----', '', body)
body = re.sub(r'\s+', '', body)
wrapped = '\n'.join(body[i:i+64] for i in range(0, len(body), 64))
pem = f"-----BEGIN RSA PRIVATE KEY-----\n{wrapped}\n-----END RSA PRIVATE KEY-----\n"
private_key = serialization.load_pem_private_key(pem.encode(), password=None, backend=default_backend())
ts = str(int(time.time() * 1000))
msg = (ts + method + path).encode() # path must NOT include query string
sig = private_key.sign(msg, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.DIGEST_LENGTH), hashes.SHA256())
return {
"KALSHI-ACCESS-KEY": os.environ["KALSHI_ACCESS_KEY"].strip(),
"KALSHI-ACCESS-TIMESTAMP": ts,
"KALSHI-ACCESS-SIGNATURE": base64.b64encode(sig).decode(),
"Content-Type": "application/json"
}
path = "/trade-api/v2/portfolio/balance"
resp = requests.get(BASE_URL + path, headers=kalshi_headers("GET", path))
print(resp.json()) # {"balance": 5000, ...} — balance is in cents
```
**Signing gotchas:**
- **PSS not PKCS1v15** — PKCS1v15 padding returns 401. Must use PSS with SHA256.
- **Strip query strings before signing** — signature is computed on the bare path only (e.g. `/trade-api/v2/portfolio/balance`), not `/trade-api/v2/portfolio/balance?param=value`. Including query string will 401.
- **Key env var format** — `KALSHI_PRIVATE_KEY` accepts any of: raw base64 body, full PEM with real newlines, or full PEM with newlines collapsed to whitespace (common when pasted through web forms). The helper normalises all formats automatically. For the most robust storage, save as a double-quoted multi-line PEM with `\n` escapes in `.env` so python-dotenv rehydrates it to a real PEM string.
### API Spec
Full OpenAPI spec: https://docs.kalshi.com/openapi.yaml
## Intent Routing
Map user intent to the right endpoint. All paths are relative to the base URL.
### Events
| Method | Endpoint | Primary Params | Description |
|--------|----------|----------------|-------------|
| GET | `/events` | `limit` (1-200), `cursor`, `status`, `series_ticker`, `with_nested_markets` | List events (excludes multivariate) |
| GET | `/events/{event_ticker}` | `event_ticker`, `with_nested_markets` | Get specific event |
| GET | `/events/{event_ticker}/metadata` | `event_ticker` | Event metadata only |
| GET | `/events/multivariate` | `limit`, `cursor`, `series_ticker`, `collection_ticker`, `with_nested_markets` | List multivariate (combo) events |
### Markets
| Method | Endpoint | Primary Params | Description |
|--------|----------|----------------|-------------|
| GET | `/markets` | `limit`, `cursor`, `status`, `ticker`, `event_ticker`, `series_ticker`, `min_close_ts`, `max_close_ts` | List/filter markets |
| GET | `/markets/{ticker}` | `ticker` | Get specific market details |
| GET | `/markets/{ticker}/orderbook` | `ticker`, `depth` | Current orderbook (yes bids + no bids) |
| GET | `/markets/orderbooks` | `tickers` (array, max 100) | Batch orderbooks |
| GET | `/markets/trades` | `ticker`, `limit`, `cursor`, `min_ts`, `max_ts` | TRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.