← Platforms

From the official docs · checked 2026-10-22

Kalshi vs Polymarket API: a side-by-side for bot builders

Three prediction-market APIs, one table: Kalshi, Polymarket US and international Polymarket (the CLOB). Auth, base URLs, demo environments, order types, idempotency, order books, websockets, rate limits, fees and settlement, each checked against the official docs, plus the gotchas our recipe tests hit.

The comparison table

KalshiPolymarket USPolymarket international (CLOB)
Who it is forKalshi account holdersPolymarket US account holders (identity-verified in the app)International users with a Polygon wallet; check the geoblock endpoint first
REST base URLhttps://external-api.kalshi.com/trade-api/v2https://api.polymarket.us (authenticated), https://gateway.polymarket.us (public)CLOB https://clob.polymarket.com, Gamma https://gamma-api.polymarket.com, Data https://data-api.polymarket.com
Demo / sandboxYes: https://external-api.demo.kalshi.co/trade-api/v2, mock funds, separate keysNo retail sandbox in the docs. POST /v1/order/preview previews an order without placing itNo testnet in the CLOB docs
AuthAPI key + RSA-PSS (SHA-256) or Ed25519 signature over timestamp + METHOD + pathAPI key + Ed25519 signature over timestamp + method + pathL1: EIP-712 wallet signature creates API credentials. L2: HMAC-SHA256 headers on every private call. Orders are also wallet-signed
Auth headersKALSHI-ACCESS-KEY, KALSHI-ACCESS-TIMESTAMP, KALSHI-ACCESS-SIGNATUREX-PM-Access-Key, X-PM-Timestamp, X-PM-SignaturePOLY_ADDRESS, POLY_SIGNATURE, POLY_TIMESTAMP, POLY_API_KEY, POLY_PASSPHRASE
Order typesLimit only in Create Order V2 (price required)Limit and market (ORDER_TYPE_LIMIT, ORDER_TYPE_MARKET)Limit (GTC, GTD) and market (FAK, FOK)
Time in forcefill_or_kill, good_till_canceled, immediate_or_cancel; GTC + expiration_time for expiring ordersDAY, GTC, GTD, IOC, FOKGTC, GTD, FAK, FOK
Post-onlypost_onlyparticipateDontInitiatepostOnly with GTC or GTD
Client order IDYes: client_order_id. Duplicates are rejected, so resubmitting with the same ID is safeNo client order ID on retail Create Order; the exchange assigns idNo client order ID; each signed order carries a random salt
Order book shapeBids only: yes_dollars and no_dollars, ascending. Best bid is the last element. YES ask = 1 − best NO bidbids and offers with px/qty. Docs don't state the order; on our live check the best price was firstbids ascending, asks descending. Best bid and best ask are the last elements
Websocketswss://external-api-ws.kalshi.com/trade-api/ws/v2; authenticated handshake, even for public channelswss://api.polymarket.us/v1/ws/markets and /v1/ws/private; both need API-key headerswss://ws-subscriptions-clob.polymarket.com/ws/market (public) and /ws/user (authenticated)
Keep-aliveServer sends Ping frames every 10 secondsServer sends {"heartbeat":{}}; reconnect if they stopMarket channel: send PING every 10 seconds, server replies PONG
Rate limitsToken buckets per tier; most requests cost 10 tokens. Basic: 200 read / 100 write tokens per second25 requests/second general, per IP and Cloudflare location; combos and RFQs 1/secondCloudflare IP limits (e.g. POST /order 5,000 per 10 s burst) plus per-signer order and cancel buckets (Standard: 40 order tokens/s, burst 60)
Batch ordersBatch create and cancel (V2), billed per order in the batch; max batch size scales with your tierUp to 20 orders per batch create, cancel or modifyPOST /orders; costs one order token per order in the batch
Taker fee (100 at $0.50)0.07 × C × P × (1 − P), rounded up: $1.750.0695 × C × p × (1 − p), banker's rounding: $1.74C × rate × p × (1 − p): $1.25 at 0.05, $1.75 at 0.07
Maker fee0.0175 on series with maker fees ($0.44 for 100 at $0.50), otherwise 0No fee; Tier 2 to 4 makers earn a rebateNever charged
Settlement$1 per contract on the winning side, net positions only$1.00 winning, $0.00 losing, processed by Polymarket ClearingUMA Optimistic Oracle (Chainlink for up-down markets). Winning tokens redeem for $1; about 2 hours if undisputed

Facts are from the docs linked under Sources, checked 2026-10-22. Exchanges change their APIs often, so confirm in the docs before you rely on a value.

Auth and base URLs

Kalshi signs each request with your private key: the string is the millisecond timestamp, the HTTP method and the path, starting at /trade-api/v2 and without the query string. RSA-PSS with SHA-256 and Ed25519 keys are both accepted. Demo has its own host (external-api.demo.kalshi.co) and its own keys; production keys don't work there.

Polymarket US uses Ed25519 keys created at polymarket.us/developer after identity verification. The secret is shown once. The timestamp must be within 30 seconds of server time. Public market data comes from gateway.polymarket.us with no key.

International Polymarket has two layers. L1 is an EIP-712 signature (domain ClobAuthDomain, chain 137) that proves you control a wallet and creates or derives API credentials. L2 is the HMAC-SHA256 header set used on every private call. Orders are signed by the wallet too, so a bot here holds a key that can move funds. Read the Wallet-Key Safety Pack before that key exists.

Starter recipes: Kalshi API starter, Polymarket US API starter kit, Polymarket CLOB API starter.

Order types and time in force

Kalshi Create Order V2 (POST /portfolio/events/orders) takes a ticker, a side (bid buys YES, ask sells YES), a count, a price and a time in force: fill_or_kill, good_till_canceled or immediate_or_cancel. There's no market order type, and GTT isn't a valid value: send good_till_canceled with an expiration_time instead. reduce_only is only accepted with IOC. The legacy /portfolio/orders endpoint is deprecated.

Polymarket US (POST /v1/orders) has limit and market orders and five TIFs: TIME_IN_FORCE_DAY, GOOD_TILL_CANCEL, GOOD_TILL_DATE, IMMEDIATE_OR_CANCEL and FILL_OR_KILL. Direction is an intent (ORDER_INTENT_BUY_LONG buys YES, BUY_SHORT buys NO), and price always refers to YES. Mark bot orders with manualOrderIndicator. synchronousExecution can make the call wait for the outcome.

International Polymarket limit orders are GTC or GTD; market orders are FAK (fill what you can, cancel the rest) or FOK (all or nothing). GTD orders expire one minute before the stated time, and the expiration must be at least three minutes ahead. Prices must match the market's tick_size, which can change mid-market.

Client order IDs and safe retries

Only Kalshi gives you an idempotency key. Set client_order_id on every order: Kalshi rejects a second submission with the same ID, so a retry after a timeout can't double your position. Neither Polymarket API has a client order ID. On Polymarket US the exchange assigns the order id, and batch results arrive on the order stream rather than in the response. On the international CLOB each signed order has a random salt, so signing again makes a new order. For both, never auto-retry an order POST. Check open orders and fills, and keep your own idempotency key in a local ledger. The kill switch and position limits recipe covers the guardrails.

Order book shape: where is the best bid?

This is where most first bots go wrong.

The portable fix is the same everywhere: take the maximum bid and the minimum ask.

Websockets

Kalshi has a single endpoint, wss://external-api-ws.kalshi.com/trade-api/ws/v2 (demo: wss://external-api-ws.demo.kalshi.co/trade-api/ws/v2). The handshake must be signed even for public channels such as orderbook_delta and ticker. Kalshi sends a Ping frame every 10 seconds.

Polymarket US splits public and private: wss://api.polymarket.us/v1/ws/markets for market data and trades, wss://api.polymarket.us/v1/ws/private for orders, positions and balance. Both handshakes carry the API-key headers. The server sends heartbeats; reconnect if they stop.

International Polymarket has a public market channel at wss://ws-subscriptions-clob.polymarket.com/ws/market and an authenticated user channel at /ws/user. On the market channel, your client sends PING every 10 seconds. Watch for tick_size_change if you cache tick sizes.

Rate limits

Fees

All three charge takers a coefficient × contracts × p × (1 − p), so fees peak at 50¢. They differ in the coefficient and rounding:

Try your own sizes in the Kalshi & Polymarket fee calculator. If you're comparing prices across venues, the arbitrage alert monitor shows why a gap that looks real often disappears after fees and fill delay.

Settlement

Kalshi pays $1 per contract on the winning side and settles net positions only; timing varies by market. Polymarket US settles winners at $1.00 and losers at $0.00 through Polymarket Clearing, with alternative terms where a market's rules say so. International Polymarket resolves through the UMA Optimistic Oracle (Chainlink for up-down markets). An undisputed proposal resolves in about two hours, a disputed one in four to six days. Winning tokens redeem for $1, and in a rare 50/50 outcome each token redeems for $0.50. Read each market's rules, not just its title.

Gotchas bot builders hit

These are the API mistakes that come up when AI coding tools build these bots (see also how we test recipes).

Official SDKs

FAQ

Which has the easier API, Kalshi or Polymarket?

Kalshi and Polymarket US are closest to a normal exchange API: an API key plus a signed request, limit orders, and a demo (Kalshi) or order preview (Polymarket US). International Polymarket adds a wallet layer: an EIP-712 signature creates API credentials, HMAC headers authenticate requests, and every order is signed by the wallet. Pick the venue you can actually use first, then the API.

Does Polymarket have a sandbox or testnet like Kalshi demo?

Kalshi has a full demo environment at demo.kalshi.co with mock funds and separate keys. The Polymarket US retail docs list no sandbox; the closest tool is POST /v1/order/preview, which previews an order without placing it. The international CLOB docs list no testnet, so paper-trade against the live book instead.

Can I safely retry an order if the request times out?

On Kalshi, yes, if you set client_order_id: Kalshi rejects duplicate submissions with the same ID. Polymarket US and international Polymarket have no client order ID, so a blind retry can place a second order. Check open orders and fills first, and keep your own idempotency key locally.

Why does my order book look backwards?

Kalshi returns bids only, sorted ascending, so the best bid is the last element, and the YES ask is 1 minus the best NO bid. International Polymarket sorts bids ascending and asks descending, so the best of each is also last. Polymarket US uses bids and offers, and the docs don't state the order. Take the max bid and min ask instead of trusting position.

Which is cheaper for a bot, Kalshi or Polymarket?

All three use the same shape: a coefficient × contracts × p × (1 − p). For 100 contracts at $0.50, a taker pays $1.75 on Kalshi, $1.74 on Polymarket US, and $1.25 to $1.75 on international Polymarket depending on the market's rate. Makers pay nothing on Polymarket, while Kalshi charges makers on some series. Use the fee calculator for your own sizes.

What are the rate limits?

Kalshi uses token buckets by tier: Basic gets 200 read and 100 write tokens per second, and most requests cost 10 tokens. Polymarket US allows 25 requests per second in general, with 1 per second for combos and RFQs. International Polymarket has Cloudflare IP limits per endpoint plus per-signer order and cancel buckets that grow with 30-day volume.

Build it

Sources