py-clob-client-v2 is Polymarket’s official Python SDK for trading on the CLOB (Central Limit Order Book) API. It installs as py-clob-client-v2 and imports as py_clob_client_v2. This reference documents every public method — signature, parameters, return type, and working code example — so you can look up exactly how to call any function without reading source code.
⚠️ This page documents CLOB V2 (live April 28, 2026). Polymarket migrated its entire trading stack to CLOB V2 in a hard cutover. The old V1 package (
py-clob-client) and V1-signed orders no longer work on production — you must usepy-clob-client-v2. V2 also renamed several methods (create_or_derive_api_creds()→create_or_derive_api_key(),get_orders()→get_open_orders(),cancel()→cancel_order()), removed others (get_balance(),get_positions()), switched theBUY/SELLconstants to aSideenum, migrated collateral from USDC.e to pUSD, and changed the order struct and fee model. Migrating from V1? See Polymarket’s Migrating to CLOB V2 guide and the Polymarket API Tutorial.
For a step-by-step tutorial on the full Polymarket API ecosystem, see the Polymarket API Tutorial. For side-by-side comparison with Kalshi’s Python SDK, see the Prediction Market API Reference.
Try it live: Test Polymarket endpoints in the API Playground — no setup required.
Why This Page Exists (What the README Doesn’t Cover)
The py-clob-client-v2 README and examples/ directory give you copy-pasteable starting points for unauthenticated and authenticated clients, market/limit orders, and token allowances. If you just need to get started, those are now good enough. This page exists for everything after that:
- The Common Pitfalls table documents the bugs and silent failures the README doesn’t mention — installing the retired V1 package, the
Sideenum,signature_typeconfusion, FOK on thin markets, missing pUSD allowances - The Migrating from V1 section maps every renamed and removed method so V1 code you find online doesn’t lead you astray
- The deep-dive sub-pages go far beyond the README’s examples with production error handling, retry patterns, and real-world code
- The Choosing the Right Method Pattern decision tree helps you pick the right workflow for your use case
- The Polymarket US compatibility note answers whether py-clob-client-v2 works with the CFTC-regulated US platform (it doesn’t)
- The RFQ documentation covers the institutional-trading sub-client the README barely mentions
CLOB V2 cutover (April 28, 2026): Polymarket rebuilt its trading stack — new Exchange contracts, a rewritten CLOB backend, new V2 SDK packages, a new order struct, a new fee model, pUSD collateral (replacing USDC.e), and a new builder-attribution mechanism. There is no backward compatibility: the V1 packages (
py-clob-client,@polymarket/clob-client) and V1-signed orders stopped working on production at cutover. Usepy-clob-client-v2(Python),@polymarket/clob-client-v2(TypeScript, now built on viem), andrs-clob-client-v2(Rust). This reference has been fully updated for V2.
Quick Method Lookup
| Method | Category | What It Does |
|---|---|---|
get_balance_allowance() | Balance | pUSD/token balance + allowance (there is no get_balance() in V2) |
update_balance_allowance() | Balance | Refresh the cached balance/allowance |
get_price() | Order Book | Current price for token/side |
get_midpoint() | Order Book | Mid between best bid/ask |
get_order_book() | Order Book | Full bids/asks |
get_order_books() | Order Book | Batch — multiple tokens |
create_order() | Trading | Sign a limit order |
create_market_order() | Trading | Sign a market order |
create_and_post_order() | Trading | Sign + post a limit order in one call |
create_and_post_market_order() | Trading | Sign + post a market order in one call |
post_order() | Trading | Submit signed order |
post_orders() | Trading | Batch submit (up to 15) |
get_order() | Management | Single order by ID |
get_open_orders() | Management | All open orders (was get_orders() in V1) |
cancel_order() | Management | Cancel one order (was cancel() in V1) |
cancel_orders() | Management | Cancel a list of orders by hash |
cancel_all() | Management | Cancel all orders |
cancel_market_orders() | Management | Cancel all orders in one market |
get_clob_market_info() | Market | Tick size, min order size, fees, tokens |
create_or_derive_api_key() | Auth | Derive API credentials (was create_or_derive_api_creds()) |
set_api_creds() | Auth | Activate credentials |
Positions: CLOB V2 has no
client.get_positions(). Fetch positions from the Data API —GET https://data-api.polymarket.com/positions?user=<address>. RFQ methods live on theclient.rfqsub-client.
Common Pitfalls
Before diving into the method reference, here are the issues that trip up most developers — none of which are documented in the official README:
| Pitfall | What Happens | Fix |
|---|---|---|
| Using the V1 package | py-clob-client orders are rejected on production after the V2 cutover | Install py-clob-client-v2 and from py_clob_client_v2 import ClobClient — V1-signed orders no longer settle |
Bare BUY/SELL import | ImportError / NameError — V1’s order_builder.constants import is gone | Use the Side enum: from py_clob_client_v2 import Side then Side.BUY / Side.SELL |
| Wei conversion | get_balance_allowance() returns "1250000000" and you think you have 1.25B pUSD | Divide the balance field by 1e6 — pUSD uses 6 decimals, not 18 |
Wrong signature_type | Auth silently fails, orders rejected | 0 = EOA (MetaMask), 1 = POLY_PROXY (Magic/email), 2 = POLY_GNOSIS_SAFE, 3 = POLY_1271 deposit wallet (recommended for new API users) |
Missing funder | Orders attributed to wrong address | Required for proxy/Safe/deposit wallets — this is the address holding your funds |
| FOK on thin markets | Market orders fail completely | If liquidity is thin, use FAK (fill-and-kill) for partial fills instead of FOK |
| No rate limit handling | Script crashes on 429 | SDK doesn’t handle retries — implement exponential backoff yourself. See Rate Limits Guide |
| Stale order book | Prices moved between read and trade | Use WebSocket for real-time data. See WebSocket Guide |
| Missing pUSD allowance (EOA) | Orders fail with no clear error | Check get_balance_allowance(AssetType.COLLATERAL) first — allowance must be > 0 (CLOB V2 collateral is pUSD) |
| Hyphen vs underscore | import py-clob-client-v2 fails | Package installs as py-clob-client-v2 but imports as py_clob_client_v2 |
Looking for get_positions() | AttributeError — the method was removed in V2 | Positions come from the Data API, not the client |
Deep-Dive Method Guides
For expanded examples, error handling, and production patterns, see the dedicated guides for the most-used methods:
- get_order_book() — OrderBookSummary, batch retrieval, spread calculation, depth analysis
- get_balance_allowance() — BalanceAllowanceParams, AssetType, wei conversion, pre-trade validation
- Position tracking — Reading positions from the Data API and computing P&L (CLOB V2 has no
get_positions()client method) - create_order() — OrderArgs, MarketOrderArgs, GTC/GTD/FOK/FAK, tick_size, neg_risk, batch orders
Migrating from V1 (CLOB V2 Changes)
If you’re porting a V1 bot — or copy-pasting V1 code you found online — these are the changes that will break first. CLOB V2 went live April 28, 2026, and the V1 py-clob-client package no longer works against production.
Package and imports:
| V1 | V2 |
|---|---|
pip install py-clob-client | pip install py-clob-client-v2 |
from py_clob_client.client import ClobClient | from py_clob_client_v2 import ClobClient |
from py_clob_client.clob_types import OrderArgs, ... | from py_clob_client_v2 import OrderArgs, ... (all types are top-level) |
from py_clob_client.order_builder.constants import BUY, SELL | from py_clob_client_v2 import Side → Side.BUY / Side.SELL |
Renamed methods:
| V1 | V2 |
|---|---|
create_or_derive_api_creds() | create_or_derive_api_key() |
get_orders() | get_open_orders() |
cancel(order_id) | cancel_order(OrderPayload(orderID=...)) |
Removed methods (and what to use instead):
| Removed in V2 | Replacement |
|---|---|
get_balance() | get_balance_allowance(BalanceAllowanceParams(asset_type=AssetType.COLLATERAL)) |
get_positions() | Data API — GET https://data-api.polymarket.com/positions?user=<address> |
Top-level get_rfq_quote() / accept_rfq_quote() | The client.rfq sub-client |
Behavioral changes:
- Collateral is pUSD, not USDC.e. Balances and allowances are denominated in pUSD (still 6 decimals). API-only EOA traders wrap USDC.e → pUSD via the Collateral Onramp; proxy/Safe/deposit wallets handle this for you.
signature_typeadds POLY_1271 (3) for deposit wallets, now recommended for new API users.SignatureTypeV2is an enum (SignatureTypeV2.POLY_1271, etc.) but plain integers still work.- The order struct dropped
nonce,feeRateBps, andtakerand addedtimestamp,metadata, andbuilder.OrderArgs/MarketOrderArgstherefore no longer takefee_rate_bps/nonce/taker; they takebuilder_code,metadata, anduser_usdc_balance. - Fees are protocol-set at match time, not embedded in your signed order. Don’t try to set a fee — read the live rate with
get_fee_rate_bps()orget_clob_market_info(). create_order()andcreate_and_post_order()take anoptionsargument (PartialCreateOrderOptions(tick_size=..., neg_risk=...)).- Pre-migration orders: V1 orders placed before the cutover are read via
get_pre_migration_orders().
Note:
py-clob-client-v2is a young package (first published April 2026). Watch its GitHub Issues and theexamples/directory for the current method surface — the V2 API may still shift between minor releases.
Installation and Setup
Installing py-clob-client-v2
pip install py-clob-client-v2
The package name uses hyphens (py-clob-client-v2) but the Python import uses underscores (py_clob_client_v2). The old V1 package (py-clob-client) is retired — it no longer works against production after the CLOB V2 cutover.
Community alternative: The
polymarket-apispackage wraps CLOB, Gamma, Data, Web3, WebSocket, and GraphQL clients with Pydantic validation. Confirm it targets CLOB V2 before relying on it for trading — community wrappers can lag the official V2 release. See the full comparison below if you’re deciding between the two.
ClobClient Initialization
ClobClient is the main entry point for all SDK operations.
Signature:
ClobClient(
host: str,
chain_id: int,
key: str = None,
creds: ApiCreds = None,
signature_type: int = None,
funder: str = None,
builder_config: BuilderConfig = None,
use_server_time: bool = False,
retry_on_error: bool = False,
fee_slippage: float = 0,
)
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
host | str | Yes | CLOB API base URL. Use https://clob.polymarket.com for production |
chain_id | int | Yes | Blockchain chain ID. Use 137 for Polygon mainnet |
key | str | For trading | Your Ethereum private key (hex string with or without 0x prefix) |
creds | ApiCreds | No | Pre-derived API credentials. Pass these to skip the separate set_api_creds() call |
signature_type | int | No | Wallet type: 0 = EOA (MetaMask), 1 = POLY_PROXY (Magic/email), 2 = POLY_GNOSIS_SAFE, 3 = POLY_1271 deposit wallet (recommended new) |
funder | str | For proxy wallets | The proxy/Safe/deposit wallet address that holds your funds on Polymarket |
builder_config | BuilderConfig | No | Builder attribution config (see the Builder Program) |
use_server_time | bool | No | Sign with the CLOB server’s time instead of local time — useful when your clock drifts |
fee_slippage | float | No | Tolerance for the protocol-set fee when building market orders |
V2 change:
chain_idis now required (it has no default), and the constructor is called with keyword arguments in every official example. Note the newcreds,builder_config,use_server_time, andfee_slippageparameters.
Example — Read-only client (no authentication):
from py_clob_client_v2 import ClobClient
client = ClobClient(host="https://clob.polymarket.com", chain_id=137)
# Public endpoints work without auth
price = client.get_price(token_id="<token-id>", side="BUY")
Example — Authenticated client (EOA wallet):
from py_clob_client_v2 import ClobClient
# EOA (MetaMask) — funder is the EOA itself, so no signature_type/funder needed
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key="<your-private-key>",
)
client.set_api_creds(client.create_or_derive_api_key())
Example — Authenticated client (deposit wallet, POLY_1271 — recommended for new users):
from py_clob_client_v2 import ClobClient, SignatureTypeV2
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key="<your-private-key>",
signature_type=SignatureTypeV2.POLY_1271, # 3 — deposit wallet
funder="<your-deposit-wallet-address>",
)
client.set_api_creds(client.create_or_derive_api_key())
Example — Authenticated client (Magic/email proxy, POLY_PROXY):
from py_clob_client_v2 import ClobClient, SignatureTypeV2
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key="<your-private-key>",
signature_type=SignatureTypeV2.POLY_PROXY, # 1 — Magic/email; use POLY_GNOSIS_SAFE (2) for a Safe
funder="<your-proxy-wallet-address>",
)
client.set_api_creds(client.create_or_derive_api_key())
Authentication: create_or_derive_api_key()
Derives or creates API credentials from your wallet signature. Call this once, then reuse the credentials. This method was renamed in V2 — it was create_or_derive_api_creds() in V1.
Signature:
client.create_or_derive_api_key(nonce: int = None) -> ApiCreds
Returns: An ApiCreds object containing your API key, secret, and passphrase. Pass this to set_api_creds() to enable authenticated endpoints.
Usage:
creds = client.create_or_derive_api_key()
client.set_api_creds(creds)
# Now you can use authenticated endpoints (trading, balance, etc.)
You only need to derive credentials once per session. The credentials are deterministic — deriving them again with the same wallet produces the same result. If you already have your ApiCreds, you can pass them straight into the constructor (ClobClient(..., creds=ApiCreds(...))) and skip set_api_creds() entirely.
Related auth methods:
create_api_key()(force-create new creds),derive_api_key()(derive existing creds only),get_api_keys()(list), anddelete_api_key(). For monitoring agents that must never trade, usecreate_readonly_api_key()(see below).
Readonly API Keys
Create read-only API credentials that allow market data queries but prevent order placement — useful for monitoring dashboards and analytics agents that should never trade. V2 exposes create_readonly_api_key(), get_readonly_api_keys(), and delete_readonly_api_key(key).
Token Allowances (EOA Wallets)
If you use a standard EOA wallet (MetaMask, hardware wallet), you must set token allowances before trading. This is a one-time on-chain transaction that approves the V2 Exchange contracts to spend your pUSD (CLOB V2 migrated collateral from USDC.e to pUSD).
Check if allowances are set:
from py_clob_client_v2 import BalanceAllowanceParams, AssetType
result = client.get_balance_allowance(
BalanceAllowanceParams(asset_type=AssetType.COLLATERAL)
)
if int(result['allowance']) == 0:
print("No allowance set — you need to approve pUSD spending first")
# See: https://docs.polymarket.com/v2-migration for approval instructions
If allowance is 0, all order placements will fail silently or with a cryptic error. This is the #1 issue new developers hit with py-clob-client-v2 on EOA wallets. Proxy, Safe, and deposit-wallet users (email/browser/POLY_1271) typically don’t need to worry about this — the proxy or deposit contract handles approvals.
Balance Methods
get_balance() — Removed in V2
There is no client.get_balance() method in CLOB V2. The standalone balance method was removed; use get_balance_allowance() instead (below), which returns both balance and allowance for a given asset type. If you’re porting V1 code that calls client.get_balance(), replace it:
# V1 (no longer works):
# balance_wei = client.get_balance()
# V2 equivalent:
from py_clob_client_v2 import BalanceAllowanceParams, AssetType
result = client.get_balance_allowance(
BalanceAllowanceParams(asset_type=AssetType.COLLATERAL)
)
balance_pusd = int(result["balance"]) / 1e6
print(f"Balance: {balance_pusd:.2f} pUSD")
Common pitfall: The balance field is in wei (micro-pUSD), not pUSD. Divide by 1e6 (or 10**6) to get the pUSD amount. Forgetting this conversion is a frequent source of bugs.
get_balance_allowance() Method
Returns both your balance and the token allowance for a specific asset type. This is the canonical way to check funds in V2 — it replaces the removed get_balance() — and is essential for checking whether you have sufficient allowance set for trading.
Signature:
client.get_balance_allowance(params: BalanceAllowanceParams = None) -> dict
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
params | BalanceAllowanceParams | No | Specifies the asset type and optional token ID |
BalanceAllowanceParams fields:
| Field | Type | Description |
|---|---|---|
asset_type | AssetType | AssetType.COLLATERAL for pUSD, or AssetType.CONDITIONAL for outcome tokens |
token_id | str | Required when asset_type is CONDITIONAL — the specific outcome token ID |
signature_type | int | Optional — override the client’s signature type for this lookup (defaults to -1 = unset) |
Returns: A dictionary with balance and allowance fields, both as strings in wei.
Example — Check pUSD balance and allowance:
from py_clob_client_v2 import ClobClient, BalanceAllowanceParams, AssetType
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key="<your-private-key>",
)
client.set_api_creds(client.create_or_derive_api_key())
result = client.get_balance_allowance(
BalanceAllowanceParams(asset_type=AssetType.COLLATERAL)
)
print(f"Balance: {int(result['balance']) / 1e6:.2f} pUSD")
print(f"Allowance: {result['allowance']}")
Example — Check conditional token balance:
result = client.get_balance_allowance(
BalanceAllowanceParams(
asset_type=AssetType.CONDITIONAL,
token_id="<outcome-token-id>"
)
)
print(f"Token balance: {result['balance']}")
print(f"Token allowance: {result['allowance']}")
update_balance_allowance() Method
After an on-chain deposit or approval, the CLOB caches your balance/allowance and may not reflect the change immediately. Call update_balance_allowance() with the same BalanceAllowanceParams to force a refresh:
client.update_balance_allowance(
BalanceAllowanceParams(asset_type=AssetType.COLLATERAL)
)
Position Tracking (Data API)
CLOB V2 has no client.get_positions() method. Positions live in the Data API, a separate public service — you query it by wallet address with no authentication. The CLOB client handles balances and allowances (get_balance_allowance()); positions (shares held, average entry, unrealized P&L) are a Data API job.
Endpoint:
GET https://data-api.polymarket.com/positions?user=<wallet-address>
Each position object includes (among other fields) asset (the outcome token ID), conditionId, size (shares held), avgPrice (average entry price), curPrice (current price), cashPnl/percentPnl (unrealized P&L), title, and outcome.
Example — List all positions for a wallet:
import requests
WALLET = "<your-wallet-address>" # the funder/proxy address holding your positions
positions = requests.get(
"https://data-api.polymarket.com/positions",
params={"user": WALLET},
).json()
for pos in positions:
token_id = pos["asset"]
size = float(pos["size"])
avg_price = float(pos["avgPrice"])
print(f"Token: {token_id[:16]}... | Shares: {size} | Avg Price: ${avg_price:.2f}")
Example — Check if you already hold a position before placing an order:
import requests
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions, Side
def has_position(wallet, target_token_id):
"""Check if we already hold a position in this outcome."""
positions = requests.get(
"https://data-api.polymarket.com/positions",
params={"user": wallet},
).json()
for pos in positions:
if pos["asset"] == target_token_id and float(pos["size"]) > 0:
return True
return False
# Only buy if we don't already have a position
if not has_position(WALLET, "<token-id>"):
client.create_and_post_order(
order_args=OrderArgs(token_id="<token-id>", price=0.50, size=10.0, side=Side.BUY),
options=PartialCreateOrderOptions(tick_size="0.01"),
order_type=OrderType.GTC,
)
The
userparameter is the funder address that holds your positions (your proxy/Safe/deposit wallet, or the EOA itself), not necessarily the signing key. See the Data API Reference for activity, trade history, and P&L endpoints.
Order Types
MarketOrderArgs
MarketOrderArgs (an alias for MarketOrderArgsV2) is the data class for specifying market orders — orders that execute immediately against resting liquidity at the best available price.
Import:
from py_clob_client_v2 import MarketOrderArgs, OrderType, Side
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
token_id | str | Yes | The outcome token ID to trade |
amount | float | Yes | USDC amount to spend (for BUY) or number of shares to sell (for SELL) |
side | Side | Yes | Side.BUY or Side.SELL |
order_type | OrderType | No | OrderType.FOK (default) or OrderType.FAK |
price | float | No | Auto-calculated from the book if omitted |
user_usdc_balance | float | No | Your collateral balance; if provided and too small, the order size is reduced to fit fees |
builder_code | str | No | bytes32 builder code for fee attribution (see the Builder Program) |
metadata | str | No | Optional bytes32 metadata attached to the order |
V2 change:
MarketOrderArgsno longer takesfee_rate_bps,nonce, ortaker. Fees are protocol-set at match time, not embedded in your order. The newuser_usdc_balancefield lets the SDK fee-adjust market buys.
Example — Buy $25 worth of YES tokens at market price (one-step):
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions, Side
response = client.create_and_post_market_order(
order_args=MarketOrderArgs(
token_id="<token-id>",
amount=25.0,
side=Side.BUY,
order_type=OrderType.FOK,
),
options=PartialCreateOrderOptions(tick_size="0.01"),
order_type=OrderType.FOK,
)
print(response)
Example — Sell 10 shares at market price (two-step):
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions, Side
sell_order = MarketOrderArgs(
token_id="<token-id>",
amount=10.0,
side=Side.SELL,
order_type=OrderType.FOK,
)
signed = client.create_market_order(sell_order, PartialCreateOrderOptions(tick_size="0.01"))
response = client.post_order(signed, OrderType.FOK)
Market orders use FOK (fill-or-kill) by default — the order must fill completely or it’s rejected entirely. If there isn’t enough resting liquidity to fill your full amount, switch to OrderType.FAK (fill-and-kill) to take what’s available and cancel the rest.
OrderArgs
OrderArgs (an alias for OrderArgsV2) is the data class for limit orders — orders that specify an exact price and rest on the order book until filled.
Import:
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions, Side
Fields:
| Field | Type | Required | Description |
|---|---|---|---|
token_id | str | Yes | The outcome token ID to trade |
price | float | Yes | Price per share in USDC (0.01 to 0.99) |
size | float | Yes | Number of shares to buy or sell |
side | Side | Yes | Side.BUY or Side.SELL |
expiration | int | No | Unix timestamp after which the order expires. 0 (default) = no expiration (GTC); set a future timestamp and post with OrderType.GTD |
builder_code | str | No | bytes32 builder code for fee attribution |
metadata | str | No | Optional bytes32 metadata attached to the order |
user_usdc_balance | float | No | If provided and insufficient to cover size × price plus fees, the size is reduced |
V2 change:
OrderArgsno longer takesnonce,fee_rate_bps, ortaker. It addsbuilder_code,metadata, anduser_usdc_balance. Tick size and neg-risk now live on the separateoptionsargument tocreate_order(), not onOrderArgs.
Example — Place a limit buy order:
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions, Side
order = OrderArgs(
token_id="<token-id>",
price=0.50,
size=10.0,
side=Side.BUY,
)
signed = client.create_order(order, PartialCreateOrderOptions(tick_size="0.01"))
response = client.post_order(signed, OrderType.GTC)
print(response)
Key difference from MarketOrderArgs: OrderArgs uses price + size (price per share and number of shares), while MarketOrderArgs uses amount (total USDC to spend). Limit orders can use GTC (good-til-cancelled), GTD (good-til-date, via expiration), FOK, or FAK; market orders use FOK or FAK.
Order Placement Methods
Placing orders is the core trading workflow. py-clob-client-v2 separates order creation (signing) from order submission (posting) to give you maximum control. For simple trades, use create_and_post_order() (limit) or create_and_post_market_order() (market) as a shortcut. For production bots that need logging, validation, or batching, use the two-step create_order() → post_order() pattern.
Choosing between limit and market orders depends on your urgency. Limit orders (OrderArgs) rest on the book until filled and give you price control — use them when you can wait for your price. Market orders (MarketOrderArgs) execute immediately against resting liquidity but give you no control over the fill price — use them when speed matters more than a few cents of slippage. Most autonomous agents use limit orders with GTC (good-til-cancelled) to avoid overpaying.
create_order() and post_order()
Order placement in py-clob-client-v2 is a two-step process: first sign the order locally, then post it to the CLOB API.
Signatures:
client.create_order(order_args: OrderArgs, options: PartialCreateOrderOptions = None) -> SignedOrder
client.post_order(signed_order, order_type: OrderType = OrderType.GTC, post_only: bool = False, defer_exec: bool = False) -> dict
create_order() Parameters:
| Parameter | Type | Description |
|---|---|---|
order_args | OrderArgs | The order specification (token, price, size, side) |
options | PartialCreateOrderOptions | tick_size and neg_risk for the market (fetched if omitted) |
post_order() Parameters:
| Parameter | Type | Description |
|---|---|---|
signed_order | signed order | The signed order from create_order() |
order_type | OrderType | OrderType.GTC, OrderType.GTD, OrderType.FOK, or OrderType.FAK |
post_only | bool | If True, rejects the order if it would immediately match. Use for market-making strategies |
defer_exec | bool | If True, defers matching-engine execution (advanced — for coordinated multi-order submission) |
Example:
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions, Side
order = OrderArgs(
token_id="<token-id>",
price=0.45,
size=20.0,
side=Side.BUY,
)
signed = client.create_order(order, PartialCreateOrderOptions(tick_size="0.01"))
response = client.post_order(signed, OrderType.GTC)
print(f"Order ID: {response['orderID']}")
Post-only example (for market makers):
signed = client.create_order(order, PartialCreateOrderOptions(tick_size="0.01"))
response = client.post_order(signed, OrderType.GTC, post_only=True)
# Rejects if the order would cross the spread
create_and_post_order()
Convenience method that combines create_order() and post_order() into a single call. For simple cases where you don’t need to inspect the signed order before posting.
Signature:
client.create_and_post_order(order_args: OrderArgs, options: PartialCreateOrderOptions = None, order_type: OrderType = OrderType.GTC, post_only: bool = False, defer_exec: bool = False) -> dict
Example:
from py_clob_client_v2 import ClobClient, OrderArgs, OrderType, PartialCreateOrderOptions, Side
client = ClobClient(host="https://clob.polymarket.com", chain_id=137, key="<key>")
client.set_api_creds(client.create_or_derive_api_key())
resp = client.create_and_post_order(
order_args=OrderArgs(price=0.50, size=100.0, side=Side.BUY, token_id="<token-id>"),
options=PartialCreateOrderOptions(tick_size="0.01"),
order_type=OrderType.GTC,
)
print(resp)
Use the two-step create_order() + post_order() workflow when you need to log, validate, or modify the signed order before submitting. Use create_and_post_order() for straightforward trades.
create_market_order() and create_and_post_market_order()
create_market_order() signs a market order for immediate execution; create_and_post_market_order() signs and submits it in one call (the market-order counterpart to create_and_post_order()).
Signatures:
client.create_market_order(order_args: MarketOrderArgs, options: PartialCreateOrderOptions = None) -> SignedOrder
client.create_and_post_market_order(order_args: MarketOrderArgs, options: PartialCreateOrderOptions = None, order_type: OrderType = OrderType.FOK, defer_exec: bool = False) -> dict
Example:
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions, Side
market_order = MarketOrderArgs(
token_id="<token-id>",
amount=50.0,
side=Side.BUY,
order_type=OrderType.FOK,
)
# One-step:
response = client.create_and_post_market_order(
order_args=market_order,
options=PartialCreateOrderOptions(tick_size="0.01"),
order_type=OrderType.FOK,
)
Batch Orders
Place up to 15 orders in a single API call. Essential for market makers updating multiple price levels.
Signature:
client.post_orders(args: list, post_only: bool = False, defer_exec: bool = False) -> dict
Example:
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions, Side
opts = PartialCreateOrderOptions(tick_size="0.01")
orders = []
for price in [0.48, 0.49, 0.50]:
order = OrderArgs(
token_id="<token-id>",
price=price,
size=50.0,
side=Side.BUY,
)
orders.append(client.create_order(order, opts))
response = client.post_orders(orders, post_only=False)
Note: In V2 the order type travels with each signed order, so
post_orders()takespost_only/defer_execflags rather than a singleorder_typefor the whole batch.
Order Management Methods
After placing orders, you need to track their status, monitor fills, and cancel orders that are no longer wanted. These methods give you full visibility into your open and historical orders. In production bots, the typical pattern is: place orders, poll get_open_orders() periodically to check fill status, and cancel stale unfilled orders with cancel_order() or cancel_all().
get_order()
Retrieves a single order by its ID.
Signature:
client.get_order(order_id: str) -> dict
Example:
order = client.get_order("<order-id>")
print(f"Status: {order['status']}")
print(f"Filled: {order['size_matched']} / {order['original_size']}")
get_open_orders()
Retrieves all your open orders, optionally filtered. This was get_orders() in V1 — it was renamed in V2.
Signature:
client.get_open_orders(params: OpenOrderParams = None) -> list
Example:
open_orders = client.get_open_orders()
for order in open_orders:
print(f"Order {order['id']}: {order['side']} {order['original_size']} @ {order['price']}")
Migrating? Orders placed before the CLOB V2 cutover aren’t returned here — read them with
client.get_pre_migration_orders().
cancel_order()
Cancels a single order. This was cancel(order_id) in V1 — V2 renamed it and it now takes an OrderPayload instead of a bare ID string.
Signature:
client.cancel_order(payload: OrderPayload) -> dict
Example:
from py_clob_client_v2 import OrderPayload
response = client.cancel_order(OrderPayload(orderID="<order-id>"))
print(response)
cancel_orders() and cancel_market_orders()
Cancel a specific list of orders by hash, or every open order in a single market:
from py_clob_client_v2 import OrderMarketCancelParams
# Cancel a list of orders by hash
client.cancel_orders(["<order-hash-1>", "<order-hash-2>"])
# Cancel all open orders in one market
client.cancel_market_orders(OrderMarketCancelParams(market="<condition-id>"))
cancel_all()
Cancels all your open orders across all markets.
Signature:
client.cancel_all() -> dict
Example:
response = client.cancel_all()
print(f"Cancelled all open orders")
RFQ (Request for Quote) Methods
RFQ enables negotiated pricing for large orders. Instead of placing an order directly on the book, a requester asks for a quote and market makers respond with firm prices.
V2 change: RFQ is no longer a set of top-level client methods (V1’s
client.get_rfq_quote()/client.accept_rfq_quote()). In V2 it lives on a dedicatedclient.rfqsub-client with an explicit requester/quoter split.
Who uses this: Institutional traders, high-volume agents, and market makers executing large positions where market impact is a concern. The typical flow is: requester creates a request → market makers respond with quotes → requester accepts the best quote → the trade executes off-book. Most retail traders and simple bots should use standard limit/market orders.
client.rfq methods:
| Method | Role | What It Does |
|---|---|---|
create_rfq_request(...) | Requester | Open an RFQ for a token/size |
cancel_rfq_request(params) | Requester | Cancel an open request |
get_rfq_requests(params) | Both | List RFQ requests |
get_rfq_best_quote(params) | Requester | Read the best quote received |
get_rfq_requester_quotes(params) | Requester | Quotes from the requester’s view |
accept_rfq_quote(params) | Requester | Accept a quote (AcceptQuoteParams) and execute off-book |
create_rfq_quote(...) | Quoter | Respond to a request with a firm price |
cancel_rfq_quote(params) | Quoter | Cancel a quote you posted |
get_rfq_quoter_quotes(params) | Quoter | Quotes from the quoter’s view |
approve_rfq_order(params) | Quoter | Approve an order for an accepted quote |
rfq_config() | Both | Read current RFQ configuration |
Example — requester flow (sketch):
# RFQ lives on the sub-client in V2:
request = client.rfq.create_rfq_request(...) # open the request
best = client.rfq.get_rfq_best_quote(...) # read the best quote back
client.rfq.accept_rfq_quote(...) # accept it -> off-book execution
The RFQ param/response dataclasses (
AcceptQuoteParams,CancelRfqRequestParams,GetRfqQuotesParams, etc.) live inpy_clob_client_v2.rfq. Because the RFQ surface is the newest part of the V2 SDK, check therfqmodule for current signatures before building against it.
RFQ vs Standard Orders
| Factor | Standard Orders | RFQ |
|---|---|---|
| Market impact | Visible on the order book | Off-book, no impact |
| Price discovery | You set the price (limit) or take the book (market) | Market makers compete to quote you |
| Size limits | Batch up to 15 orders | Single large block trades |
| Speed | Immediate (GTC rests, FOK fills or fails) | Requires quote round-trip |
| Best for | < $10K positions, automated strategies | > $10K positions, institutional flow |
Price and Order Book Methods
These methods provide market data — current prices, midpoints, and full order books. They work without authentication, so you can use them from a read-only client. For real-time data, consider the Polymarket WebSocket API instead of polling these endpoints. Polling is simpler to implement but consumes rate limit budget and introduces latency between price changes and your bot’s awareness of them.
When building a trading bot, the typical pattern is to use get_order_book() for initial state, then switch to WebSocket for live updates. Use get_midpoint() for quick price checks, and get_price() when you need the best available price on a specific side (bid vs ask).
get_price()
Returns the current price for a specific token and side.
Signature:
client.get_price(token_id: str, side: str) -> str
Parameters:
| Parameter | Type | Description |
|---|---|---|
token_id | str | The outcome token ID |
side | str | "BUY" or "SELL" — the side you want the price for |
Example:
buy_price = client.get_price(token_id="<token-id>", side="BUY")
sell_price = client.get_price(token_id="<token-id>", side="SELL")
print(f"Buy at: ${buy_price} | Sell at: ${sell_price}")
get_midpoint()
Returns the midpoint between the best bid and best ask.
Signature:
client.get_midpoint(token_id: str) -> str
Example:
mid = client.get_midpoint(token_id="<token-id>")
print(f"Midpoint: ${mid}")
get_order_book()
Returns the full order book for a token.
Signature:
client.get_order_book(token_id: str) -> dict
Returns: An OrderBookSummary with bids and asks arrays, each containing price/size entries sorted by price. The /book response also carries a few trading parameters inline — min_order_size, neg_risk, and tick_size — so you don’t need a separate lookup for them. For market context (question text, slug, end date, outcome labels) use the Gamma API or get_clob_market_info().
Example:
book = client.get_order_book(token_id="<token-id>")
print("Top 5 bids:")
for bid in book["bids"][:5]:
print(f" ${bid['price']} — {bid['size']} shares")
print("Top 5 asks:")
for ask in book["asks"][:5]:
print(f" ${ask['price']} — {ask['size']} shares")
get_order_books()
Batch endpoint — fetch order books for multiple tokens in one request.
Signature:
client.get_order_books(params: list[BookParams]) -> list
Example:
from py_clob_client_v2 import BookParams
books = client.get_order_books([
BookParams(token_id="<token-id-1>"),
BookParams(token_id="<token-id-2>"),
])
More market-data methods: V2 also exposes batch and history variants —
get_prices(),get_midpoints(),get_spread()/get_spreads(),get_last_trade_price()/get_last_trades_prices(), andget_prices_history()— plusget_clob_market_info()for tick size, min order size, fees, and tokens in one call.
Bridge Operations
The Polymarket Bridge API includes a POST /withdraw endpoint for bridging funds to other chains. This endpoint is accessed via the Bridge API (https://bridge.polymarket.com/withdraw), not through py-clob-client-v2 directly. (CLOB V2 collateral is pUSD; the Bridge handles the on/off-ramp.) See the Polymarket API Guide — Bridge API for endpoint documentation and example code.
Choosing the Right Method Pattern
For quick reference, here is how common trading workflows map to SDK methods:
| Workflow | Methods | Notes |
|---|---|---|
| Check if I can trade | get_balance_allowance() | Verify pUSD balance (divide by 1e6) and that allowance > 0 — there’s no get_balance() in V2 |
| Find a market to trade | Use Gamma API (requests.get) → get_order_book() | Gamma for discovery, CLOB for execution data |
| Place a simple bet | create_and_post_order() (limit) / create_and_post_market_order() (market) | One-step convenience methods |
| Place a bet with validation | create_order() → inspect → post_order() | Two-step when you need to log or validate before submitting |
| Place many orders at once | Loop create_order() → post_orders() | Batch up to 15 orders in a single API call |
| Buy immediately at market price | create_and_post_market_order(FOK) | Use FOK for full fill; switch to FAK if liquidity is thin |
| Check position before trading | Data API GET /positions → check → create_order() | Positions come from the Data API, not the client |
| Cancel everything | cancel_all() | Emergency reset; also useful at bot shutdown |
| Monitor fills | get_order() or get_open_orders() | Poll periodically or use WebSocket for real-time fill events |
For expanded examples and production patterns on each method, see the deep-dive guides linked in the method lookup table at the top of this page.
Version History
CLOB V2 is a clean break from the V1 release line, so this table tracks the V1 → V2 transition rather than individual V2 point releases. The py-clob-client-v2 package is young and moves quickly — check PyPI and the GitHub releases for the current version.
| Milestone | Date | Key Changes |
|---|---|---|
| CLOB V2 cutover | Apr 28, 2026 | Hard migration to py-clob-client-v2: new Exchange contracts, rewritten CLOB backend, a new order struct (drops nonce/feeRateBps/taker, adds timestamp/metadata/builder), protocol-set fees, pUSD collateral, the Side enum, options-based order creation, the RFQ sub-client, method renames (create_or_derive_api_key, get_open_orders, cancel_order), and removal of get_balance()/get_positions(). V1 packages and V1-signed orders stopped working on production. |
| py-clob-client v0.34.6 (final V1) | Feb 19, 2026 | Last notable V1 release before V2 superseded it (tick size cache fix). V1 is now retired |
| py-clob-client v0.31.0 | 2025 | V1 introduced RFQ methods and readonly API keys |
For the V2 changelog, see py-clob-client-v2 releases on GitHub. For Polymarket’s platform-level changes, see the Polymarket Changelog and Migrating to CLOB V2.
Polymarket US Compatibility
py-clob-client-v2 does not work with Polymarket US. This is the most common source of confusion for US-based developers.
Polymarket US is a CFTC-regulated Designated Contract Market (DCM) that launched after receiving CFTC approval in November 2025. It operates on a completely separate infrastructure from the global Polymarket platform:
| Global Polymarket | Polymarket US | |
|---|---|---|
| API endpoint | clob.polymarket.com | api.polymarket.us |
| Auth scheme | EIP-712 (wallet signing) | Ed25519 (key-pair signing) |
| Python SDK | py-clob-client-v2 | Separate CFTC-compliant SDKs |
| KYC required | No | Yes (mandatory) |
| Regulation | Unregulated (non-US) | CFTC-regulated DCM |
If you need to integrate with the US platform, you’ll need to use the SDKs provided at polymarketexchange.com/developers.html. Pointing ClobClient at api.polymarket.us will fail — the authentication schemes are fundamentally incompatible.
The Polymarket US developer portal now notes that the Trading Gateway is being deprecated in favor of the Exchange Gateway — new integrations should target the Exchange Gateway. No official Python SDK has been announced for Polymarket US as of May 2026.
For more on the differences between global and US Polymarket APIs, see the Polymarket API Guide.
py-clob-client-v2 vs polymarket-apis
Two Python packages exist for Polymarket development. Here’s when to use each.
| py-clob-client-v2 | polymarket-apis | |
|---|---|---|
| Maintainer | Polymarket (official) | Community (qualiaenjoyer) |
| CLOB version | CLOB V2 | Confirm V2 support before trading |
| API coverage | CLOB only | CLOB, Gamma, Data, Web3, WebSockets, GraphQL |
| Type safety | Dataclasses | Pydantic validation |
| Install | pip install py-clob-client-v2 | pip install polymarket-apis |
Use py-clob-client-v2 when:
- You’re building a trading bot focused on order placement and management
- You want the official SDK that Polymarket maintains and tests against their API
- Your project only interacts with the CLOB (order book, orders, balances)
- You need V2 signing — it’s guaranteed to track the current Exchange contracts and order struct
Use polymarket-apis when:
- You need market discovery (Gamma), portfolio analytics (Data API), and real-time streaming (WebSockets) in one package
- You want Pydantic-validated response models with type safety
- You want a single unified client instead of juggling
py_clob_client_v2+requestsfor Gamma + custom WebSocket code - Caveat: community wrappers can lag the official V2 release — confirm it signs CLOB V2 orders correctly before trusting it with real funds
Can you use both? Yes — some projects use polymarket-apis for market discovery and data, then switch to py-clob-client-v2 for order execution where they want the official V2 signing logic. The two packages don’t conflict.
See Also
- get_order_book() Deep Dive — OrderBookSummary, batch retrieval, spread and depth analysis
- get_balance_allowance() Deep Dive — BalanceAllowanceParams, wei conversion, pre-trade validation
- Position Tracking Deep Dive — Reading positions from the Data API, P&L calculation (no
get_positions()in V2) - create_order() Deep Dive — OrderArgs, MarketOrderArgs, tick_size, neg_risk, batch orders
- Polymarket API: The Complete Developer Guide — Conceptual overview of all Polymarket APIs
- Polymarket WebSocket & Orderbook Guide — Real-time streaming and orderbook reconstruction
- Polymarket Auth Troubleshooting — POLY headers, signatureType, common errors
- Polymarket TypeScript SDK Reference — @polymarket/clob-client-v2 equivalent (viem-based)
- Polymarket Rust SDK Reference — High-performance Rust SDK
- Polymarket Gamma API Deep Dive — Market discovery and price history
- Polymarket Subgraph Guide — On-chain data via GraphQL
- Prediction Market API Reference — Side-by-side Polymarket vs Kalshi comparison
- Polymarket Rate Limits Guide — Concrete per-endpoint limits and retry strategies
- py-clob-client-v2 on GitHub — Official V2 source code, examples, and issues
- API Playground — Test endpoints live in your browser
- Sports Betting vs Prediction Markets — How py-clob-client-v2 fits in the broader betting API landscape
- Offshore Sportsbook API Guide — Data access patterns for traditional sportsbooks (no SDK equivalent)
- Migrating to CLOB V2 — Polymarket’s official V1 → V2 migration guide
- Polymarket Changelog — Official changelog for API updates, fee changes, and new endpoints
This reference is maintained by AgentBets.ai. Found an error or SDK change we missed? Let us know on Twitter.
Not financial advice. Built for builders.
