Kalshi API Rate Limits and WebSockets: A Bot Builder's Guide

If you are building a bot for Kalshi's 15-minute crypto markets, the two API details that decide whether it works are the rate limits and the WebSocket feed. Get them wrong and your bot either gets throttled with 429 Too Many Requests at the exact moment a market moves, or it trades on an order book that stopped updating 20 seconds ago. This guide covers how Kalshi's token-bucket limits work, how to budget a bot against them, and how to use the WebSocket API so you poll less and see more. Everything here was checked against docs.kalshi.com on October 23, 2026.

New to the markets themselves? Start with Kalshi 15-minute markets explained and the Kalshi API tutorial in Python, then come back here.

How Kalshi rate limits work: tokens, not request counts

Kalshi does not give you "N requests per minute." Every authenticated request costs tokens, and your account tier sets a budget: how many tokens per second refill into your balance. Most requests cost the default of 10 tokens. Some cost less; for example, Kalshi's docs list a batch cancel at 2 tokens per order. The authoritative list of non-default costs is the GET /account/endpoint_costs endpoint, so a careful bot reads it rather than hard-coding numbers.

Your sustained rate for any endpoint is simply:

sustained requests per second = budget ÷ cost

Two separate buckets: Read and Write

You have two independent budgets:

  • Read: GET endpoints (markets, order books, positions, fills) and anything not routed to Write.
  • Write: placing, amending and cancelling orders, order groups, and the RFQ quote flow.

The split is by what the request does, not how it is sent. REST and FIX requests drain the same buckets. Polling the order book too hard therefore cannot block your order placement, but it can stop you reading positions and fills. And GET /portfolio/balance sits in its own small bucket: once per second on the Basic and Advanced tiers. Kalshi's own advice is to react to fills and settlements (for example through the fills WebSocket channel) instead of polling balance.

The tier table

Per-second token budgets for event contracts (predictions), from Kalshi's rate-limit page:

Tier Read budget Write budget Orders/sec at 10 tokens
Basic 200 100 10
Advanced 300 300 30
Expert 600 600 60
Premier 1,200 1,200 120
Paragon 2,400 2,400 240
Prime 4,800 4,800 480
Prestige 12,000 9,600 960

Basic is what you get at signup. Advanced is available by calling Kalshi's "Upgrade Account API Usage Level" endpoint. The higher tiers are granted automatically from trading volume (your trailing 30-day volume as a share of exchange volume, reviewed daily) or assigned by Kalshi. You can see your current tier and grants with GET /account/limits.

Bursting: why an idle bot can fire a block of orders

Each budget is a token bucket that refills continuously; there are no fixed windows or per-second resets. Bucket size matters:

  • Basic and Advanced Read buckets, and Write buckets above Basic, hold three seconds of budget. After three quiet seconds the bucket is full and you can spend up to 3× your per-second budget at once.
  • The Basic Write bucket holds only one second of budget. Idle time banks nothing beyond that.

Worked example (Basic tier): your Write bucket refills at 100 tokens/second and holds 100. You can send 10 default-cost orders in one instant, then 10 per second after that. On Advanced, the Write bucket refills at 300/second and holds 900, so after three idle seconds you could send 90 orders at once, then 30 per second.

For a 15-minute crypto bot this is usually plenty. A bot trading BTC, ETH, SOL and XRP 15-minute markets that places one entry and maybe one cancel per market per window needs a handful of writes every 15 minutes. You hit the limit only with loops that re-quote or cancel-and-replace on every tick.

Batch endpoints do not save tokens

This catches many bot builders. Batch requests cost the same as the individual calls: Kalshi's docs give 25 batched order creates as 25 × 10 = 250 tokens. Worse, the whole batch must fit in the bucket at once. On Basic, where the Write bucket holds 100 tokens, a 25-order create batch needs 250 tokens and will be rejected whole, every time. Batching helps with round trips, not with your budget.

What a 429 looks like and how to handle it

A throttled request returns HTTP 429 with the body {"error": "too many requests"}. Per the docs, 429s currently carry no Retry-After or X-RateLimit-* headers and there is no penalty or cooldown: the next request succeeds once the bucket refills enough. Kalshi recommends exponential backoff. In practice, a good bot also:

  • Budgets itself on the client side, keeping a local token counter that mirrors the server's, so it rarely sees a 429 at all.
  • Gives writes priority. If a cancel is waiting, it goes before a nice-to-have refresh.
  • Never retries an order blindly. A timeout is not a rejection. Send a client_order_id and check your open orders before you re-send, or you risk a duplicate position.

Exchange shards and per-shard Write budgets

Kalshi runs prediction markets across exchange shards, and each market reports an exchange_index. When we pulled an open BTC 15-minute market (series KXBTC15M) from the public markets endpoint this evening, it reported exchange_index: 2. That matters for budgets: a single REST order create, cancel, decrease or amend that targets shard 1 or higher draws from a Write bucket scoped to that shard, and each shard's bucket carries your full tier budget. Shard 0 bills your unscoped Write bucket. Auto-routed traffic (exchange_index: -1, or omitted when market_ticker is given) is billed to every shard's bucket. Batch creates and cancels always bill the unscoped bucket.

The practical takeaway: if your bot trades markets on more than one shard, passing the market's own exchange_index on single orders keeps each shard's traffic in its own budget instead of charging all of them.

Use the WebSocket API instead of polling

The fastest way to burn your Read budget is to poll the order book of four markets every 250 ms: that is 16 requests and 160 tokens per second, most of your 200-token Basic Read budget, for data that often hasn't changed. Kalshi's WebSocket API pushes changes to you instead: one subscription replaces that whole polling loop, and your Read budget is left for the occasional REST call.

Connecting

The production WebSocket endpoint is wss://external-api-ws.kalshi.com/trade-api/ws/v2 (demo: wss://external-api-ws.demo.kalshi.co/trade-api/ws/v2; the older shared hosts are still supported). The handshake is authenticated with the same three headers as REST: KALSHI-ACCESS-KEY, KALSHI-ACCESS-TIMESTAMP (milliseconds) and KALSHI-ACCESS-SIGNATURE. The signature is over timestamp + "GET" + "/trade-api/ws/v2", signed with your Ed25519 key (Kalshi's recommended type) or with RSA-PSS SHA-256 for an RSA key.

Channels that matter for a 15-minute bot

  • orderbook_delta (private): an orderbook_snapshot first, then incremental orderbook_delta messages for the markets you list.
  • ticker (public data): best yes bid/ask and last price updates.
  • trade: executions as they print.
  • fill and market_positions (private): your own fills and positions, which replace most portfolio polling.
  • market_lifecycle_v2: markets opening, closing and settling, which is how a bot knows the next 15-minute window exists without polling the markets list.

You subscribe by sending a command such as:

{"id": 1, "cmd": "subscribe",
 "params": {"channels": ["orderbook_delta"],
            "market_tickers": ["KXBTC15M-..."]}}

Each subscription gets a server-generated sid. You can add or remove markets with update_subscription, and ask for a fresh snapshot with its get_snapshot action without changing the subscription.

Sequence numbers: how to know your book is real

This is the part most homemade bots skip. Every snapshot and delta carries a seq, and per Kalshi's docs seq counts messages on one subscription only. If you see a gap (seq 41 followed by seq 43), you missed a message and your local book is wrong. Don't keep trading on it: request a new snapshot and rebuild. Messages also carry an exchange clock, which is the same on every connection. That lets you match updates across two redundant connections. Clocks skip values and are not comparable across markets, so always use seq to detect gaps.

Two more details worth building in:

  • Kalshi's book lists bids on both sides. The snapshot has YES bids and NO bids. The YES ask is $1 minus the best NO bid. (Our guide to reading the Kalshi order book walks through it.)
  • Keep-alive. Kalshi notes that Python's websockets library answers ping/pong frames automatically; other libraries may need you to handle them. Either way, plan for disconnects: on reconnect, re-sign, re-subscribe and wait for a fresh snapshot before trading.

A sane budget for a four-market 15-minute bot

Here is a design that fits comfortably inside the Basic tier:

  1. One WebSocket connection subscribed to orderbook_delta and ticker for the current BTC, ETH, SOL and XRP 15-minute markets, plus fill, market_positions and market_lifecycle_v2.
  2. REST reads only on events: when a new window opens (lifecycle message), read that market's details once. That is a few reads per 15 minutes, not per second.
  3. Writes: at most a few per market per window, such as one limit order and an occasional cancel. Even 20 writes in a burst spread over a couple of seconds stays under 100 tokens/second.
  4. A local token counter for both buckets, with writes taking priority and backoff on any 429.

Rate limits and data freshness are only half the job, though. The other half is whether a trade is worth taking after fees. At a 50¢ price Kalshi's trading fee works out to about 2¢ per contract after rounding, and near 90¢ a single loss wipes out many small wins. See Kalshi fees and breakeven win rate for the math.

Build it or start from one that's already built

Everything above is buildable in a weekend if you enjoy it, and the Kalshi docs are good. If you'd rather see a working bot first, DeskBot for Kalshi ($19.99/month) runs on your own Windows or Mac machine with your own Kalshi API key, so the market feed and order plumbing are already done. You choose the settings and decide whether it trades.

FAQ

What is the Kalshi API rate limit?

It's token-based. Most requests cost 10 tokens. The Basic tier refills 200 Read tokens and 100 Write tokens per second, so about 20 reads and 10 order actions per second at the default cost. Higher tiers raise both.

Does the Kalshi API return a Retry-After header on 429?

Not currently. Kalshi's docs say 429 responses have no Retry-After or X-RateLimit-* headers and no cooldown. Back off exponentially and retry once the bucket has refilled.

Do Kalshi batch orders reduce rate-limit usage?

No. Each item is billed separately, and the whole batch must fit in your bucket at once. On Basic, a 25-order create batch (250 tokens) is larger than the 100-token Write bucket and will be rejected.

How do I get a higher Kalshi API tier?

Advanced is self-serve through the API usage-level upgrade endpoint. Expert and above are granted automatically from your 30-day trading volume share, reviewed daily, or assigned by Kalshi.

What is the Kalshi WebSocket URL?

wss://external-api-ws.kalshi.com/trade-api/ws/v2 for production and wss://external-api-ws.demo.kalshi.co/trade-api/ws/v2 for demo. The handshake is signed like a REST request, over the path /trade-api/ws/v2.

How do I know if I missed an order book update?

Check seq on every message of a subscription. A gap means you missed a message, so request a fresh snapshot and rebuild your local book before trading.

Is a faster bot a profitable bot?

No. Good API handling keeps a bot from acting on stale data or getting throttled, but it creates no edge by itself. Fees and spread still have to be beaten, and many strategies don't beat them.

Risk: Trading on Kalshi involves risk, and you can lose money. There are no guaranteed results, and past or paper results do not predict future results. DeskBot is not affiliated with or endorsed by Kalshi. API details were taken from Kalshi's published documentation on October 23, 2026. Limits and endpoints change, so check docs.kalshi.com before you build.