API + MCP live · talk to us

// 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 APICLOB API
Hostgamma-api.polymarket.comclob.polymarket.com
PurposeMarket metadata, events, pricesOrder books, orders, trades
AuthNoneL1/L2 (see below)
Use it forResearch, discovery, dashboardsActually 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:

python
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_id identifies the market — use it for metadata, matching, and resolution.
  • token_id identifies 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:

python
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:

python
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:

python
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:

python
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 a condition_id where 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.