mcpbeat Sign in

Kalshi API Skill for Claude

Kalshi exchange mechanics — RSA-PSS auth, order schema, YES/NO orderbook convention, WebSocket, and endpoint surface. Market-type-agnostic shared layer for all Kalshi skills.

6k tokens
context cost
the whole folder, loaded on every use
5
files
ships runnable scripts
0
copies elsewhere
how many repositories repackaged it
257
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/agiprolabs/claude-trading-skills --skill kalshi-api

The instruction itself

13 sections, as written by the author

Kalshi API

CFTC-regulated US event exchange. USD-denominated binary contracts settle at $1.00 (YES wins) or $0.00 (NO wins). REST + WebSocket, RSA-PSS authentication on every request.

For contract semantics and settlement rules, see the kalshi-weather-markets and kalshi-crypto-index-markets skills. For strategy, sizing, and backtesting, see prediction-market-strategy.


> VERIFY BEFORE CODING.

> The Kalshi API has broken backward compatibility before: the host changed (old trading-api.kalshi.com → dead), and the order schema changed (integer cents → dollar strings). Always smoke-test signing and order bodies against a live response before shipping.

>

> Canonical sources:

> - API reference: <https://docs.kalshi.com> (legacy mirror: <https://trading-api.readme.io>)

> - Official Python starter: <https://github.com/Kalshi/kalshi-starter-code-python>


Overview

  • Base URL: https://api.elections.kalshi.com/trade-api/v2
  • Auth: RSA-PSS on every request — there are no public/unauthenticated endpoints
  • No demo parity: the demo environment (demo-api.kalshi.co) has a near-empty book; use production even for read-only pulls
  • Contracts: $0.01–$0.99 per contract; pay price if YES wins, lose price if NO wins; max payout = $1.00

Quick Start

1. Credentials

KALSHI_KEY_ID=<your-key-uuid>
KALSHI_PRIVATE_KEY_PATH=~/.kalshi/private.pem

Generate the key in the Kalshi dashboard. Store secrets in environment variables or a secrets manager — never in code.

2. Install

pip install httpx cryptography

3. Host + auth (the part everyone gets wrong)

The host and signature format are where implementations break. Three common failures:

  • Using the old trading-api.kalshi.com host → 401
  • Including the query string in the signed path → 401
  • Signing with seconds instead of milliseconds → 401
import os, time, base64, httpx
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

BASE = "https://api.elections.kalshi.com/trade-api/v2"
KEY_ID = os.environ["KALSHI_KEY_ID"]
with open(os.environ["KALSHI_PRIVATE_KEY_PATH"], "rb") as f:
    PRIV = serialization.load_pem_private_key(f.read(), password=None)

def _headers(method: str, path: str) -> dict:
    """path must include /trade-api/v2 prefix and exclude query string."""
    ts = str(int(time.time() * 1000))             # milliseconds
    msg = f"{ts}{method}{path}".encode()
    sig = PRIV.sign(
        msg,
        padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.DIGEST_LENGTH),
        hashes.SHA256(),
    )
    return {
        "KALSHI-ACCESS-KEY": KEY_ID,
        "KALSHI-ACCESS-TIMESTAMP": ts,
        "KALSHI-ACCESS-SIGNATURE": base64.b64encode(sig).decode(),
    }

def get(path: str, params=None):
    # Sign the path only — query goes into params, not the signature
    r = httpx.get(BASE + path, params=params,
                  headers=_headers("GET", "/trade-api/v2" + path))
    r.raise_for_status()
    return r.json()

def post(path: str, body: dict):
    r = httpx.post(BASE + path, json=body,
                   headers=_headers("POST", "/trade-api/v2" + path))
    r.raise_for_status()
    return r.json()

# Example: open markets in a series
markets = get("/markets", params={"series_ticker": "KXHIGHNY", "status": "open"})

Signature spec: RSA-PSS, MGF1 over SHA-256, salt length = PSS.DIGEST_LENGTH. String to sign: {timestamp_ms}{METHOD}{path} where path includes /trade-api/v2 and excludes the query string.

Headers: KALSHI-ACCESS-KEY (UUID), KALSHI-ACCESS-TIMESTAMP (ms), KALSHI-ACCESS-SIGNATURE (base64).

4. Candlestick history

# Returns OHLC for yes_bid / yes_ask + volume + open_interest
# Values are dollar strings: {"close": "0.42"}
candles = get(
    f"/series/KXHIGHNY/markets/{ticker}/candlesticks",
    params={"start_ts": start_epoch, "end_ts": end_epoch, "period_interval": 60},
)

period_interval is in minutes: 1, 60, or 1440.


YES/NO Order-Book Convention

On Kalshi, yes and no are both resting BID ladders — there is no separate ask book. To take the other side you lift the opposing bid:

no_ask  = 1 − best_yes_bid    # cost to buy NO right now (lift YES bids)
yes_ask = 1 − best_no_bid     # cost to buy YES right now (lift NO bids)
P(YES) mid = (best_yes_bid + (1 − best_no_bid)) / 2

Getting this backwards silently inverts every signal. Use the helpers in scripts/kalshi_orderbook.py.

Orderbook response comes in two variants depending on API tier — normalize before using:

{"orderbook": {"yes": [[price, size], ...], "no": [[price, size], ...]}}

If a price value is > 1.0, it is integer cents — divide by 100.


Order Schema

POST /trade-api/v2/portfolio/orders uses fixed-point dollar STRINGS, not integers. The old schema (integer cents, count, yes_price) returns 400 invalid_parameters.

{
  "ticker": "KXHIGHNY-26JUN02-B75.5",
  "action": "buy",
  "side": "yes",
  "count_fp": "1.00",
  "yes_price_dollars": "0.01",
  "client_order_id": "my-strategy-001",
  "time_in_force": "good_till_canceled"
}

Critical field rules — each violation returns 400:

| Field | Rule | Common mistake that 400s |

|---|---|---|

| count_fp | fixed-point string "1.00" | integer count: 1 |

| {side}_price_dollars | dollar string "0.01" | integer cents yes_price: 1 |

| time_in_force | required: good_till_canceled \| immediate_or_cancel \| fill_or_kill | omitted |

| client_order_id | [A-Za-z0-9-] only | . or : in the string — bracket tickers contain ., so never copy the ticker directly |

| type | do not send | "type": "limit" |

For the full order lifecycle (amend, decrease, cancel, batch) and strike_type gotchas, see references/auth-and-orders.md.


Endpoint Summary

| Category | Endpoint | Notes |

|---|---|---|

| Balance | GET /portfolio/balance | — |

| Positions | GET /portfolio/positions | — |

| Orders | GET /portfolio/orders | ?status=resting\|canceled\|executed |

| Place order | POST /portfolio/orders | dollar-string schema above |

| Cancel | DELETE /portfolio/orders/{id} | returns {"order": {...status: "canceled"}} |

| Amend | POST /portfolio/orders/{id}/amend | ticker required in body |

| Decrease | POST /portfolio/orders/{id}/decrease | {"reduce_by_fp": "1.00"} |

| Batch | POST /portfolio/orders/batched | {"orders": [...]} |

| Fills | GET /portfolio/fills | ?limit=N |

| Settlements | GET /portfolio/settlements | ?limit=N |

| Markets | GET /markets | ?series_ticker=&status=open&limit=500 |

| Orderbook | GET /markets/{ticker}/orderbook | ?depth=N |

| Candlesticks | GET /series/{series}/markets/{ticker}/candlesticks | ?start_ts=&end_ts=&period_interval=60 |

| Trades | GET /markets/trades | recent trade prints |

Full endpoint surface, market metadata fields, and rate limits: references/endpoints-and-marketdata.md.

WebSocket discovery pipeline: references/websocket.md.


Files

References

  • references/auth-and-orders.md — RSA-PSS spec, dollar-string order schema, time_in_force, client_order_id sanitization, amend/decrease/cancel lifecycle, strike_type gotcha, fees
  • references/endpoints-and-marketdata.md — Full endpoint table, orderbook variants, market metadata fields (result, open_time, close_time, series_ticker), candlesticks, rate limits
  • references/websocket.md — WS host, discovery pipeline, channels, signing the WS upgrade

Scripts

  • scripts/kalshi_orderbook.py — YES/NO bid-ladder helpers (no_ask, yes_ask, p_yes_mid, overround, kalshi_fee). Pure stdlib, no keys, runs offline.

Other skills for the same job

different authors, same section of the catalogue
MCP Builder
by anthropics
vendor ×13

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

30k tokens scripts
Changelog Generator
by frostant
×9

Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.

774 tokens
Finishing A Development Branch
by ZhanlinCui
×7

Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup

1k tokens
MCP Builder
by JayZeeDesign
×7

Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).

37k tokens scripts
Vercel React Native Skills
by vercel-labs
vendor ×6

React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.

39k tokens
Vercel React Best Practices
by ratacat
×5

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

34k tokens
Next Best Practices
by vercel-labs
vendor ×4

Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling

20k tokens
Using Git Worktrees
by ZhanlinCui
×4

Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification

1k tokens

How to use it

Copy the folder

Take agiprolabs/kalshi-api from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.

Install what it needs

The instructions reference pip. Without those the skill loads but fails at the first command.