API · Reference
The CLOB (Central Limit Order Book) at clob.polymarket.com is where orders
rest and match. You read the book, prices and tick size with no auth, and trade
(place / cancel orders, read your balance) with API credentials and signing.
This is the CLOB V2 reference: collateral is pUSD, fees are on-chain, and
makers pay zero.
Read the order book (no auth)
from py_clob_client_v2 import ClobClient # pip install py-clob-client-v2
client = ClobClient(host="https://clob.polymarket.com", chain_id=137) # read-only: no key
book = client.get_order_book(token_id)
mid = client.get_midpoint(token_id)
print(book.bids[0].price, book.asks[0].price, mid)
// polymarket_client_sdk_v2 (official, repo rs-clob-client-v2)
use polymarket_client_sdk_v2::clob::{Client, Config};
use polymarket_client_sdk_v2::clob::types::request::OrderBookSummaryRequest;
let client = Client::new("https://clob.polymarket.com", Config::default())?;
let book = client.order_book(&OrderBookSummaryRequest::builder().token_id(token_id).build()).await?;
curl -s "https://clob.polymarket.com/book?token_id=$TOKEN_ID"
Sample response
{
"market": "0x...",
"bids": [ { "price": "0.62", "size": "1400" }, { "price": "0.61", "size": "900" } ],
"asks": [ { "price": "0.64", "size": "1100" }, { "price": "0.65", "size": "2000" } ]
}
Read endpoints
| Endpoint | Returns |
|---|---|
GET /book?token_id= | Full order book (bids / asks). |
GET /price?token_id=&side= | Best bid or ask. |
GET /midpoint?token_id= | Mid = (best bid + best ask) / 2. |
GET /spread?token_id= | Best ask − best bid. |
GET /tick-size?token_id= | Minimum price increment (round your price to it). |
Limits are high: CLOB ~9,000 requests / 10s, /book and /price 1,500 / 10s,
and over-limit requests are throttled, not rejected. More on 429s.
Place & cancel an order (auth)
One call builds, signs (the V2 order struct) and posts your order. You choose an order type:
| Type | Behaviour |
|---|---|
GTC | Good-Till-Cancelled: rests on the book until filled or cancelled. |
GTD | Good-Till-Date: rests until an expiry timestamp. |
FOK | Fill-Or-Kill: fill the whole order immediately or cancel it. |
FAK | Fill-And-Kill: fill what it can immediately, cancel the rest. |
from py_clob_client_v2 import (ClobClient, OrderArgs, OrderType,
PartialCreateOrderOptions, Side, OrderPayload)
# authenticated client (creds from create_or_derive_api_key - see Authentication)
client = ClobClient(host="https://clob.polymarket.com", chain_id=137, key=PK, creds=creds)
resp = client.create_and_post_order(
order_args=OrderArgs(token_id=token_id, price=0.62, side=Side.BUY, size=10),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False), # read both off the market
order_type=OrderType.GTC, # GTC, GTD, FOK or FAK
)
# resp -> {"success": true, "orderID": "0x...", "status": "live"}
client.cancel_order(OrderPayload(orderID=resp["orderID"])) # cancel
tick_size ("0.01" or "0.001") and set neg_risk=True for
multi-outcome "negative risk" markets - read both off Gamma (orderPriceMinTickSize,
negRisk) before signing. Also: minimum order size is 5 shares, and your price
must already be rounded to the tick or the order is rejected.nonce,
feeRateBps, taker and expiration and added timestamp,
metadata and builder; the Exchange EIP-712 domain version is "2".
Fees are collected on-chain at match: makers pay 0, only takers pay.
Before trading you must approve pUSD + conditional tokens to the three V2 contracts
(see the allowance fix).Fees: only takers pay, and the rate curves
Makers are never charged. Takers pay a fee that is not flat - it scales with the market's uncertainty and varies by category. The formula:
fee = shares × feeRate × p × (1 - p) # p = share price, 0..1
The p·(1-p) term means the fee peaks at 50/50 and shrinks toward the 1¢ and
99¢ edges - so a near-certain outcome is cheap to take, a coin-flip is dear. Per-category taker
feeRate:
| Category | Taker feeRate |
|---|---|
| Crypto | 0.07 (7 bps) - the highest |
| Economics / Culture / Weather | 0.05 |
| Finance / Politics / Tech / Mentions | 0.04 |
| Sports | 0.03 |
| Geopolitics & world events | 0 - fee-free |
Read the live rate per token with GET /fee-rate-bps?token_id= rather than hardcoding it; fees
round to 5 decimals (min 0.00001 pUSD). Makers paying zero is why most edge-free bots quote rather than take.
Negative-risk (multi-outcome) markets
Multi-candidate events ("who wins the election?") are neg-risk markets: their outcomes are
linked, so a No share in one outcome converts into a Yes share in every other through the Neg
Risk Adapter - capital-efficient, but mechanically different. They run on different contracts
from binary markets, so you must pass neg_risk=True in the order options (read
the market's negRisk flag off Gamma). Omit it and the order is signed against the wrong exchange
and rejected.
Conditional tokens: split, merge, redeem (beyond the book)
Underneath every market is the Conditional Token Framework (CTF). Outcome tokens are ERC-1155 tokens, and every Yes/No pair is backed by exactly $1.00 of pUSD locked in the CTF contract. That gives you three primitives the order book alone does not:
| Operation | What it does | Why a bot uses it |
|---|---|---|
| Split | Lock $1 pUSD → mint 1 Yes + 1 No | Create inventory without crossing the spread; quote both sides. |
| Merge | Burn 1 Yes + 1 No → recover $1 pUSD | Exit a hedged pair instantly - no resolution wait, no taker fee. |
| Redeem | After resolution, winning token → $1.00 pUSD | Cash out a resolved position (redeemPositions). |
Split and merge are the basis of CTF arbitrage: if Yes + No trade below
$1.00 on the book, buy both and merge back to $1.00; if they trade above $1.00,
split $1 into a fresh pair and sell both. Redemption settles through the
ConditionalTokens contract once the oracle posts the outcome on-chain - a position shows
redeemable: true on the Data API when it is claimable.
Position IDs derive via getConditionId → getCollectionId → getPositionId.
Advanced: RFQ & combo markets (for serious makers)
Beyond the order book, Polymarket runs a Request-for-Quote (RFQ) system, used especially for combo markets - existing markets bundled into multi-leg composite positions. The flow has three phases: a taker requests a quote, makers compete with quotes, and the chosen maker gets a last look to confirm or decline before execution.
- Discover combos:
GET /v1/rfq/combo-markets(public;limit1-100,cursor,exclude). Each combo exposes two position IDs (Yes = index 0, No = index 1). - Quote as a maker:
POST combos-rfq-api.polymarket.com/v1/maker/quotes(L2 auth). You generate thequote_idyourself, and sendrfq_id,maker_address,signature_type, a signed Exchange order, andprice_e6/size_e6as six-decimal fixed-point strings (the*_e6convention avoids float precision loss). - Last look: while the RFQ is
AWAITING_MAKER_CONFIRMATION, respondCONFIRM,DECLINE, or let itTIMED_OUT.
RFQ state machine: CREATED → COLLECTING_QUOTES → AWAITING_REQUESTER_ACCEPTANCE →
AWAITING_MAKER_CONFIRMATION → EXECUTING → FILLED (else FAILED / EXPIRED / CANCELED / REJECTED). Subscribe to
the RFQ WebSocket gateway for live state. This is niche - most bots only need the CLOB book above - but it is how
multi-leg and combo liquidity gets priced.
Check balance & allowance
client.get_balance_allowance(...) # collateral (pUSD) and conditional-token allowances
If this shows zero allowance, approve pUSD/CTF to the V2 exchange contracts before ordering.
outcomes array (Gamma returns it, and
clobTokenIds, as JSON-encoded strings you must decode) and map by name.Next: Authentication & wallets · WebSocket: stream the book · Fix a CLOB error.



