This is the side-by-side API reference for Polymarket and Kalshi — the two dominant prediction market platforms. Every endpoint, CLI command, and SDK method is documented in parallel so you can find the equivalent operation on each platform without switching between documentation sites.
If you’re building an agent that needs to browse markets, read prices, place bets, manage positions, or stream live data, this page has the exact call you need for each platform. For a deep-dive tutorial on Polymarket specifically, see the Polymarket API Tutorial. For py_clob_client method signatures and return types, see the py_clob_client Reference.
For an overview of how these trading APIs fit into the full agent stack (identity, wallet, trading, intelligence), see The Agent Betting Stack Explained.
Platform Overview
Before diving into endpoints, here’s what you’re working with.
| Polymarket | Kalshi | |
|---|---|---|
| Base URL (Market Data) | https://gamma-api.polymarket.com | https://api.elections.kalshi.com/trade-api/v2 |
| Base URL (Trading) | https://clob.polymarket.com | Same as above |
| Base URL (WebSocket) | wss://ws-subscriptions-clob.polymarket.com/ws/ | wss://api.elections.kalshi.com/trade-api/ws/v2 |
| CLI Tool | polymarket (Rust, via Homebrew) | None (REST only) |
| Python SDK | py-clob-client | kalshi_python_sync |
| TypeScript SDK | @polymarket/clob-client | kalshi-typescript |
| Auth (read-only) | None required | None required for market data |
| Auth (trading) | API key + HMAC signature (L2 headers) | API key + RSA signature |
| Currency | USDC on Polygon | USD (cents) |
| Rate Limits | Published: 15,000/10s general (full table) | Varies by endpoint |
| Chain | Polygon (chainId: 137) | N/A (centralized) |
| Market Structure | Series → Events → Markets | Series → Events → Markets |
| Pricing | 0.00 to 1.00 (USDC per share) | 1 to 99 (cents per contract) |
| Fees | Taker fees by category since March 30, 2026: Crypto 1.80%, Sports 0.75%, Politics 1.00%, Finance 1.00%, Economics 1.50%, Culture 1.25%, Weather 1.25%, Tech 1.00%, Mentions 1.56%. Geopolitics is fee-free. Maker rebates range 20–50% by category. | 0% fees on all trades |
| Demo/Sandbox | No official sandbox | https://demo-api.kalshi.co/trade-api/v2 |
| US API | Separate platform at api.polymarket.us (Ed25519 auth, KYC required). See US vs Global guide | N/A (US-based by default) |
Note on the “elections” subdomain: Kalshi’s
api.elections.kalshi.comprovides access to ALL markets — not just election-related ones. This includes economics, weather, sports, technology, and more.
Polymarket 5-minute crypto markets: Polymarket launched short-duration crypto markets that resolve every 5 minutes. These markets carry taker fees and maker rebates like other crypto markets. Agents scanning for trading opportunities will encounter these alongside standard markets.
Authentication
Polymarket
Polymarket uses a three-tier authentication system.
Level 0 (no auth): Browse markets, read prices, check order books. No credentials needed.
Level 1 (wallet signature): Create or derive API credentials. Requires your private key to sign a message.
Level 2 (API key): Place orders, manage positions, cancel orders. Requires API key + secret + passphrase sent as HMAC-signed headers via five POLY_* headers.
Polymarket US uses a completely different auth system (Ed25519 instead of EIP-712/HMAC) with different SDKs and endpoints. The Trading Gateway is being deprecated in favor of the new Exchange Gateway. Developer onboarding now requires an application process and sandbox integration testing before production access is granted. See the Polymarket US vs. Global API Guide for details.
# Polymarket: Create a client with full trading auth
from py_clob_client.client import ClobClient
client = ClobClient(
host="https://clob.polymarket.com",
key="YOUR_PRIVATE_KEY", # Wallet private key
chain_id=137, # Polygon
signature_type=1, # 1 = proxy wallet
funder="YOUR_FUNDER_ADDRESS" # Address holding your funds
)
client.set_api_creds(client.create_or_derive_api_creds())
Note: Polymarket’s agent-skills documentation describes
signature_type=2(Gnosis Safe / browser-wallet proxy) as the wallet pattern most Polymarket accounts use; usesignature_type=1for Magic Link (email) proxy wallets. Older samples often show1as a generic “proxy” example—verify against your actual login path.
# Polymarket CLI: Import wallet for trading
polymarket wallet import 0xYOUR_PRIVATE_KEY
polymarket wallet show
Complete py_clob_client reference: For every ClobClient method with parameters, return types, and working examples, see the py_clob_client Method Reference. Deep-dive guides: get_order_book(), get_balance_allowance(), get_positions(), create_order().
Kalshi
Kalshi uses RSA key-pair authentication. You generate an API key and a private RSA key in your Kalshi account settings, then sign each request.
# Kalshi: Create authenticated client
import kalshi_python
config = kalshi_python.Configuration(
host="https://api.elections.kalshi.com/trade-api/v2"
)
with open('path/to/private_key.pem', 'r') as f:
config.private_key_pem = f.read()
config.api_key_id = "your-api-key-id"
client = kalshi_python.KalshiClient(config)
# Kalshi: Raw curl with auth headers
curl --request GET \
--url https://api.elections.kalshi.com/trade-api/v2/portfolio/balance \
--header 'KALSHI-ACCESS-KEY: YOUR_API_KEY' \
--header 'KALSHI-ACCESS-SIGNATURE: COMPUTED_SIGNATURE' \
--header 'KALSHI-ACCESS-TIMESTAMP: UNIX_MS_TIMESTAMP'
Quick Comparison: Auth
| Task | Polymarket | Kalshi |
|---|---|---|
| Browse markets | No auth | No auth |
| Read order books | No auth | No auth (most endpoints) |
| Place orders | L2 (API key + HMAC) | RSA signature |
| Manage positions | L2 | RSA signature |
| Key format | API key + secret + passphrase | API key ID + RSA private key PEM |
| Key creation | Derived from wallet signature | Generated in account settings |
Browsing Markets
This is the most common agent operation: scanning available markets to find trading opportunities. Both platforms provide unauthenticated endpoints for listing and searching markets, so you can build a market discovery pipeline before committing to either platform’s trading API.
The key difference in market browsing is structure. Polymarket separates market discovery (Gamma API) from trading (CLOB API), so you browse on one domain and trade on another. Kalshi uses a single API for both. Polymarket also has a dedicated CLI tool for quick lookups from the terminal, while Kalshi relies on curl or SDK calls.
For agents that need to scan both platforms simultaneously, the unified API section below covers aggregators like Dome and pmxt that normalize market data from both Polymarket and Kalshi into a single format.
List Markets
Polymarket — gamma-api.polymarket.com/markets:
# CLI
polymarket markets list --limit 20
polymarket -o json markets list --limit 100
# curl
curl "https://gamma-api.polymarket.com/markets?limit=20&closed=false"
# Python SDK (read-only, no auth)
from py_clob_client.client import ClobClient
client = ClobClient("https://clob.polymarket.com")
markets = client.get_markets()
Kalshi — api.elections.kalshi.com/trade-api/v2/markets:
# curl (no auth needed)
curl "https://api.elections.kalshi.com/trade-api/v2/markets?limit=20&status=open"
# Python SDK
markets = client.get_markets(limit=20, status="open")
for m in markets.markets:
print(f"{m.ticker}: {m.title}")
Search Markets
Polymarket:
# CLI
polymarket markets search "bitcoin"
polymarket markets search "fed rate" --limit 5
# Gamma API
curl "https://gamma-api.polymarket.com/search?query=bitcoin&limit=5"
Kalshi:
# Filter by series ticker
curl "https://api.elections.kalshi.com/trade-api/v2/markets?series_ticker=KXBTC"
# No dedicated search endpoint — filter by series, event, or category
Get Market Details
Polymarket:
# CLI
polymarket markets get bitcoin-above-100k
polymarket -o json markets get bitcoin-above-100k
# Gamma API (by slug)
curl "https://gamma-api.polymarket.com/markets?slug=bitcoin-above-100k"
Kalshi:
curl "https://api.elections.kalshi.com/trade-api/v2/markets/TICKER_HERE"
market = client.get_market("KXBTC-26FEB28-T100000")
print(f"Title: {market.market.title}")
print(f"Yes price: {market.market.yes_price}¢")
Browse by Category/Tag
Polymarket:
# CLI (by tag)
polymarket events list --tag politics
polymarket events list --tag crypto
polymarket events list --tag sports
# Gamma API (by tag ID)
curl "https://gamma-api.polymarket.com/events?tag_id=2&closed=false"
# Tag IDs: politics=2, crypto=21, sports=100639, tech=1401, culture=596
Kalshi:
# Filter by category via series
curl "https://api.elections.kalshi.com/trade-api/v2/events?series_ticker=KXBTC"
# List all series to discover categories
curl "https://api.elections.kalshi.com/trade-api/v2/series/KXHIGHNY"
Quick Comparison: Market Browsing
| Operation | Polymarket CLI | Polymarket API | Kalshi API |
|---|---|---|---|
| List markets | markets list --limit N | GET /markets | GET /markets |
| Search | markets search "query" | GET /search?query=X | Filter by series/event |
| Get one market | markets get SLUG | GET /markets?slug=X | GET /markets/{ticker} |
| By category | events list --tag TAG | GET /events?tag_id=N | Filter by series_ticker |
| List events | events list | GET /events | GET /events |
| Get event | — | GET /events/{id} | GET /events/{ticker} |
| JSON output | -o json on any command | All responses are JSON | All responses are JSON |
| Pagination | --limit, --offset | limit, offset params | limit, cursor params |
| Auth required | No | No | No |
Order Books & Pricing
Reading order books and current prices is the second most common agent operation — essential for arbitrage detection, spread analysis, and order sizing. The two platforms differ significantly in how they expose order book data.
Polymarket provides a traditional two-sided order book with separate bids and asks, along with convenience endpoints for midpoint and price lookups. Kalshi only returns bids — in binary markets, a YES bid at price X is equivalent to a NO ask at (100-X), so you compute asks by inverting the other side. This difference matters for agents that compare order books across platforms: you need to normalize Kalshi’s one-sided representation into a two-sided book before making cross-platform comparisons.
Price formats also differ. Polymarket uses decimals between 0 and 1 (e.g., 0.65 means $0.65 per share). Kalshi uses cents between 1 and 99 (e.g., 65 means $0.65 per contract). Since early 2026, Kalshi has been transitioning from integer cents to decimal dollars (yes_price_dollars instead of yes_price) — check the fractional_trading_enabled flag on market responses.
Get Order Book
Polymarket — clob.polymarket.com/book:
# CLI
polymarket clob book TOKEN_ID
# curl
curl "https://clob.polymarket.com/book?token_id=TOKEN_ID"
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import BookParams
client = ClobClient("https://clob.polymarket.com")
book = client.get_order_book("TOKEN_ID")
# Batch: get multiple books at once
books = client.get_order_books([
BookParams(token_id="TOKEN_1"),
BookParams(token_id="TOKEN_2")
])
Kalshi — api.elections.kalshi.com/trade-api/v2/markets/TICKER/orderbook:
curl "https://api.elections.kalshi.com/trade-api/v2/markets/TICKER/orderbook"
book = client.get_market_orderbook("TICKER", depth=10)
# Returns yes bids and no bids only (no asks)
# In binary markets: yes bid at X¢ = no ask at (100-X)¢
Important Kalshi note: Kalshi only returns bids, not asks. This is because in binary markets, a yes bid at price X is equivalent to a no ask at (100-X). Your agent needs to compute asks by inverting the opposite side’s bids.
Kalshi orderbook fixed-point fields: The orderbook endpoint now returns
yes_ask_size_fp,yes_bid_size_fp, and related fixed-point fields alongside the existing integer fields. Agents parsing orderbook data should use the_fpfields for precision on fractional-trading-enabled markets.
Get Midpoint Price
Polymarket:
# CLI
polymarket clob midpoint TOKEN_ID
polymarket -o json clob midpoint TOKEN_ID | jq '.mid'
# Python
mid = client.get_midpoint("TOKEN_ID")
Kalshi:
# No dedicated midpoint endpoint — compute from orderbook
# Midpoint = (best_yes_bid + (100 - best_no_bid)) / 2
Get Price History
Polymarket:
# CLI
polymarket clob price-history TOKEN_ID --interval 1d
polymarket clob price-history TOKEN_ID --interval 1h
# CLOB API
curl "https://clob.polymarket.com/prices-history?market=TOKEN_ID&interval=1d"
Kalshi:
curl "https://api.elections.kalshi.com/trade-api/v2/markets/TICKER/history?limit=100"
Quick Comparison: Order Books & Pricing
| Operation | Polymarket CLI | Polymarket API | Kalshi API |
|---|---|---|---|
| Order book | clob book TOKEN | GET /book?token_id=X | GET /markets/{ticker}/orderbook |
| Midpoint | clob midpoint TOKEN | get_midpoint(token) | Compute from orderbook |
| Best price | — | get_price(token, side) | Best bid from orderbook |
| Spread | — | get_spread(token) | Compute from orderbook |
| Price history | clob price-history TOKEN | GET /prices-history | GET /markets/{ticker}/history |
| Batch books | — | get_order_books([...]) | One call per market |
| Book format | Bids + Asks | Bids + Asks | Bids only (compute asks) |
Placing Orders
The core trading operation. Both platforms support limit orders and market orders, but with different mechanics.
Kalshi breaking change — March 12, 2026: Kalshi removed legacy integer-cent price fields and integer contract count fields from all API endpoints. If your code uses
yes_price(cents, e.g.,yes_price=45) orcount(integer contracts) in order requests, migrate toyes_price_dollars(e.g.,yes_price_dollars=0.45) andcount_fpfor fractional-enabled markets. See Kalshi changelog for the full migration guide.
Limit Orders
Polymarket:
# CLI
polymarket clob create-order \
--token TOKEN_ID \
--side buy \
--price 0.45 \
--size 10
from py_clob_client.clob_types import OrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY
order = OrderArgs(
token_id="TOKEN_ID",
price=0.45, # Price per share in USDC (0.00-1.00)
size=10.0, # Number of shares
side=BUY
)
signed = client.create_order(order)
resp = client.post_order(signed, OrderType.GTC) # Good-til-canceled
// TypeScript
import { ClobClient, Side } from "@polymarket/clob-client";
const order = await client.createAndPostOrder(
{ tokenID: "TOKEN_ID", price: 0.50, size: 10, side: Side.BUY },
{ tickSize: "0.01", negRisk: false }
);
Kalshi:
import uuid
order = client.create_order(
ticker="MARKET_TICKER",
action="buy",
side="yes",
count=10, # Number of contracts (use count_fp on fractional-enabled markets)
type="limit",
yes_price_dollars=0.45, # Price in dollars (0.01–0.99); replaces legacy yes_price cents field
client_order_id=str(uuid.uuid4())
)
curl --request POST \
--url https://api.elections.kalshi.com/trade-api/v2/portfolio/orders \
--header 'Content-Type: application/json' \
--header 'KALSHI-ACCESS-KEY: KEY' \
--header 'KALSHI-ACCESS-SIGNATURE: SIG' \
--header 'KALSHI-ACCESS-TIMESTAMP: TS' \
--data '{
"ticker": "MARKET_TICKER",
"action": "buy",
"side": "yes",
"count": 10,
"type": "limit",
"yes_price_dollars": 0.45,
"client_order_id": "UUID"
}'
Market Orders
Polymarket:
# CLI
polymarket clob market-order \
--token TOKEN_ID \
--side buy \
--amount 5
from py_clob_client.clob_types import MarketOrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY
mo = MarketOrderArgs(
token_id="TOKEN_ID",
amount=25.0, # USDC amount to spend
side=BUY,
order_type=OrderType.FOK # Fill-or-kill
)
signed = client.create_market_order(mo)
resp = client.post_order(signed, OrderType.FOK)
Kalshi:
order = client.create_order(
ticker="MARKET_TICKER",
action="buy",
side="yes",
count=10,
type="market", # No price needed for market orders
client_order_id=str(uuid.uuid4())
)
Polymarket taker fees (since March 30, 2026): The
feeRateBpsfield is now required on signed order objects. Developers must fetch the current fee rate dynamically via the fee-rate API endpoint before constructing orders. Fee rates vary by market category (see the Platform Overview table).
Order Types
| Type | Polymarket | Kalshi |
|---|---|---|
| Good-til-canceled (GTC) | OrderType.GTC | type: "limit" (default) |
| Fill-or-kill (FOK) | OrderType.FOK | time_in_force: "fill_or_kill" |
| Market order | MarketOrderArgs + FOK | type: "market" |
| Post-only | post_only=True on post_order() | post_only: true |
| Reduce-only | Not directly supported | reduce_only: true |
Price Formats
This is a common source of bugs when building cross-platform agents:
| Polymarket | Kalshi | |
|---|---|---|
| Price range | 0.00 to 1.00 | 0.01 to 0.99 |
| Unit | USDC per share | Dollars per contract (yes_price_dollars) |
| “50% chance” | price: 0.50 | yes_price_dollars: 0.50 |
| “10% chance” | price: 0.10 | yes_price_dollars: 0.10 |
| Size unit | Number of shares (decimal) | Number of contracts (count, or count_fp for fractional markets) |
| Tick sizes | 0.01 or 0.001 (varies) | $0.01 (subpenny on some markets) |
| Fees | Taker fee varies by category (0.75%–1.80%); fetch via fee-rate API. feeRateBps required on signed orders. | 0% fees on all trades |
Order Management
View Open Orders
Polymarket:
# CLI
polymarket clob orders
# Python
orders = client.get_orders()
Kalshi:
orders = client.get_orders(status="resting")
curl "https://api.elections.kalshi.com/trade-api/v2/portfolio/orders?status=resting" \
--header 'KALSHI-ACCESS-KEY: KEY' \
--header 'KALSHI-ACCESS-SIGNATURE: SIG' \
--header 'KALSHI-ACCESS-TIMESTAMP: TS'
Cancel Orders
Polymarket:
# CLI: Cancel one
polymarket clob cancel ORDER_ID
# CLI: Cancel all
polymarket clob cancel-all
# Python
client.cancel(order_id="ORDER_ID")
client.cancel_all()
client.cancel_market_orders(market="CONDITION_ID")
Kalshi:
# Cancel one
client.cancel_order("ORDER_ID")
# Cancel all (batch)
client.batch_cancel_orders(
tickers=["TICKER1", "TICKER2"]
)
# Cancel one
curl --request DELETE \
"https://api.elections.kalshi.com/trade-api/v2/portfolio/orders/ORDER_ID" \
--header 'KALSHI-ACCESS-KEY: KEY' \
--header 'KALSHI-ACCESS-SIGNATURE: SIG' \
--header 'KALSHI-ACCESS-TIMESTAMP: TS'
Amend Orders
Polymarket: Not supported via API — cancel and replace.
Kalshi:
# Amend an existing order (change price/size without cancel+replace)
# client_order_id is now optional — you can amend using just order_id
client.amend_order(
order_id="ORDER_ID",
count=15,
yes_price_dollars=0.48 # Use yes_price_dollars (not legacy yes_price cents)
)
curl --request POST \
"https://api.elections.kalshi.com/trade-api/v2/portfolio/orders/ORDER_ID/amend" \
--header 'Content-Type: application/json' \
--data '{"count": 15, "yes_price_dollars": 0.48}'
Quick Comparison: Order Management
| Operation | Polymarket CLI | Polymarket API | Kalshi API |
|---|---|---|---|
| List orders | clob orders | get_orders() | GET /portfolio/orders |
| Cancel one | clob cancel ID | cancel(order_id) | DELETE /portfolio/orders/{id} |
| Cancel all | clob cancel-all | cancel_all() | POST /portfolio/orders/batch (cancel) |
| Amend | Not supported | Not supported | POST /portfolio/orders/{id}/amend |
| Batch create | Not supported | post_orders([...]) (up to 15 per request, raised from 5) | POST /portfolio/orders/batch |
Positions & Portfolio
Check Positions: get_positions
Polymarket — data-api.polymarket.com/positions:
# CLI
polymarket data positions YOUR_ADDRESS
# Data API
curl "https://data-api.polymarket.com/positions?user=YOUR_ADDRESS"
Kalshi:
positions = client.get_positions(settlement_status="unsettled")
for p in positions.market_positions:
print(f"{p.ticker}: {p.position} contracts")
curl "https://api.elections.kalshi.com/trade-api/v2/portfolio/positions" \
--header 'KALSHI-ACCESS-KEY: KEY' \
--header 'KALSHI-ACCESS-SIGNATURE: SIG' \
--header 'KALSHI-ACCESS-TIMESTAMP: TS'
Check Balance: get_balance_allowance
Polymarket — py_clob_client get_balance and get_balance_allowance:
# CLI
polymarket clob balance --asset-type collateral
# Python
balance = client.get_balance_allowance()
Full method reference: See the dedicated get_balance_allowance() guide for BalanceAllowanceParams, AssetType, wei conversion, and pre-trade validation patterns.
Kalshi:
balance = client.get_balance()
# Returns balance in cents + portfolio_value (balance + positions value)
print(f"Available: ${balance.balance / 100:.2f}")
print(f"Portfolio: ${balance.portfolio_value / 100:.2f}")
Portfolio Value
Polymarket:
# CLI
polymarket data value YOUR_ADDRESS
Kalshi:
balance = client.get_balance()
# portfolio_value includes balance + position market values
Withdraw / Bridge Funds
Polymarket now offers a POST /withdraw endpoint to bridge USDC.e from Polymarket to any supported chain and token. This is useful for agents that need to move funds off-platform programmatically after closing positions.
Kalshi: Withdrawals are managed through the Kalshi dashboard; no public API endpoint for withdrawals.
Trade History
Polymarket:
# CLI
polymarket clob trades
# Python
trades = client.get_trades()
Kalshi:
fills = client.get_fills(ticker="MARKET_TICKER")
# A "fill" = a completed trade match
# Each fill includes:
# fee_cost — fee charged on this fill (since January 28, 2026)
# yes_price_dollars — dollar-denominated yes price (replaces deprecated yes_price_fixed)
# no_price_dollars — dollar-denominated no price (replaces deprecated no_price_fixed)
Quick Comparison: Portfolio
| Operation | Polymarket CLI | Polymarket API | Kalshi API |
|---|---|---|---|
| Positions | data positions ADDR | GET /positions | GET /portfolio/positions |
| Balance | clob balance | get_balance_allowance() | GET /portfolio/balance |
| Portfolio value | data value ADDR | Compute from positions | Included in balance response |
| Trade history | clob trades | get_trades() | GET /portfolio/fills |
| Settlements | — | On-chain (CTF redeem) | GET /portfolio/settlements (now includes yes_total_cost_dollars / no_total_cost_dollars; legacy cent fields deprecated) |
| Subaccounts | — | Not applicable | PUT /portfolio/subaccounts/netting (manage netting across subaccounts) |
| Withdraw/Bridge | — | POST /withdraw (bridge USDC.e to other chains/tokens) | Dashboard only (no API endpoint) |
WebSocket Streaming
For agents that need real-time data, both platforms offer WebSocket feeds.
Polymarket WebSocket
Base URL: wss://ws-subscriptions-clob.polymarket.com/ws/
Channels:
market — Order book updates, price changes (public)
user — Order status updates (authenticated)
# Subscribe to market channel
import websocket
import json
ws = websocket.create_connection(
"wss://ws-subscriptions-clob.polymarket.com/ws/market"
)
# Subscribe to specific assets
ws.send(json.dumps({
"type": "subscribe",
"assets_ids": ["TOKEN_ID_1", "TOKEN_ID_2"]
}))
while True:
msg = json.loads(ws.recv())
# msg contains orderbook updates, trade events
Kalshi WebSocket
Base URL: wss://api.elections.kalshi.com/trade-api/ws/v2
Channels:
orderbook — Live order book snapshots
ticker — Price/volume updates
trades — Completed trades
fills — Your fills (authenticated)
market_lifecycle — Market state changes
order_group_updates — Order group lifecycle events: created, triggered, reset, deleted, limit_updated (Jan 2026)
# Kalshi WebSocket subscription
import websocket
import json
ws = websocket.create_connection(
"wss://api.elections.kalshi.com/trade-api/ws/v2"
)
# Authenticate
ws.send(json.dumps({
"id": 1,
"cmd": "subscribe",
"params": {
"channels": ["orderbook", "ticker"],
"market_tickers": ["TICKER1", "TICKER2"]
}
}))
Quick Comparison: WebSocket
| Feature | Polymarket | Kalshi |
|---|---|---|
| Public channels | market | orderbook, ticker, trades, market_lifecycle |
| Authenticated channels | user | fills, positions, order_group_updates |
| Subscription format | assets_ids array | market_tickers array |
| Book updates | Incremental | Snapshots |
| Auth method | Separate auth handshake | Auth headers on connect |
Polymarket CLI Complete Command Reference
The Polymarket CLI is unique to the ecosystem — no other platform has a dedicated CLI for agent access. Here’s the full command map for quick reference.
Browsing (No Wallet Required)
polymarket markets list [--limit N] [--offset N]
polymarket markets search "QUERY" [--limit N]
polymarket markets get SLUG
polymarket events list [--tag TAG] [--limit N]
polymarket clob book TOKEN_ID
polymarket clob midpoint TOKEN_ID
polymarket clob price-history TOKEN_ID [--interval 1d|1h|1m]
polymarket status # API health check
Wallet Management
polymarket wallet create # Generate new wallet
polymarket wallet import 0xKEY # Import existing private key
polymarket wallet show # Display wallet address and config
polymarket approve set # Approve USDC for trading (needs MATIC)
Trading (Wallet Required)
polymarket clob market-order --token TOKEN --side buy|sell --amount USDC
polymarket clob create-order --token TOKEN --side buy|sell --price 0.XX --size N
polymarket clob balance [--asset-type collateral|conditional]
polymarket clob orders # List open orders
polymarket clob trades # List trade history
polymarket clob cancel ORDER_ID
polymarket clob cancel-all
Data & Positions
polymarket data positions ADDRESS # All positions for an address
polymarket data value ADDRESS # Portfolio value
Utility
polymarket setup # Guided first-time setup
polymarket upgrade # Update CLI to latest version
polymarket shell # Interactive REPL mode
polymarket --version
polymarket --help
polymarket -o json COMMAND # JSON output (on any command)
Unified API Aggregators
The direct Polymarket and Kalshi APIs are powerful but different — different auth, different price formats, different SDKs. A growing category of unified APIs abstracts these differences into a single interface. If your agent needs to trade across multiple prediction markets, these tools save significant integration work.
Deep dive available: For a complete comparison of all three tools with code examples, data quality benchmarks, and a decision framework, see the Dome vs pmxt vs OddsPapi Comparison Guide.
Dome (Acquired by Polymarket)
Dome was a YC W25 startup that built a single-API-key interface to Polymarket, Kalshi, and other prediction markets. Polymarket acquired Dome in early 2026, signaling the industry’s move toward standardized API access.
Status: Integrated into Polymarket. The standalone Dome API is being merged into Polymarket’s official developer tooling. New integrations should use the Polymarket API directly, but Dome’s unified data models influenced how Polymarket is expanding its API surface.
What Dome contributed:
- Normalized market schema across platforms (consistent event/market/outcome hierarchy)
- Single authentication layer for multi-platform access
- Unified order placement with platform-specific execution routing
- Real-time price aggregation across platforms
See the Dome tool entry for links and current status.
pmxt — “CCXT for Prediction Markets”
pmxt is an open-source SDK that normalizes prediction market data into a consistent format, inspired by how CCXT unifies crypto exchange APIs. Unlike Dome (which was a hosted service), pmxt runs client-side — no third-party server in the middle.
Installation:
pip install pmxt
Basic usage:
import pmxt
# Initialize exchanges
poly = pmxt.polymarket()
kalshi = pmxt.kalshi()
# Fetch markets (normalized format)
poly_markets = poly.fetch_markets()
kalshi_markets = kalshi.fetch_markets()
# Normalized market object
# {
# "id": "...",
# "symbol": "PRESIDENTIAL-ELECTION-2028",
# "question": "Who will win the 2028 Presidential Election?",
# "outcomes": [{"name": "Democrat", "price": 0.54}, ...],
# "volume": 1250000,
# "platform": "polymarket"
# }
Key features:
- Normalized market, order book, and trade data across platforms
- Consistent price format (0-1 implied probability)
- Local execution — your API keys stay on your machine
- Extensible — community can add new platform adapters
Limitations:
- Newer project, smaller community than CCXT
- Trading support varies by platform (read operations are more mature than write)
- No hosted API — you manage your own infrastructure
OddsPapi
OddsPapi bridges prediction markets and traditional sportsbooks, aggregating odds data from both worlds into a single feed. This is particularly useful for cross-market arbitrage strategies.
Key features:
- Aggregates Polymarket, Kalshi, and 10+ sportsbooks
- Odds normalization across American, decimal, and implied probability formats
- Historical odds data for backtesting
- REST API with generous free tier
Best for: Agents that need to compare prediction market prices against sportsbook odds. If your strategy involves cross-market arbitrage or market-making informed by sportsbook lines, OddsPapi provides the data bridge.
For live multi-sportsbook odds data, see also The Odds API.
Unified API Comparison
| Dome | pmxt | OddsPapi | |
|---|---|---|---|
| Type | Hosted API (now part of Polymarket) | Open-source SDK | Hosted API |
| Platforms | Polymarket, Kalshi, others | Polymarket, Kalshi | Prediction markets + sportsbooks |
| Auth model | Single API key | Per-platform API keys (local) | Single API key |
| Trading support | Full (order placement, management) | Partial (read-heavy, trading in development) | Read-only (odds data) |
| Real-time data | WebSocket feeds | Polling (WebSocket planned) | REST polling |
| Pricing | Was paid SaaS (now integrated) | Free, open-source | Free tier + paid plans |
| Self-hosted | No (was cloud-only) | Yes (runs locally) | No (cloud API) |
| Best for | N/A (use Polymarket API directly) | Multi-platform agents, CCXT users | Cross-market arb, sportsbook comparison |
When to Use Unified vs. Direct APIs
Use direct APIs (Polymarket/Kalshi) when:
- You trade on a single platform
- You need the lowest possible latency
- You need features not yet supported by unified SDKs (e.g., advanced order types, FIX protocol)
- You need full WebSocket streaming with orderbook reconstruction
Use a unified SDK (pmxt) when:
- Your agent trades on multiple prediction markets
- You want consistent data models across platforms
- You’re building a comparison or aggregation tool
- You value open-source and local execution
Use an odds aggregator (OddsPapi, The Odds API) when:
- Your strategy compares prediction markets to sportsbooks
- You need cross-market arbitrage detection
- You want historical odds data for backtesting
Notable exclusion: OG.com. OG.com is a CFTC-regulated prediction market by Crypto.com (CDNA) with sports-focused contracts and parlays. It is excluded from this API reference because it does not offer a public API or SDK for programmatic trading.
SDKs & Client Libraries: Python, TypeScript, Go
Polymarket SDKs: py-clob-client and More
| Language | Package | Install | Docs |
|---|---|---|---|
| Python | py-clob-client | pip install py-clob-client | GitHub |
| TypeScript | @polymarket/clob-client | npm i @polymarket/clob-client | GitHub |
| Go | poly-market-sdk | go get github.com/mtt-labs/poly-market-sdk | pkg.go.dev |
| Rust (CLI) | polymarket | brew install polymarket | GitHub |
| Python | polymarket-apis | pip install polymarket-apis (v0.5.7+, Python ≥3.12) | PyPI |
Deep dive: For every
py_clob_clientmethod with parameters, return types, and working code examples, see the py_clob_client Method Reference.
polymarket-apis (v0.5.7, April 2026) is a unified third-party Python SDK that wraps the CLOB, Gamma, Data, Web3, WebSockets, and GraphQL clients into a single package with Pydantic validation. Requires Python ≥3.12. Use it as a higher-level alternative to
py-clob-clientwhen you need access to multiple Polymarket APIs from one import.
Kalshi SDKs
| Language | Package | Install | Docs |
|---|---|---|---|
| Python | kalshi_python_sync | pip install kalshi_python_sync | docs.kalshi.com |
| TypeScript | kalshi-typescript | npm install kalshi-typescript | docs.kalshi.com |
Error Handling
Polymarket Common Errors
| Error | Meaning | Fix |
|---|---|---|
INSUFFICIENT_BALANCE | Not enough USDC | Fund wallet or reduce order size |
INVALID_TICK_SIZE | Price doesn’t match market’s tick size | Check tick size (0.01 or 0.001) |
ORDER_ALREADY_EXISTS | Duplicate order submission | Generate new nonce |
MARKET_NOT_TRADABLE | Market is closed or resolved | Check market status before ordering |
INVALID_SIGNATURE | Auth signature mismatch | Regenerate API credentials |
Kalshi Common Errors
| HTTP Code | Meaning | Fix |
|---|---|---|
| 400 | Bad request (invalid params). Order validation failures now return granular error codes (e.g., specific field-level errors) instead of the generic invalid_order response. | Check the error code and message for the specific validation failure |
| 401 | Authentication failed | Verify API key and signature |
| 403 | Insufficient permissions | Check account status and permissions |
| 404 | Market/order not found | Verify ticker or order ID |
| 429 | Rate limited | Back off and retry with exponential delay |
| 500 | Server error | Retry after brief delay |
Cross-Platform Arbitrage Reference
For agents comparing prices across platforms, here’s how to normalize data:
def normalize_price(polymarket_price=None, kalshi_price=None):
"""Convert to a common 0-1 probability format."""
if polymarket_price is not None:
return polymarket_price # Already 0.00-1.00
if kalshi_price is not None:
return kalshi_price / 100 # Convert cents to 0.00-1.00
def denormalize_price(probability, platform):
"""Convert common probability to platform-native format."""
if platform == "polymarket":
return round(probability, 2) # 0.00-1.00
elif platform == "kalshi":
return int(probability * 100) # 1-99 cents
When comparing equivalent markets across platforms, an arbitrage opportunity exists when the combined cost of buying “Yes” on one platform and “No” on the other totals less than 1.00 (after fees).
The price normalization pattern above extends to sportsbooks. American odds (-110, +150), decimal odds (1.91, 2.50), and prediction market probabilities (0.52, 0.40) all represent the same underlying concept. For converting between these formats and normalizing odds across offshore sportsbooks like BetOnline, Bovada, and BookMaker, see the Odds Normalization Guide.
Rate Limits
Polymarket
Polymarket now publishes concrete rate limits enforced via Cloudflare throttling. The general limit is 15,000 requests per 10 seconds, with CLOB trading endpoints at 3,500/10s burst and 36,000/10min sustained for POST /order. Gamma API is 4,000/10s general, and Data API is 1,000/10s general.
Kalshi
Kalshi enforces rate limits per endpoint. When rate limited, the API returns HTTP 429 with a Retry-After header. The demo environment at demo-api.kalshi.co has more generous limits for testing.
To check your account’s specific rate limit tier, use the endpoint added in January 2026:
curl "https://api.elections.kalshi.com/trade-api/v2/account/limits" \
--header 'KALSHI-ACCESS-KEY: KEY' \
--header 'KALSHI-ACCESS-SIGNATURE: SIG' \
--header 'KALSHI-ACCESS-TIMESTAMP: TS'
# Returns your API tier and read/write limits
Deep dive: See the Polymarket Rate Limits Guide for 429 error handling, retry code, and rate limit header documentation.
Frequently Asked Questions
Which prediction market API should I use?
Polymarket offers the highest volume and a decentralized order book on Polygon. Kalshi is CFTC-regulated and uses USD directly. For U.S.-based agents, Kalshi has clearer regulatory standing. For global agents, Polymarket has more markets and liquidity. See the Platform Overview table above for a detailed comparison.
What is the best Python SDK for prediction markets?
For Polymarket, use py-clob-client (method reference). For Kalshi, use kalshi_python_sync. Both are official SDKs maintained by the platforms with full trading support including order placement, position tracking, and WebSocket streaming.
Can I use the same code for both Polymarket and Kalshi?
No — they use different authentication (EIP-712 vs RSA-PSS), different price formats (0.00-1.00 vs cents), and different SDKs. However, you can build an abstraction layer. See the Cross-Platform Arbitrage Reference section above for price normalization code and comparison patterns.
Further Reading
- The Agent Betting Stack Explained — How trading APIs fit into the full agent architecture
- Polymarket API: The Complete Developer Guide — Full deep dive with code examples in Python, TypeScript, and Rust
- Kalshi API: Complete Trading Automation Guide — Full deep dive with authentication, WebSocket, and FIX protocol
- Polymarket CLI + Coinbase Quickstart — Hands-on setup tutorial
- py_clob_client Reference — Every Python SDK method with parameters, return types, and examples
- get_order_book() Guide — OrderBookSummary, batch retrieval, spread calculation
- get_balance_allowance() Guide — BalanceAllowanceParams, wei conversion, pre-trade validation
- get_positions() Guide — P&L calculation, Data API alternative
- create_order() Guide — OrderArgs, MarketOrderArgs, tick_size, neg_risk, batch orders
- Polymarket Rate Limits Guide — Concrete per-endpoint limits and retry strategies
- Polymarket WebSocket & Orderbook Guide — All four channels and orderbook reconstruction
- Polymarket Auth Troubleshooting — POLY headers, signatureType, error reference
- Polymarket TypeScript SDK Reference — @polymarket/clob-client methods
- Polymarket Rust SDK Reference — Cargo setup and method reference
- Polymarket Gamma API Deep Dive — Market discovery and price history
- Polymarket Subgraph Guide — On-chain data via GraphQL
- Cross-Market Arbitrage Guide — Arb across sportsbooks and prediction markets
- Sports Betting Arbitrage Bot Guide — Build a full arb bot from scratch
- Offshore Sportsbook API Guide — Data access for BetOnline, Bovada, BookMaker
- Offshore vs. Regulated Sportsbooks — Full comparison for developers
- Best Sportsbook Odds by Sport — Vig rankings across NFL, NBA, MLB, NHL
- Dome vs pmxt vs OddsPapi Comparison — Full unified API comparison with decision framework
- Build a Polymarket Trading Bot — From scanning to production deployment
- Dome Tool Entry — Unified prediction market API (now part of Polymarket)
- Security Best Practices — Protecting your API keys and wallet
- Tool Directory — All tools in the prediction market agent ecosystem
- Polymarket Official Docs — Full Polymarket documentation
- Polymarket Changelog — Official changelog for API updates and new endpoints
- Kalshi Official Docs — Full Kalshi documentation
