// PREDICTION-MARKET APIS
Polymarket CLOB API guide
2026-07-16 · Mithril
Polymarket looks like an exchange from the outside — an order book, bids and
asks, limit orders — but under the hood it is a central limit order book
settled on-chain. Orders are cryptographically signed messages from your
wallet, matching happens off-chain at the operator, and fills settle to USDC
on Polygon. That hybrid design is why the API feels unfamiliar if you come
from Kalshi or a traditional brokerage. This guide covers the mental model
first, then a working py-clob-client walkthrough.
Two services, two jobs
Polymarket splits its API in half, and knowing which service does what saves a lot of confusion:
| Gamma API | CLOB API | |
|---|---|---|
| Host | gamma-api.polymarket.com | clob.polymarket.com |
| Purpose | Market metadata, events, prices | Order books, orders, trades |
| Auth | None | L1/L2 (see below) |
| Use it for | Research, discovery, dashboards | Actually trading |
Gamma is the friendly half: plain REST, no auth, query markets and events by slug or ID. If you are building a screener or backfilling metadata, you may never need anything else:
import requests
resp = requests.get(
"https://gamma-api.polymarket.com/markets",
params={"active": "true", "limit": 50},
)
for m in resp.json():
print(m["question"], m.get("conditionId"))
The CLOB API is where orders live, and it is where the crypto machinery starts.
condition_id vs token_id
Every Polymarket market has a condition_id — a hex string like
0x26d06d9c... identifying the market (the "condition" being resolved).
Each outcome of that market is a separate ERC-1155 token with its own
token_id: for a binary market, one token for YES and one for NO.
The rule of thumb:
condition_ididentifies the market — use it for metadata, matching, and resolution.token_ididentifies what you actually buy and sell — every order is placed against a token_id.
Buying YES and selling NO are trades in different tokens that happen to be economically linked (a YES token plus a NO token can be merged back into $1 of USDC). Neither ID resembles Kalshi's human-readable tickers, which is one reason mapping markets across venues is such a pain.
Auth: the L1/L2 model
The CLOB uses two layers of authentication:
- L1 — your wallet's private key. This is the root credential. It signs orders (as EIP-712 typed data) and is used once to create or derive API credentials.
- L2 — API credentials (key, secret, passphrase) derived from an L1 signature. These sign ordinary REST requests via HMAC headers — fetching your open orders, trades, and balances — without touching the wallet key each time.
So the flow is: wallet key → derive L2 creds → use L2 for REST, and the wallet key again whenever an order needs signing. The important consequence for key management: the credential that trades is a crypto private key that can also move funds. That is a different risk profile from an exchange API key with trading-only scope, and it is worth thinking about before a bot — or an AI agent — holds it. More on that in agent custody for prediction markets.
Walkthrough with py-clob-client
The official Python client wraps the signing so you rarely handle EIP-712 directly:
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs, OrderType
HOST = "https://clob.polymarket.com"
CHAIN_ID = 137 # Polygon mainnet
client = ClobClient(HOST, key=PRIVATE_KEY, chain_id=CHAIN_ID)
client.set_api_creds(client.create_or_derive_api_creds())
If you trade through a Polymarket proxy wallet (the default when you signed up via the website) rather than a bare externally-owned account, the client needs to know — check the client's docs for the signature-type and funder parameters that apply to your account setup.
Read the book for a token:
book = client.get_order_book(token_id=YES_TOKEN_ID)
print(book.bids[:3], book.asks[:3])
Prices are decimals between 0.01 and 0.99 — a price of 0.42 is an implied 42% and pays out $1.00 of USDC if that outcome wins. Markets also have tick-size and minimum-size rules; fetch them per market rather than hard-coding.
Place a limit order:
order = client.create_order(OrderArgs(
token_id=YES_TOKEN_ID,
price=0.42,
size=100, # shares (each pays $1 if correct)
side="BUY",
))
resp = client.post_order(order, OrderType.GTC)
print(resp)
create_order builds and signs the EIP-712 payload with your key;
post_order submits it to the operator. Order types include good-til-canceled
and time-bound variants, plus fill-type behavior for marketable orders — see
order types and rate limits
for the comparison with Kalshi.
Manage the order:
open_orders = client.get_orders()
client.cancel(order_id=resp["orderID"])
Settlement: what "on Polygon" actually means
Matching is off-chain — the operator crosses your signed order with a counterparty's — but settlement is an on-chain token transfer on Polygon. Your USDC leaves, outcome tokens arrive, and the trade is visible on-chain. Practical consequences:
- You need a funded Polygon wallet: USDC to trade with, and the relevant token approvals set so the exchange contract can move your collateral (the client and docs cover the approval step).
- When the market resolves, winning tokens redeem for $1.00 of USDC each through the resolution contracts.
- Gas on Polygon is small but not zero, and approvals/redemptions are transactions you (or your wallet infrastructure) pay for.
On fees: Polymarket charges no exchange trading fee on most markets today. Your real costs are the spread, price impact in thin books, and Polygon gas around funding, approvals, and redemptions. That does not make execution free — a 2¢ spread on a 0.50 market is a bigger cost than most exchange fees — see Polymarket fees and gas explained.
Gotchas worth knowing in advance
- Don't confuse the IDs. Orders take a
token_id. Passing acondition_idwhere a token_id belongs is the classic first-hour error. - Decimals, not cents. 0.42, never 42. If your code also talks to Kalshi, normalize at the boundary or you will eventually cross the streams.
- Signature/nonce errors are usually setup errors. Wrong chain ID, wrong signature type for a proxy-wallet account, or missing approvals produce errors that look cryptic but are almost always configuration.
- Negative-risk and multi-outcome events structure differently from simple binaries — a multi-candidate election is a set of linked markets. Read the market structure before assuming binary math.
- WebSockets over polling for books and your own order updates; the CLOB has rate limits and polling the book is the fastest way to find them.
Wrapping up
The CLOB API is well designed once the mental model clicks: Gamma for
metadata, wallet key at the root, L2 creds for REST, EIP-712 orders,
settlement on Polygon. The friction is that all of it is different from
Kalshi — different in ways that bite
when one codebase trades both. That is the integration Mithril packages up:
one REST API over both venues, unified mkt_ IDs, encrypted key custody,
and fee-aware routing — docs here if you'd
rather not maintain two signing stacks.
APIs change. Details above reflect public documentation as of July 2026 — always confirm against the venues' own docs before trading real money.
One API + MCP for Kalshi and Polymarket
Fee-aware routing, unified market IDs, and hard server-side risk limits — live today, free during beta.
Keep reading
- The complete guide to prediction market APIs (Kalshi + Polymarket)
- Kalshi API vs Polymarket API: the differences that bite
- How to build a prediction-market trading bot in Python
- Polymarket fees and gas explained
- Unified market IDs: mapping the same event across Kalshi and Polymarket
Terms used