Kalshi API 完整开发指南 (2026)

2026-05-16

Kalshi API 是美国受 CFTC 监管的事件合约交易所同名 REST + WebSocket 接口,向编程客户端开放数千个二元市场和带鉴权的 portfolio 操作。生产流量走 https://external-api.kalshi.com/trade-api/v2;鉴权方式是用 RSA-PSStimestamp + METHOD + path 做签名,作为三个请求 header 发送。日常工作面覆盖四个家族:公开发现端点(/series/events/markets、orderbooks)、带鉴权 portfolio 端点(/portfolio/balance/portfolio/orders,以及 /portfolio/events/orders 下的 V2 订单端点)、自 2026-02-19 起分区的历史数据 tier,以及实时 WebSocket(wss://external-api-ws.kalshi.com/trade-api/ws/v2)。限流采用 token bucket,Read / Write 双桶独立,五个 tier(Basic 到 Prime)。本指南用 Python、TypeScript 和 cURL 三套可运行示例端到端走完每一块,所有内容基于 docs.kalshi.com(2026-05)校准。

如果你参考的是旧 Kalshi 教程,请先扫一遍 §0 —— 2025 年末到 2026 年有几处技术细节的变化会让旧代码静默失效。

0. 与多数旧 Kalshi 教程的差异

如果你手上的资料停留在 2024 或 2025 年初,先看一份精简的对比表,省一轮调试:

主题旧版(≤ 2025 年初)当前版(2026-05)
签名算法RSA-SHA256 / PKCS#1 v1.5RSA-PSS,MGF1(SHA256),salt = 摘要长度
限流模型RPS 配额,三层Token bucket,每请求默认 10 token,五层(Basic / Advanced / Premier / Paragon / Prime),Read 和 Write 是两个独立桶
429 处理Retry-After header没有 Retry-After、没有 X-RateLimit-* —— 只能纯指数退避
WebSocket 鉴权URL 查询字符串签名WebSocket 握手时通过 HTTP headers(与 REST 同一套)
WebSocket 心跳客户端发起服务端发起;服务端每 10 秒发 Ping(body=heartbeat),客户端回 Pong
订单类型marketlimit当前创建订单示例和 SDK surface 使用 limit orders;不要基于旧 market-order 示例新建集成
Orderbook 结构bids + asks只返回 bids;YES BID @ $0.60 ≡ NO ASK @ $0.40
价格 / 数量字段整数美分(yes_bid: 42),整数 count(count: 10字符串定点(yes_bid_dollars: "0.4200"count_fp: "10.00");旧字段已在 2026 Q1 breaking 移除
公开域名文档在 trading-api.readme.io,旧示例使用 shared API hosts文档迁至 docs.kalshi.com;推荐生产 REST host 是 external-api.kalshi.comapi.elections.kalshi.com 仍作为兼容地址可用

如果上面任意一行让你意外,那这份指南就是为你写的。

一图看懂 Kalshi API 表面

代码之前先建立一份心智地图:

Kalshi API v2
├── REST  →  https://external-api.kalshi.com/trade-api/v2
│   ├── 公开发现(无需鉴权)
│   │   ├── /series, /series/{ticker}
│   │   ├── /events, /events/{ticker}, /events/multivariate
│   │   ├── /markets, /markets/{ticker}
│   │   ├── /markets/{ticker}/orderbook  (只返回 bids)
│   │   ├── /markets/orderbooks?tickers=...  (批量,最多 100 个)
│   │   └── /markets/trades
│   ├── Portfolio(RSA-PSS 鉴权)
│   │   ├── /portfolio/balance
│   │   ├── /portfolio/positions
│   │   ├── /portfolio/settlements
│   │   ├── /portfolio/orders, /portfolio/fills
│   │   └── /portfolio/events/orders/...  (V2 create / amend / decrease / cancel / batched)
│   ├── 历史数据 tier(自 2026-02-19,分区独立)
│   │   └── /historical/{cutoff, markets, trades, fills, orders}
│   └── Account
│       ├── /account/limits           (实时 token-bucket 预算)
│       └── /account/endpoint_costs   (各端点 token 成本)
└── WebSocket  →  wss://external-api-ws.kalshi.com/trade-api/ws/v2
    ├── 公开 channels:ticker、trade、market_lifecycle_v2、multivariate*
    └── 私有 channels(需要鉴权握手):
        orderbook_delta、fill、market_positions、user_orders、...

旧的 host(api.elections.kalshi.comdemo-api.kalshi.co)仍兼容解析,但所有新集成应走上面的 external-api.*

1. 30 秒:第一个 Kalshi API 响应

Kalshi 最快的一次调用根本不需要鉴权。GET /seriesGET /markets 是公开端点 —— 不需要 Key,不需要签名,也不需要时钟同步的机器。挑一个 series ticker,拉它的元数据即可。从这一步出发再决定到底要不要做鉴权(很多分析场景压根用不上)。

curl -sS https://external-api.kalshi.com/trade-api/v2/series/KXHIGHNY \
  | jq '.series | {ticker, title, frequency, category}'
连接 Parlay MCP:
https://mcp.parlay.run/mcp

在你的 AI 客户端里问:
Find Kalshi markets about NYC high temperature and include source links.

预期结果:
Parlay 的只读 MCP 工具返回结构化市场结果,而不是原始 Kalshi JSON。

直接 API 读取 vs 托管 Parlay MCP 研究提示词。

两个开始之前要知道的事:

  1. 推荐生产 REST 域名是 external-api.kalshi.com。旧 shared host api.elections.kalshi.com 仍作为兼容地址可用,并且仍覆盖所有 Kalshi 市场分类,不仅是选举。推荐 demo REST host 是 external-api.demo.kalshi.codemo-api.kalshi.co 仍支持。
  2. 旧的 trading-api.readme.io 文档和 trading-api.kalshi.com 示例已经过时。官方文档在 2025-07-31 迁到 docs.kalshi.com,当前示例使用 external API hosts。还指向旧 URL 的教程和 SDK README 都要谨慎对待。

接下来这份指南假设你访问推荐的生产 REST host,并且想做的事比读单个 series 更有意思。

2. 鉴权:RSA-PSS 签名分步走

Kalshi API 鉴权一段话总结。 本地生成 RSA 密钥对,在 Kalshi 后台上传公钥,把私钥放进 secrets manager。每个鉴权请求拼出消息 timestamp_ms + METHOD + path(path 必须含 /trade-api/v2 前缀、去掉 query string),用 RSA-PSSSHA-256(哈希和 MGF1 都用 SHA-256,salt 长度等于摘要长度 32 字节)签名,签名结果 base64 编码。三个 header 必须带:KALSHI-ACCESS-KEY(你的 key ID)、KALSHI-ACCESS-TIMESTAMP(签名时用的 Unix 毫秒)、KALSHI-ACCESS-SIGNATURE(base64 签名)。公开端点(/series/events/markets、orderbooks)接受但不要求这些 header;/portfolio 下所有端点都需要。

鉴权是大多数 Kalshi 集成卡住一小时然后过几天再卡几分钟的地方。机制并不复杂,但每个细节都得对 —— padding 错了、时间戳单位错了、path 前缀错了,都是同一个不带说明的 401。建议把这五步全读完再写代码。

Step 1 — How the signature is constructed

Kalshi uses RSA-PSS signing, not HMAC and not RSA PKCS#1 v1.5. PSS adds randomized padding (the "salt"); two signatures of the same payload don't match. Use SHA-256 as the hash and as the MGF1 hash, with a salt length equal to the digest length (32 bytes).

The payload you sign is plain ASCII concatenation: timestamp + METHOD + path. Three rules about that payload:

  • timestamp is Unix milliseconds, not seconds.
  • METHOD is the HTTP verb in upper case.
  • path must include /trade-api/v2 and must not include the query string.

Three headers go on every authenticated request:

KALSHI-ACCESS-KEY: <api_key_id>
KALSHI-ACCESS-TIMESTAMP: <unix_ms>
KALSHI-ACCESS-SIGNATURE: <base64-encoded RSA-PSS signature>

Step 2 — Working signing implementation

完整 Python / TypeScript / cURL 实现见英文版 kalshi-api.mdx §2 Step 2。Python 示例按 Kalshi 官方 RSA-PSS 模式写法,TypeScript 与 cURL/OpenSSL 是等价移植;所有示例都使用当前推荐的 external-api.kalshi.com host。

Step 3 — Three real traps

Trap A — clock drift. NTP 不同步会被签名失败拒绝,但返回的是无差别的 401。 Trap B — PEM format. PKCS#8 (-----BEGIN PRIVATE KEY-----) vs PKCS#1 (-----BEGIN RSA PRIVATE KEY-----),两者主流加密库都能加载,但中间环节(Vault、K8s Secret、Slack 复制粘贴)容易丢换行。用 openssl rsa -in key.pem -check -noout 验证。 Trap C — production key management. Kalshi 不存私钥;丢了只能重生成。生产环境用 secrets manager(AWS Secrets ManagerGoogle Secret ManagerHashiCorp Vault),不要塞 ConfigMap 或 git 里的 .env。

Step 5 — Same call, three layers

# 见英文版 §2 Step 5:完整 RSA-PSS 签名 + 游标分页 ≈ 40 行
from kalshi_python_sync import Configuration, KalshiClient
config = Configuration(host="https://external-api.kalshi.com/trade-api/v2")
config.api_key_id = "..."
with open("key.pem", "r") as f:
    config.private_key_pem = f.read()
client = KalshiClient(config)
response = client.get_markets(series_ticker="KXHIGHNY", status="open")
连接 Parlay MCP:
https://mcp.parlay.run/mcp

在你的 AI 客户端里问:
Find active Kalshi weather markets and compare any similar Polymarket markets.
Include market links, current prices if available, and wording differences.

预期结果:
Parlay 返回带来源链接的跨平台归一化市场列表。

原生 API / SDK 路径 vs 托管 MCP 研究工作流。

3. Endpoints that actually matter

Kalshi API 日常工作集一段话总结。 公开发现端点都在 /series/events/markets,以及单市场和批量 orderbook 端点(无需鉴权,orderbook 不含 asks —— 见下方说明)。带鉴权的 portfolio 端点都在 /portfolio/*balancepositionssettlementsordersfills,以及推荐的 V2 订单面 /portfolio/events/orders(create、amend、decrease、cancel、batched)。独立的历史 tier /historical/* 存放 GET /historical/cutoff 返回时间戳之前的已结算市场、fills 和 orders。实时 token-bucket 预算在 GET /account/limits,各端点 token 成本在 GET /account/endpoint_costs。大多数集成日常只碰这十来个端点;其余知道有就行。

完整端点目录见英文版 §3 — 公开端点(/series/events/markets/markets/{ticker}/orderbook)、authenticated portfolio 端点(/portfolio/balance 等)、2026-04-22 新增并推荐使用的 V2 orders 端点(/portfolio/events/orders*),以及 2026-02-19 起的历史数据分区(/historical/cutoff + /historical/{markets,trades,fills,orders})。

Orderbook 关键事实:只返回 bids,没有 asks;最佳 bid 在数组末尾;价格和数量都是字符串定点。下面这块响应直观说明数据形状:

{
  "orderbook_fp": {                  // 定点变体;已替代旧的整数美分字段
    "yes_dollars": [                 // 买 YES 的 bid,按价格升序
      ["0.3900", "5.00"],            // [price_dollars, count_fp]
      ["0.4000", "13.00"],
      ["0.4200", "13.00"]            // ← 最佳 YES bid(数组末尾)
    ],
    "no_dollars": [                  // 买 NO 的 bid,按价格升序
      ["0.5400", "8.00"],
      ["0.5600", "17.00"]            // ← 最佳 NO bid → YES ask = 1.00 − 0.5600
    ]
  }
}

要点:(1) 价格和数量都是字符串(定点),支持亚美分定价和分数合约;旧的 yes_bid / count 整数字段已在 2026 Q1 移除。(2) 数组按价格升序,最佳 bid 是数组最后一个。(3) 响应里没有 YES ask,用对偶性 YES_ask = 1.00 − best_NO_bid 自己算 —— 上例最佳 YES ask 是 1.00 − 0.5600 = $0.4400,spread 是 $0.02。

4. Pagination, rate limits, and token costs

Kalshi API 分页和限流一段话总结。 分页是游标式:所有列表端点接受 cursorlimit,响应里带 cursor,空或缺失即终止 —— 没有总数字段,进度条只能是近似。限流自 2026-04-23 是 token bucket,Read / Write 双桶独立,五个 tier(Basic 200/100、Advanced 300/300、Premier 1000/1000、Paragon 2000/2000、Prime 4000/4000 tokens/s),每请求默认 10 token。两个坑:429 响应没有 Retry-After也没有 X-RateLimit-*(只能用带 jitter 的指数退避),以及批量下单不省 token —— 25 单 batched 同样消耗 250 token。实时预算在 GET /account/limits,各端点 token 成本在 GET /account/endpoint_costs

详见英文版 §4。要点:

  • Cursor-based pagination,没有总数字段。
  • Token bucket(2026-04-23 上线):每请求默认 10 token,5 tier,Read/Write 双桶独立。Basic = 200 read tokens/s(约 20 req/s),100 write tokens/s(约 10 req/s)。多数 Write bucket 可累计约 2 秒 burst,但 Basic Write bucket 只保留 1 秒预算。
  • 429 没有 Retry-After,只能纯指数退避 + jitter。
  • 批量端点不省 token(25 单 × 10 = 250 token),只省往返延迟。
# 见英文版 §4 Step 2:游标持久化 + 指数退避 + jitter + 429/503 区分
连接 Parlay MCP:
https://mcp.parlay.run/mcp

在你的 AI 客户端里问:
Search Kalshi and Polymarket for active NYC weather markets.
Return the best matches with source links and note any missing venue coverage.

预期结果:
Parlay 处理 venue-specific search,并返回统一 schema 的研究结果。

全量 backfill 用原生 paginator;跨平台研究查询用 Parlay 的统一 schema。

5. Real-time data via WebSocket

Kalshi WebSocket 一段话总结。 连接 wss://external-api-ws.kalshi.com/trade-api/ws/v2;鉴权用与 REST 同一套 RSA-PSS 签名,但作为 HTTP header 附在握手请求上,而不是 subscribe 消息里、也不是 URL 查询字符串。订阅时发 JSON {"id":1,"cmd":"subscribe","params":{"channels":["orderbook_delta"],"market_tickers":["..."]}}。公开 channel(tickertrademarket_lifecycle_v2、multivariate)对所有人广播;私有 channel(orderbook_deltafillmarket_positionsuser_ordersorder_group_updatescommunications)需要鉴权过的连接。心跳是服务端发起 —— Kalshi 每 10 秒发一次 Ping,客户端必须回 Pong(大多数库自动处理)。短暂掉线想恢复订阅而不重新订阅,用 2026-04-20 加的 get_snapshot action。废弃的 ticker_v2 channel 已在 2026-02-12 下线,用 ticker

推荐 WebSocket URL:wss://external-api-ws.kalshi.com/trade-api/ws/v2。旧 wss://api.elections.kalshi.com/trade-api/ws/v2 仍作为兼容地址可用。鉴权用握手时的 HTTP headers(不是 query string,签 path = /trade-api/ws/v2)。心跳是服务端发起,每 10 秒一次 Ping。完整代码示例见英文版 §5。

orderbook_delta 是私有频道(消息里带你自己的 client_order_id),但 channel-level 鉴权由 connection-level 鉴权覆盖。断线重连后用 2026-04-20 新加的 get_snapshot action 拿快照,不要尝试手动回放 delta。

# 见英文版 §5:完整 RSA-PSS WebSocket 握手 + 订阅 orderbook_delta ≈ 50 行
连接 Parlay MCP:
https://mcp.parlay.run/mcp

在你的 AI 客户端里问:
Inspect this Kalshi market and compare it with any similar Polymarket market
you can find. Include source links and note whether live pricing is available.

预期结果:
Parlay 返回 snapshot 风格的研究结果。原始实时 delta 仍然直接用 Kalshi WebSocket。

实时 delta 用原生 WebSocket;Parlay 负责跨平台 snapshot 风格研究查询。

6. Common errors and how to fix them

详细分组见英文版 §6(鉴权 / 限流 / 订单 / WebSocket / 数据迁移)。挑几个高频的:

7. Beyond Kalshi: querying across markets

如果你的应用只跟 Kalshi 打交道,官方 kalshi_python_sync / kalshi_python_async / kalshi-typescript 已经覆盖核心 API 和签名逻辑,重新写一遍 RSA-PSS 通常没价值。

差异化的场景从"跨平台"开始:Kalshi 是 Parlay 当前主要覆盖源之一,另外是 Polymarket(链上、EIP-712PolygonUSDC 结算)、Limitless 和 Manifold Markets(玩具币、REST-oriented)。Opinion.trade 当前作为低流动性状态源跟踪,不是 MVP 的 primary venue。每家自己一套鉴权、分页、限流和市场标识符 —— 写多套集成加一层抽象,认真做是真实工作量。

Parlay 的 Model Context Protocol(MCP)server 面向研究工作流做了这一层:市场搜索、发现、对比、差异扫描、平台状态检查和带来源 brief 等只读工具在主要 venue 上使用同一组 schema,市场标识规范化,客户端鉴权统一,可由 Claude 或任何 MCP-aware 客户端调用。Kalshi 特有的 RSA-PSS、定点字段、bids-only orderbook 仍然要在底层处理,但你不用为每个跨平台比较手动归一化。

单平台用官方 SDK;跨平台才是 Parlay 的价值层。

8. 常见问题

9. 下一步

如果你专注 Kalshi,下一步建议看官方 API environments 页rate-limits 页fixed-point 迁移页。如果是多平台,看本站的 Polymarket API 指南,对应 Polymarket 在 Polygon 上的 CLOB API。要让 Claude 或别的 MCP-aware 客户端直接调用所有这些 venue 而不用自己写签名代码,安装 Parlay MCP server 后直接问 AI 就行。