The Polymarket API spans three REST hosts rather than one base URL. CLOB https://clob.polymarket.com handles trading — auth is EIP-712 (L1 private key → derive L2 API credentials), collateral is pUSD, chain ID 137 (Polygon). Gamma https://gamma-api.polymarket.com is read-only market discovery with no auth. Data https://data-api.polymarket.com serves positions, trades, and holders. The live SDK is py-clob-client-v2 v1.1.0; V1 py-clob-client has been archived and non-functional since the April 28, 2026 CLOB V2 cutover.
from py_clob_client_v2 import ClobClient
client = ClobClient(host="https://clob.polymarket.com", chain_id=137, key="<private-key>")
client.set_api_creds(client.create_or_derive_api_key())
US users: the global API remains geoblocked for trading; the CFTC-regulated Polymarket US stack at api.polymarket.us (Ed25519 auth, KYC, separate SDKs) is the compliant path — see the Polymarket US vs. Global API Guide.
Hosts and SDK versions verified 2026-09-02.
This tutorial walks you through the API from first authentication to a working trading bot. You’ll set up py-clob-client-v2, authenticate with EIP-712, place orders, stream prices via WebSocket, and handle rate limits — all with tested Python code. Building a bot right now? Jump straight to Putting It Together: A Minimal Trading Agent.
CLOB V2 is live (April 28, 2026). Polymarket migrated its entire trading stack to CLOB V2 in a hard cutover: 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 SDKs (
py-clob-client,@polymarket/clob-client) and V1-signed orders stopped working on production at cutover. This guide has been updated for V2. Migrating from V1? See Polymarket’s Migrating to CLOB V2 guide.
Polymarket splits its functionality across three APIs (CLOB, Gamma, Data) plus WebSocket channels. This guide covers them all in the order you’ll need them. For a method-by-method SDK reference, see the py_clob_client Reference. For a side-by-side comparison of Polymarket and Kalshi endpoints, see the Prediction Market API Reference.
Last verified against Polymarket’s CLOB V2 API: September 2, 2026. We update this guide whenever the API changes. Check the Polymarket Changelog for the latest updates.
Try it live: Test these endpoints instantly in the API Playground — no setup, no keys, real data in your browser.
Architecture Overview
Polymarket’s API isn’t one API — it’s three primary APIs plus a Bridge API and real-time streaming channels. Understanding this architecture is essential before writing any code.
| Service | Base URL | Auth Required | Purpose |
|---|---|---|---|
| CLOB API | https://clob.polymarket.com | Partial (trading endpoints) | Order book, prices, order management |
| Gamma API | https://gamma-api.polymarket.com | No | Market discovery, metadata, events |
| Data API | https://data-api.polymarket.com | No | User positions, trade history, leaderboards |
| Bridge API | https://bridge.polymarket.com | Yes | Deposits and withdrawals (proxies fun.xyz) |
Real-time streaming channels (not separate REST APIs):
| Channel | Endpoint | Auth | Purpose |
|---|---|---|---|
| Market WebSocket | wss://ws-subscriptions-clob.polymarket.com/ws/market | No | Orderbook updates, price changes, new markets |
| User WebSocket | wss://ws-subscriptions-clob.polymarket.com/ws/user | Yes | Order fills, cancellations, status updates |
| Sports WebSocket | wss://sports-api.polymarket.com/ws | No | Live game scores and status |
| RTDS | wss://ws-live-data.polymarket.com | Optional | Crypto prices, comments stream |
Polymarket’s sports channel covers game scores and status, but not traditional odds formats. For comparing prediction market probabilities against sportsbook lines, see Offshore Sportsbook Odds Normalization and the Offshore Sportsbook API Guide.
Polymarket US: A separate CFTC-regulated API exists at
api.polymarket.uswith different auth (Ed25519), different SDKs, and KYC requirements. See the Polymarket US vs. Global API Guide for a complete comparison.
The mental model: Use the Gamma API to discover markets. Use the CLOB API to read prices and trade. Use the Data API to track positions and history. Use WebSockets for real-time updates.
How Polymarket Works Under the Hood
Before diving into endpoints, you need to understand the on-chain architecture because it affects how you interact with the API.
Polymarket runs on the Polygon blockchain. Markets use the Conditional Token Framework (CTF), an ERC-1155 standard where each market outcome is a tradable token. When you “buy YES” on a market, you’re actually acquiring YES outcome tokens.
The CLOB (Central Limit Order Book) is hybrid-decentralized: order matching happens off-chain for speed, but settlement happens on-chain for security. Orders are EIP-712 signed messages — you sign a structured order with your private key, and the operator matches it off-chain, then settles the swap on-chain via the Exchange contract. (CLOB V2 deployed new Exchange contracts and bumped the EIP-712 Exchange signing domain from version 1 to 2; the V2 SDKs handle this for you.)
Key implications for developers:
- You need a Polygon wallet (private key) to trade
- pUSD is the collateral asset (CLOB V2) — positions are denominated in pUSD (Polymarket USD), an ERC-20 on Polygon backed 1:1 by USDC. The polymarket.com UI wraps USDC.e → pUSD automatically (one-time approval); API-only traders must wrap USDC.e into pUSD via the Collateral Onramp contract’s
wrap()function before trading. (Pre-V2, collateral was USDC.e directly.) - Token IDs are critical — every market outcome has a unique token ID (not a ticker symbol)
- Prices range from 0.00 to 1.00 — representing the probability (and cost in USDC) of that outcome
- YES + NO prices should sum to ~$1.00 — any deviation is an arbitrage opportunity
- Tick sizes matter — most markets use 0.01 ticks, but some use 0.001
Getting Started: Your First API Call (No Auth Required)
The fastest way to start is reading public market data. No wallet, no keys, no authentication.
Fetch All Active Markets (Gamma API)
import requests
# Fetch open markets from the Gamma API
response = requests.get(
"https://gamma-api.polymarket.com/markets",
params={
"closed": False,
"limit": 10
}
)
markets = response.json()
for market in markets:
print(f"{market['question']}")
print(f" Token ID (YES): {market['clobTokenIds']}")
print(f" Outcome Prices: {market['outcomePrices']}")
print(f" Volume: ${float(market.get('volume', 0)):,.0f}")
print()
Get a Price (CLOB API)
# Get the current price for a specific outcome token
token_id = "<your-token-id>" # Get this from the Gamma API response
price = requests.get(
f"https://clob.polymarket.com/price",
params={
"token_id": token_id,
"side": "BUY"
}
)
print(f"Current buy price: {price.json()['price']}")
Get the Order Book (CLOB API)
book = requests.get(
f"https://clob.polymarket.com/book",
params={"token_id": token_id}
)
data = book.json()
print(f"Best bid: {data['bids'][0]['price'] if data['bids'] else 'No bids'}")
print(f"Best ask: {data['asks'][0]['price'] if data['asks'] else 'No asks'}")
print(f"Midpoint: {data.get('mid', 'N/A')}")
Authentication
Public endpoints (prices, order books, market listings) require no authentication. Trading endpoints (placing orders, canceling orders, checking your positions) require EIP-712 signed requests.
How Authentication Works
- You have a private key — from an EOA (MetaMask), a deposit wallet (POLY_1271), an email/Magic proxy, or a Gnosis Safe
- You derive API credentials — the client library generates a key/secret pair from your wallet signature
- You sign each trading request — using five L2 headers:
POLY_ADDRESS,POLY_SIGNATURE,POLY_TIMESTAMP,POLY_API_KEY, andPOLY_PASSPHRASE
Auth issues? See our Polymarket Auth Troubleshooting Guide for common error codes (
INVALID_SIGNATURE,NONCE_ALREADY_USED, clock drift) and step-by-step fixes.
Wallet Types and Signature Types
CLOB V2 supports four signature types. New API users should use a deposit wallet with POLY_1271 (type 3) — Polymarket now steers new integrations there rather than the older Safe/proxy flows. Existing Safe and proxy users are unaffected and can keep their current type.
| Wallet Type | signature_type | funder Required | Notes |
|---|---|---|---|
| EOA (MetaMask) | 0 | No — funder is the EOA | Direct wallet; needs POL for gas and must set token allowances |
| POLY_PROXY | 1 | Yes — your proxy address | Existing Polymarket proxy flow (Magic Link email / Google login) |
| GNOSIS_SAFE | 2 | Yes — your Safe address | Existing Gnosis Safe flow |
| POLY_1271 | 3 | Yes — your deposit wallet | Deposit-wallet flow for new API users. Validated via ERC-1271 |
The funder address is the actual address holding your funds on Polymarket. When using proxy or deposit wallets, the signing key differs from the funded address.
Python Authentication Setup
from py_clob_client_v2 import ClobClient # V2 package — import is py_clob_client_v2
HOST = "https://clob.polymarket.com"
CHAIN_ID = 137 # Polygon mainnet
# Recommended for new API users — deposit wallet (POLY_1271, signature_type=3):
client = ClobClient(
host=HOST,
chain_id=CHAIN_ID,
key="<your-private-key>",
signature_type=3,
funder="<your-deposit-wallet-address>"
)
# EOA (MetaMask) users (funder is the EOA itself):
client = ClobClient(host=HOST, chain_id=CHAIN_ID, key="<your-private-key>")
# Derive and set API credentials (do this once, then reuse).
# V2 renamed this method: create_or_derive_api_creds() -> create_or_derive_api_key()
client.set_api_creds(client.create_or_derive_api_key())
TypeScript Authentication Setup
import { ClobClient, Side } from "@polymarket/clob-client-v2";
// V2 takes a single options object, uses `chain` (not `chainId`), and a viem signer.
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137, // Polygon — note `chain`, not `chainId`
signer, // viem account (V2 uses viem, not ethers.js)
signatureType: 3, // POLY_1271 deposit wallet (recommended for new users)
funder: "<your-deposit-wallet-address>",
});
// Derive API credentials once, then attach them (V2 method name):
const creds = await client.createOrDeriveApiKey();
client.setApiCreds(creds);
Rust Authentication Setup
// V2 crate: polymarket_client_sdk_v2 (cargo add polymarket_client_sdk_v2 --features clob)
use polymarket_client_sdk_v2::clob::{Client, Config};
use alloy::signers::local::LocalSigner;
use std::str::FromStr;
let private_key = std::env::var("PRIVATE_KEY").expect("Need a private key");
let signer = LocalSigner::from_str(&private_key)?
.with_chain_id(Some(137));
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.authenticate()
.await?;
The V2 Rust client (
rs-clob-client-v2) is the newest of the three SDKs. Check the repository for the current builder API — method names may differ from the example above.
Token Allowances (EOA Users Only)
If you’re using a direct EOA wallet (not a proxy), you must approve the Exchange contracts before trading:
# Approve pUSD and conditional tokens for the V2 Exchange contracts.
# (EOA only — proxy and deposit wallets handle approvals for you.)
# This only needs to be done once per wallet.
# See: https://docs.polymarket.com/v2-migration
Proxy and deposit-wallet users (email/Magic, Gnosis Safe, or POLY_1271) do not need to set allowances — the proxy or deposit contract handles this.
CLOB API Reference
The CLOB API is the core trading interface. It handles prices, order books, and order management.
Public Endpoints (No Auth)
GET /price
Returns the current price for a token.
GET https://clob.polymarket.com/price?token_id=<id>&side=BUY
Parameters:
token_id(required) — The outcome token IDside(required) —BUYorSELL
Example response:
{
"price": "0.567"
}
GET /midpoint
Returns the midpoint between best bid and best ask.
GET https://clob.polymarket.com/midpoint?token_id=<id>
Example response:
{
"mid": "0.5650"
}
GET /book
Returns the full order book for a token.
GET https://clob.polymarket.com/book?token_id=<id>
Response includes bids, asks, and a few trading parameters. The get-book/get-books endpoints return min_order_size, neg_risk, and tick_size inline (added July 2025) — convenient so you don’t need a separate lookup just for a market’s tick size or neg-risk flag. For market context (question text, slug, end date, outcome labels, status) you still use the Gamma API, the new_market WebSocket event, or getClobMarketInfo.
Example response (truncated):
{
"market": "0x...",
"asset_id": "21742633143463906290569050155826241533067272736897614950488156847949938836455",
"bids": [
{"price": "0.56", "size": "1250.00"},
{"price": "0.55", "size": "3400.00"}
],
"asks": [
{"price": "0.57", "size": "800.00"},
{"price": "0.58", "size": "2100.00"}
],
"mid": "0.5650",
"spread": "0.01",
"hash": "0x..."
}
POST /books
Batch endpoint — fetch order books for multiple tokens in one request. It’s a POST (the token list goes in the request body), not a GET. Polymarket also exposes batch POST pricing variants: /prices, /midpoints, /spreads, and last-trade-price endpoints.
from py_clob_client_v2.clob_types import BookParams
books = client.get_order_books([
BookParams(token_id="<token-id-1>"),
BookParams(token_id="<token-id-2>"),
])
Authenticated Endpoints (Trading)
All trading endpoints require L2 authentication headers.
POST /order — Place a Single Order
All orders on Polymarket are limit orders. Market orders are simulated by setting a marketable price against resting liquidity.
Order types:
- GTC (Good Til Cancelled) — Rests on the book until filled or cancelled
- FOK (Fill or Kill) — Must execute immediately and completely, or is rejected entirely
- FAK (Fill and Kill) — Fills whatever is available immediately, cancels the rest
CLOB V2 order struct & fees: The signed order no longer carries
nonce,feeRateBps, ortaker. V2 addstimestamp(in ms — it now provides per-address order uniqueness, replacingnonce),metadata, andbuilder. Fees are no longer embedded in the order — the protocol sets them at match time and the SDK handles the math, so don’t try to setfeeRateBpsyourself. For market buys, the optionaluserUSDCBalancefield lets the SDK compute fee-adjusted fill amounts. If you sign orders manually, the EIP-712 Exchange domain version is now2(the ClobAuth domain stays1) with new V2verifyingContractaddresses.
Place a limit order (Python):
from py_clob_client_v2.clob_types import OrderArgs, OrderType
from py_clob_client_v2.order_builder.constants import BUY
order = OrderArgs(
token_id="<token-id>",
price=0.50, # Price in USDC (0.00 to 1.00)
size=10.0, # Number of shares
side=BUY
)
signed = client.create_order(order)
response = client.post_order(signed, OrderType.GTC)
print(response)
Place a market order (Python):
from py_clob_client_v2.clob_types import MarketOrderArgs, OrderType
from py_clob_client_v2.order_builder.constants import BUY
market_order = MarketOrderArgs(
token_id="<token-id>",
amount=25.0, # Dollar amount to spend
side=BUY,
order_type=OrderType.FOK
)
signed = client.create_market_order(market_order)
response = client.post_order(signed, OrderType.FOK)
Place a limit order (TypeScript):
const order = await client.createAndPostOrder(
{
tokenID: "<token-id>",
price: 0.50,
size: 10,
side: Side.BUY
},
{
tickSize: "0.01",
negRisk: false // true for neg-risk markets
}
);
Post-only orders:
The postOnly flag ensures your order is added to the book as a maker order. If it would immediately match (cross the spread), it’s rejected instead of executed. This is critical for market-making strategies where you only want to earn the maker rebate.
order = OrderArgs(
token_id="<token-id>",
price=0.48,
size=100.0,
side=BUY
)
signed = client.create_order(order)
# postOnly cannot be combined with FOK or FAK
response = client.post_order(signed, OrderType.GTC, post_only=True)
Example response:
{
"orderID": "0xabc123...",
"status": "live",
"transactionsHashes": []
}
Possible status values: live (resting on book), matched (fully filled), delayed (pending matching engine processing).
July 24, 2026 response change: the raw
POST /order/POST /ordersREST response no longer includestransactionHasheson successful FAK/FOK matches — it returnstradeIDsinstead (changelog). The current SDKs resolve hashes for you:py-clob-client-v2polls the returnedtradeIDsand merges a best-efforttransactionsHashesfield into the response (passdefer_exec=Trueto skip that resolution and get the raw response back immediately). Custom REST integrations that depended on inline hashes must poll trades bytradeIDuntil each has a hash or returnsFAILED.
POST /orders — Batch Orders
Place up to 15 orders in a single request. Essential for market makers updating multiple price levels.
orders = []
for price in [0.48, 0.49, 0.50]:
order = OrderArgs(
token_id="<token-id>",
price=price,
size=50.0,
side=BUY
)
orders.append(client.create_order(order))
response = client.post_orders(orders, OrderType.GTC)
The batch limit was increased from 5 to 15 orders per call in 2025.
DELETE /order — Cancel a Single Order
py-clob-client-v2 replaced V1’s cancel(order_id=...) with cancel_order(OrderPayload):
from py_clob_client_v2.clob_types import OrderPayload
response = client.cancel_order(OrderPayload(orderID="<order-id>"))
DELETE /orders — Cancel Multiple Orders
response = client.cancel_orders(["<order-id-1>", "<order-id-2>"])
Capped at 1,000 order IDs per request since June 15, 2026 (changelog) — split larger batches.
DELETE /cancel-all — Cancel All Orders
response = client.cancel_all()
Gamma API Reference
The Gamma API is your market discovery layer. Use it to find markets, get metadata, and understand the structure of events.
Understanding Gamma’s Data Model
Polymarket organizes data hierarchically:
Series (e.g., "US Presidential Election")
└── Event (e.g., "2028 Presidential Election Winner")
└── Market (e.g., "Will Kamala Harris win?")
└── Outcomes (YES / NO, each with a token ID)
Key Endpoints
GET /events — List Events
GET https://gamma-api.polymarket.com/events?closed=false&limit=20
Returns events with their associated markets. Each event can contain multiple markets.
GET /markets — List Markets
GET https://gamma-api.polymarket.com/markets?closed=false&limit=50
Key fields in the response:
question— The human-readable market questionclobTokenIds— Array of token IDs for each outcome (critical for trading)outcomePrices— Current prices as a JSON stringvolume— Total trading volume in USDCliquidity— Current available liquidityendDate— When the market resolvesconditionId— The on-chain condition identifierslug— URL-friendly market identifier
Note (April 9, 2026):
GET /marketsnow defaultsclosed=false, so passingclosed=falseexplicitly is no longer required (though still fine). Passclosed=trueto fetch resolved markets instead.
Keyset (Cursor) Pagination
For large pulls, prefer the keyset endpoints added April 10, 2026: GET /markets/keyset and GET /events/keyset. They use opaque cursor tokens instead of offset:
GET https://gamma-api.polymarket.com/markets/keyset?limit=100&after_cursor=<token>
The response wraps results with a next_cursor:
{ "markets": [ ... ], "next_cursor": "eyJpZCI6..." }
Pass next_cursor back as after_cursor to page forward. The maximum limit is 100 (capped May 14, 2026). The offset-based GET /markets / GET /events still work but will be deprecated, so build new pagination on keyset.
Three behaviours worth knowing before you write the loop (all verified live 2026-08-30):
| Behaviour | What you see |
|---|---|
offset is hard-capped at 2000 on /markets and /events | offset=2001 → HTTP 422 {"type":"validation error","error":"offset too large, use /markets/keyset for deeper pagination"}. It is an error object, not an empty array, so while True: ... if not batch: break loops do not terminate — they spin on truthy garbage. |
offset is rejected on keyset endpoints | HTTP 422 {"type":"validation error","error":"offset is not allowed on keyset endpoints"}. You cannot mix the two schemes. |
| Unknown query parameters are ignored silently | ?cursor=<token> (instead of after_cursor) returns HTTP 200 and page 1 — every time. A while next_cursor: loop becomes an infinite loop re-reading the same 100 rows. There is no warning field in the response. |
limit also clamps to 100 with a 200 status on both the offset and keyset endpoints, so advance your loop by len(batch), never by the limit you asked for.
GET /events/{id} — Get Event Details
GET https://gamma-api.polymarket.com/events/<event-id>
Returns full event details including all child markets.
GET /markets?tag= — Filter by Category
Polymarket tags markets with categories. Common tags: politics, crypto, sports, science, pop-culture.
# Get all sports markets
response = requests.get(
"https://gamma-api.polymarket.com/markets",
params={"tag": "sports", "closed": False}
)
Sports-Specific Endpoints
Polymarket has dedicated sports endpoints for structured sports market data:
GET https://gamma-api.polymarket.com/sports
Data API Reference
The Data API provides user-specific and aggregate analytics data.
Base URL: https://data-api.polymarket.com
Key Endpoints
GET /positions — User Positions
Returns current positions for a wallet address, including token balances and unrealized P&L. As of August 10, 2026, entries can also include grossInitialValue (remaining entry basis including attributed buy fees) and entryFeesUsdc (that fee component) — both optional, so treat an omitted field as unavailable, not zero. A new includeArchived query parameter returns positions in archived-but-active markets, which stay excluded by default (changelog).
GET /activity — User Activity
Returns trade history, deposits, withdrawals. Since August 10, 2026, REDEEM rows are reported per outcome: redeeming both sides of a market returns two rows (one per outcome, the losing side with usdcSize: 0) where a single combined row appeared before — sum usdcSize across a transaction’s rows for the total payout (changelog).
GET /trades — Trade History
Historical trade data for analysis and backtesting.
The Data API is fully public and requires no authentication. You can query any wallet’s positions and activity.
Newer Data API endpoints worth knowing: open interest, top holders, closed positions, total position value, the builder leaderboard / daily volume (both now include builderCode as of May 18, 2026), the trader leaderboard, and an accounting-snapshot ZIP export.
Other Useful Endpoints
A few endpoints that round out an agent’s toolkit:
GET /clob-market-info(getClobMarketInfo) — tick size, min order size, fee details (fd), tokens, and RFQ flag in a single call.GET /fee-rateandGET /tick-size— read those parameters directly.POST /heartbeat— the HeartBeats endpoint for auto-cancel-on-disconnect (see the WebSocket section).DELETE /cancel-market-orders— cancel every open order for one market.GET /server-time— check clock drift before signing (EIP-712 timestamps are drift-sensitive).- Sports (structured):
GET /sportsmetadata, valid sports market types, and team listings.
Bridge API
The Bridge API at https://bridge.polymarket.com handles deposits and withdrawals. It proxies fun.xyz infrastructure for cross-chain bridging.
POST /withdraw
Creates withdrawal (bridge deposit) addresses for moving funds off Polygon to a supported chain. It takes no amount and requires no auth — you call it to get deposit addresses, then send funds to the returned address. The request body uses address (your source Polygon wallet), toChainId (the destination chain ID as a numeric string, e.g. "1" for Ethereum or "8453" for Base), toTokenAddress (the destination token contract address), and recipientAddr:
curl -X POST https://bridge.polymarket.com/withdraw \
-H 'Content-Type: application/json' \
-d '{
"address": "0x...source-polygon-wallet",
"toChainId": "1",
"toTokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"recipientAddr": "0x...destination"
}'
The response returns multi-chain deposit addresses:
{
"address": {
"evm": "0x23566f8b2E82aDfCf01846E54899d110e97AC053",
"svm": "CrvTBvzryYxBHbWu2TiQpcqD5M7Le7iBKzVmEj3f36Jb",
"btc": "bc1q8eau83qffxcj8ht4hsjdza3lha9r3egfqysj3g"
}
}
Companion Bridge endpoints include GET /supported-assets, address-creation POSTs, POST /quote, and transaction-status lookups. Multi-chain support covers EVM, Solana, and Bitcoin. The Bridge general rate limit is 50/10s. Check the Polymarket Changelog for the full list of supported chains and tokens.
WebSocket API
For real-time applications — trading bots, live dashboards, arbitrage systems — the WebSocket API is essential. Polymarket offers four WebSocket channels:
| Channel | Endpoint | Auth | Heartbeat |
|---|---|---|---|
| Market | wss://ws-subscriptions-clob.polymarket.com/ws/market | No | PING every 10s |
| User | wss://ws-subscriptions-clob.polymarket.com/ws/user | Yes | PING every 10s |
| Sports | wss://sports-api.polymarket.com/ws | No | Respond to server ping within 10s |
| RTDS | wss://ws-live-data.polymarket.com | Optional | PING every 5s |
Market Channel (Public)
Orderbook updates, price changes, trade data, and custom events (best_bid_ask, new_market, market_resolved when custom_feature_enabled: true).
import asyncio
import websockets
import json
async def stream_prices():
uri = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
async with websockets.connect(uri) as ws:
await ws.send(json.dumps({
"assets_ids": ["<token-id>"],
"type": "market",
"custom_feature_enabled": True
}))
async def heartbeat():
while True:
await asyncio.sleep(10)
await ws.send("PING")
asyncio.create_task(heartbeat())
async for message in ws:
if message == "PONG":
continue
data = json.loads(message)
print(f"Update: {data}")
asyncio.run(stream_prices())
User Channel (Authenticated)
Real-time order status updates — fills, cancellations, status changes. Requires API key/secret/passphrase in the subscription payload. Subscribes by condition ID (not asset ID).
Sports Channel
Streams live game scores, periods, and status for all active sports events. No subscription message needed — connections receive all active events automatically.
RTDS (Real-Time Data Socket)
Low-latency stream for crypto prices (from Binance and Chainlink sources) and platform comments. Supports topic-based subscriptions with optional filters.
WebSocket connections do not count against REST API rate limits. Using WebSockets instead of polling is the most effective way to avoid 429 errors.
HeartBeats API (January 2026): Polymarket added a dedicated HeartBeats API endpoint for connection health monitoring and automatic order cancellation on disconnect. If your bot holds open orders over a long WebSocket session, wiring this in protects you from stranded orders during transient network drops. See the Polymarket Changelog for the endpoint spec.
Deep dive: For complete channel documentation, subscription formats, orderbook reconstruction, and production reconnection patterns, see the Polymarket WebSocket & Orderbook Guide.
Rate Limits
Polymarket publishes concrete rate limits enforced via Cloudflare throttling. When limits are exceeded, requests are delayed/queued rather than immediately rejected. CLOB trading limits were raised on April 8, 2026 — current values below.
| API | General Limit | Key Read Limits |
|---|---|---|
| CLOB | 9,000 / 10s | /book, /price, /midpoint — 1,500/10s each |
| Gamma | 4,000 / 10s | /markets 300/10s, /events 500/10s, /public-search 350/10s |
| Data | 1,000 / 10s | /trades 200/10s, /positions 150/10s |
| Relayer | — | /submit 25/min |
| General | 15,000 / 10s | Applies across all APIs |
CLOB trading endpoints carry dual burst (per 10s) + sustained (per 10 min) limits:
| Endpoint | Burst (10s) | Sustained (10 min) |
|---|---|---|
POST /order | 5,000 | 120,000 |
DELETE /order | 5,000 | 120,000 |
POST /orders | 2,000 | 21,000 |
DELETE /orders | 2,000 | 15,000 |
DELETE /cancel-all | 250 | 6,000 |
DELETE /cancel-market-orders | 1,500 | 21,000 |
Order and cancel limits were raised on June 1, 2026 (POST /order sustained went from 48,000 to 120,000 per 10 minutes — changelog). Since June 15, 2026, DELETE /orders also caps each request at 1,000 order IDs — split larger cancellation batches. On top of the Cloudflare limits, CLOB order and cancel requests are metered by separate per-signer token buckets (live since July 24, 2026) — see the Rate Limits Guide for that system.
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.
Basic retry pattern:
import time
import random
def retry_on_429(func, *args, max_retries=3, **kwargs):
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if "429" in str(e) and attempt < max_retries - 1:
delay = 2 ** attempt + random.uniform(0, 1)
time.sleep(delay)
else:
raise
If you’re hitting rate limits frequently:
- Use WebSockets instead of polling for real-time data
- Batch order operations —
POST /ordershandles up to 15 orders in one request - Cache Gamma API responses — market metadata changes infrequently
- Apply for the Market Maker program for elevated limits
Full rate limits reference: See our Polymarket Rate Limits Guide for complete header documentation, retry code in Python and TypeScript, and strategies for staying within limits.
Key Concepts for Agent Builders
Finding Token IDs
Every market outcome has a unique token ID. This is the primary identifier you’ll use for all trading operations. You get token IDs from the Gamma API:
response = requests.get(
"https://gamma-api.polymarket.com/markets",
params={"slug": "will-bitcoin-hit-100k-by-2026"}
)
market = response.json()[0]
token_ids = market["clobTokenIds"] # [YES_token_id, NO_token_id]
Understanding Neg-Risk Markets
Some Polymarket markets use a “negative risk” model where multiple outcomes share a single collateral pool. This is common in multi-outcome markets (e.g., “Who will win the election?” with 5+ candidates). When trading neg-risk markets, you need to set negRisk: true in your order parameters.
Common gotcha: Forgetting
negRisk: trueon neg-risk markets causes three distinct failures: (1) your order is rejected with a cryptic error because the Exchange contract doesn’t match, (2) split/merge operations fail because the CTF framework routes to the wrong contract, and (3) fee calculations are wrong because neg-risk markets use a different fee structure. Always check the market’sneg_riskfield from the Gamma API before placing orders.
To check programmatically:
market = requests.get(
"https://gamma-api.polymarket.com/markets",
params={"slug": "your-market-slug"}
).json()[0]
is_neg_risk = market.get("negRisk", False)
# Pass this to your order builder
Inventory Management: Split and Merge
The Conditional Token Framework allows you to:
- Split USDC into YES + NO token pairs
- Merge YES + NO tokens back into USDC
- Redeem winning tokens after market resolution
This is essential for market makers managing inventory across both sides of a market.
# Splitting: 1 USDC → 1 YES token + 1 NO token
# Merging: 1 YES token + 1 NO token → 1 USDC
# Redeem: 1 winning token → 1 USDC (after resolution)
Fees
Polymarket fees are applied symmetrically on output assets (proceeds), and in CLOB V2 they are not embedded in your signed order — the protocol computes them at match time. The per-trade fee follows:
fee = C × feeRate × p × (1 − p)
where C is the number of shares and p is the share price. Since p × (1 − p) peaks at p = 0.5, the maximum effective rate for a category is feeRate × 0.25.
Maker fees: 0% on all markets — limit orders that add liquidity are free.
Taker fees: Set per category by
feeRate(in effect since March 30, 2026). Peak rates (at p = 0.5):Category feeRatePeak rate Crypto 0.07 1.75% Economics / Culture / Weather / Other 0.05 1.25% Finance / Politics / Tech / Mentions 0.04 1.00% Sports 0.05 1.25% Geopolitics 0 fee-free The sports
feeRaterose from 0.03 to 0.05 on July 10, 2026, and the sports maker rebate dropped from 25% to 15% of collected taker fees (changelog; current table at Fees).Maker rebates: Calculated per-market — makers compete with other makers in the same market for rebates funded by taker fees. As of March 17, 2026, orders must remain on the book for a minimum of 3.5 seconds of active time to qualify for liquidity rewards. Takers can also earn a portion of fees back through the tiered Taker Rebate Program.
Gas fees: Minimal on Polygon (fractions of a cent per transaction).
Reading fees programmatically: Call
getClobMarketInfo(conditionID)— it returnsfd = { r: feeRate, e: exponent, to: takerOnly }along with tick size, min order size, and the token IDs. Check the market’sfeesEnabledboolean to know whether a market charges fees at all. (The GammafeeScheduleobject, added March 31, 2026, is also available, butgetClobMarketInfois the canonical V2 source.) Read live values rather than hardcoding the table above — category fees can shift.
Check the Polymarket Changelog for the latest fee schedule and the Builder Program for current maker rebate rates.
Builder Program & Relayer Client
If you’re building a consumer-facing application on top of Polymarket (not just a personal bot), the Builder Program provides higher rate limits, volume-based rewards, and access to the Relayer Client for gasless transactions. The program has tiered levels based on volume contributed.
Builder attribution (CLOB V2): Order attribution no longer uses HMAC-signed POLY_BUILDER_* headers (the separate builder-signing SDK is gone). Instead, copy your public builderCode (a bytes32 identifier) from Settings → Builder and attach it to each order via the builderCode field (or set it once at client construction). builderCode is a public identifier — it appears on-chain and on the builder leaderboard.
Relayer Client enables gasless order submission — your users don’t need POL for gas fees. Orders are submitted to the Relayer, which sponsors the gas and submits them on-chain. The HMAC builder API key (key/secret/passphrase, from onboarding at builders.polymarket.com) is still used to authenticate with the Relayer — only per-order attribution moved to builderCode.
Relayer API Key vs Builder API Key — Which One Do You Need?
The Builder API key is not the only way into the Relayer, and most solo agent operators need the other one. The Relayer at https://relayer-v2.polymarket.com accepts either credential:
- Relayer API key — a Signer Address plus an API Key, created at polymarket.com → Settings → API Keys → Relayer API Keys (creation itself requires Gamma auth). Send it as the
RELAYER_API_KEYandRELAYER_API_KEY_ADDRESSheaders, where the address must match the key owner.GET /relayer/api/keyslists the keys held by the authenticated address. This is the credential for gasless operations on your own wallet. - Builder API key — key, secret, and passphrase from Builder Program onboarding. Required when you create accounts for, and submit transactions on behalf of, other users’ wallets.
Two practical consequences:
- You can skip the tier upgrade. Daily Relayer transactions are capped by builder tier — 100/day Unverified, 10,000/day Verified, unlimited for Partner. If you are not routing orders for other users’ wallets, a Relayer API key gives you unlimited daily Relay transactions without applying for a higher tier. (The
/submitcap of 25 req/min still applies — see the rate limits guide.) - Self-custody EOAs need no Relayer key at all. The Relayer sponsors gas for Polymarket’s managed wallet types — Deposit Wallet (default for accounts created May 4, 2026 onward), Proxy Wallet (legacy Magic Link/Google), and Safe Wallet (legacy external signer). From an allowlisted EOA, every onchain action — token approvals, ERC-20 transfers, splits, merges, redemptions — is submitted directly from the EOA and requires POL for gas. You trade the relay cap for a gas bill.
See POLY_1271 smart-contract wallets for how deposit wallets sign the requests the Relayer submits.
SDK packages (unchanged in V2):
| Language | Package | Install |
|---|---|---|
| Python | py-builder-relayer-client | pip install py-builder-relayer-client |
| TypeScript | @polymarket/builder-relayer-client | npm install @polymarket/builder-relayer-client |
Python setup:
from py_builder_relayer_client import BuilderRelayerClient
relayer = BuilderRelayerClient(
key="<your-builder-api-key>",
secret="<your-builder-api-secret>",
passphrase="<your-builder-passphrase>",
)
# As of April 21, 2026, POST /submit returns immediately with a transaction ID
# and state — transactionHash was removed. Poll GET /transaction for the hash.
submission = relayer.submit_order(signed_order)
# -> { "transactionID": "...", "state": "STATE_NEW" }
tx_id = submission["transactionID"]
See the Builder Program docs for onboarding, tier details, and the full Relayer API reference.
Official SDK Libraries
Looking for a complete method reference? See our py_clob_client Method Reference for every method with parameters, return types, and working code examples.
Polymarket maintains official CLOB V2 client libraries. The old V1 packages (py-clob-client, @polymarket/clob-client, polymarket-client-sdk) only work against the retired V1 backend — use the -v2 packages below.
| Language | Package | Repository |
|---|---|---|
| Python | py-clob-client-v2 | github.com/Polymarket/py-clob-client-v2 |
| TypeScript | @polymarket/clob-client-v2 | github.com/Polymarket/clob-client-v2 |
| Rust | polymarket_client_sdk_v2 | github.com/Polymarket/rs-clob-client-v2 |
The TypeScript V2 client uses viem for signing (not ethers.js) — install it alongside. Polymarket’s long-signaled unified SDK has now shipped in beta: py-sdk (PyPI polymarket-client) and ts-sdk (npm @polymarket/client) each fold Gamma + Data + CLOB into one package. Both are pre-1.0 and currently carry open bugs — including a POLY_1271 deposit-wallet auth failure — so the -v2 CLOB clients above remain the stable path for production today. See Polymarket Beta SDK Bugs (May 2026).
Community alternative: The polymarket-apis package is a third-party unified wrapper around CLOB, Gamma, Data, Web3, WebSocket, and GraphQL clients with Pydantic validation. Check its current version and confirm CLOB V2 compatibility before relying on it for trading — community wrappers can lag the official V2 packages. Install with pip install polymarket-apis.
Install
# Python
pip install py-clob-client-v2
# TypeScript (viem is a peer dependency in V2)
npm install @polymarket/clob-client-v2 viem
# Rust
cargo add polymarket_client_sdk_v2 --features clob
Version note: Always install the latest
-v2packages — the V1 packages and V1-signed orders no longer work on production. If you hit a breaking change, let us know on Twitter.
Putting It Together: A Minimal Trading Agent
Here’s a complete Python example that finds a market, checks the price, and places an order:
import requests
from py_clob_client_v2 import ClobClient
from py_clob_client_v2.clob_types import OrderArgs, OrderType
from py_clob_client_v2.order_builder.constants import BUY
# 1. Initialize authenticated client (POLY_1271 deposit wallet, signature_type=3 — recommended for new users)
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key="<your-private-key>",
signature_type=3,
funder="<your-deposit-wallet-address>"
)
client.set_api_creds(client.create_or_derive_api_key())
# 2. Discover a market via the Gamma API
markets = requests.get(
"https://gamma-api.polymarket.com/markets",
params={"closed": False, "limit": 5, "order": "volume", "ascending": False}
).json()
target = markets[0]
token_id = target["clobTokenIds"][0] # YES token
print(f"Market: {target['question']}")
print(f"Current price: {target['outcomePrices']}")
# 3. Check the order book
book = client.get_order_book(token_id)
best_ask = float(book["asks"][0]["price"]) if book["asks"] else None
print(f"Best ask: {best_ask}")
# 4. Place a limit order below the current ask
if best_ask and best_ask > 0.05:
my_price = round(best_ask - 0.02, 2)
order = OrderArgs(
token_id=token_id,
price=my_price,
size=10.0,
side=BUY
)
signed = client.create_order(order)
result = client.post_order(signed, OrderType.GTC)
print(f"Order placed: {result}")
Common Patterns
Pattern 1: Price Monitoring Bot
Poll prices at an interval and trigger actions on threshold changes.
import time
def monitor_market(token_id, threshold_low, threshold_high):
while True:
mid = client.get_midpoint(token_id)
price = float(mid)
if price < threshold_low:
print(f"ALERT: Price dropped to {price} — buying opportunity")
# Place buy order logic here
if price > threshold_high:
print(f"ALERT: Price rose to {price} — selling opportunity")
# Place sell order logic here
time.sleep(5) # Check every 5 seconds
Pattern 2: Cross-Market Arbitrage Scanner
Check if YES + NO prices deviate from $1.00 across markets.
def scan_arb_opportunities():
markets = requests.get(
"https://gamma-api.polymarket.com/markets",
params={"closed": False, "limit": 100}
).json()
for market in markets:
prices = market.get("outcomePrices")
if prices:
try:
parsed = [float(p) for p in prices.strip("[]").split(",")]
total = sum(parsed)
if total < 0.98 or total > 1.02:
print(f"ARB: {market['question']}")
print(f" Prices sum to: {total:.4f}")
print(f" Gap: {abs(1.0 - total):.4f}")
except (ValueError, IndexError):
continue
For agents scanning beyond prediction markets, the same arbitrage logic applies to sportsbook lines. Offshore sportsbooks like BetOnline and Bovada frequently price sports events differently from Polymarket — and the API access patterns differ significantly. See the Sports Betting Arbitrage Bot Guide for a full cross-platform implementation, and Offshore vs. Regulated Sportsbooks for a comparison of data access across both worlds.
Pattern 3: WebSocket + LLM Agent
Stream market updates and feed them to an LLM for analysis.
import asyncio
import websockets
import json
async def agent_loop():
uri = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
async with websockets.connect(uri) as ws:
# Subscribe to all watched markets in the initial message
await ws.send(json.dumps({
"assets_ids": watched_tokens, # list of token IDs
"type": "market"
}))
# To add/drop tokens later, send an operation message:
# await ws.send(json.dumps({"operation": "subscribe", "assets_ids": ["<id>"]}))
async for message in ws:
if message == "PONG":
continue
data = json.loads(message)
# Feed price update to your LLM/agent for analysis
# agent.analyze(data)
# If the agent recommends a trade, execute via CLOB API
Security Considerations
Building autonomous agents that handle real money demands careful security practices. See our Security Best Practices for Agent Betting guide for the full treatment. Key points:
- Never hardcode private keys — use environment variables or a secrets manager
- Use spending limits — configure your wallet with maximum position sizes
- Implement kill switches — your bot should have a way to cancel all orders and stop trading instantly
- Guard against prompt injection — if using LLMs, sanitize all market data before feeding it to the model
- Test on small amounts first — Polymarket has no demo/testnet environment, so start with minimal positions
- Monitor the heartbeat — the Rust SDK supports automatic heartbeats that cancel all orders if your client disconnects
Troubleshooting
For an in-depth breakdown of the 10 most common integration failures — including L1/L2 auth confusion, wallet type mismatches, identifier confusion, heartbeat timeouts, and US NO-side pricing — see the top 10 Polymarket API problems guide.
Order Rejected Errors
The CLOB matching engine rejects orders that violate market constraints. Common causes:
- Check that your price aligns with the market’s tick size (usually 0.01, but finer ticks exist — World Cup markets moved to 0.0025 on July 2, 2026, and the SDK’s
TickSizetype goes down to 0.0001 — check the/bookresponse for themin_tick_sizefield) - Ensure you have sufficient pUSD balance on Polygon (CLOB V2 collateral; wrap USDC.e via the Collateral Onramp)
- For EOA wallets, verify token allowances are set for both the Exchange and Neg Risk Exchange contracts
- If using
postOnly, your order may be crossing the spread — lower your bid or raise your ask - Orders with
sizebelow the market minimum (typically 1.0 shares) are silently rejected
Authentication Failures (401 / INVALID_SIGNATURE)
Auth errors almost always come down to a mismatch between your wallet type and the signature parameters you’re sending.
- Verify your
signature_typematches your wallet type:0for EOA,1for email/Magic proxy,2for Gnosis Safe,3for POLY_1271 deposit wallets (recommended for new API users) - Ensure the
funderaddress is correct for proxy wallets — this is the address holding funds, not the signing key address - API credentials may need to be re-derived if you get persistent 401 errors — call
client.create_or_derive_api_key()again - Check for clock drift — EIP-712 signatures include a timestamp, and a drift of more than 60 seconds causes rejection
- See the full Polymarket Auth Troubleshooting Guide for error code reference
Rate Limit Errors (429)
When you hit rate limits, Polymarket’s Cloudflare layer queues your requests rather than immediately rejecting them — but sustained overuse will eventually return 429s.
- Switch from polling to WebSockets for real-time data — WebSocket connections do not count against REST rate limits
- Batch order operations using the
POST /ordersendpoint (up to 15 orders per call) - Cache Gamma API responses — market metadata (questions, token IDs, slugs) changes infrequently
- Check
X-RateLimit-Remainingheaders before making bursts of requests - See the Polymarket Rate Limits Guide for the full per-endpoint breakdown
Missing or Wrong Token IDs
Token ID confusion is the single most common issue for new Polymarket developers.
- Token IDs come from the Gamma API, not the CLOB API — use the
clobTokenIdsfield fromGET /markets clobTokenIdsis an array: index 0 is typically YES, index 1 is NO, but always verify againstoutcomes- Some multi-outcome (neg-risk) markets have their token IDs in a nested structure within the event response
- Token IDs are long numeric strings (not hex addresses) — e.g.,
21742633143463906290569050155826241533067272736897614950488156847949938836455 - If a token ID returns empty order books, the market may have been resolved or delisted — check
closedstatus via Gamma
What’s New in Official Docs
Polymarket’s official documentation has expanded significantly. Key areas now covered:
- CLOB V2 (April 28, 2026) — A hard-cutover upgrade of the entire trading stack: new Exchange contracts, V2 SDK packages, a new order struct, protocol-set fees, and pUSD collateral. V1 SDKs and V1-signed orders no longer work — see Migrating to CLOB V2
- pUSD collateral — Collateral migrated from USDC.e to pUSD (an ERC-20 backed 1:1 by USDC); API-only traders wrap via the Collateral Onramp
- Deposit wallets / POLY_1271 (type 3) — A new signature type now recommended for new API users
- Rate-limit increases (April 8 + June 1, 2026) — CLOB trading burst/sustained limits raised twice;
POST /ordernow allows 5,000/10s burst + 120,000/10min sustained, with per-signer token buckets layered on top since July 24 - Order response change (July 24, 2026) —
POST /order/POST /ordersreturntradeIDsinstead oftransactionHasheson successful FAK/FOK matches; current SDKs resolve hashes fromtradeIDs - Sports fee increase (July 10, 2026) — sports
feeRate0.03 → 0.05 (peak 1.25%); sports maker rebate 25% → 15% - Chainlink TWAP resolution (August 2026) — crypto up/down markets now resolve on Chainlink time-weighted average prices (60-second window for 5-minute markets since Aug 14) instead of a single price snapshot; the crypto taker delay dropped to 50ms on Aug 17
- Data API additions (August 10, 2026) — per-outcome
REDEEMactivity rows, optionalgrossInitialValue/entryFeesUsdcposition fields, and anincludeArchivedpositions filter - Keyset pagination (April 10, 2026) —
GET /markets/keyset&/events/keysetwith cursor tokens; maxlimitcapped at 100 (May 14, 2026) - Relayer
/submitchange (April 21, 2026) — Returns{ transactionID, state }immediately; pollGET /transactionfor the on-chain hash builderCodeattribution (May 18, 2026) — Per-order builder attribution via a publicbuilderCode, now shown on the builder leaderboardGET /marketsdefault changed (April 2026) — Theclosedquery parameter now defaults tofalse, so most market discovery calls no longer need to pass it explicitly- Programmatic fees — Read per-market fees via
getClobMarketInfo()(canonical V2 source) or the GammafeeScheduleobject; check thefeesEnabledflag - Liquidity reward floor (March 2026) — Orders must sit on the book for at least 3.5 seconds to count toward liquidity rewards
- Multi-chain withdrawals (January 2026) —
POST /withdrawnow supports Solana and Bitcoin destinations in addition to EVM chains - Fees and maker rebates — Per-market fee tiers, taker fees on crypto/sports markets, and per-market rebate calculation
- CTF operations — Split, merge, and redeem operations for conditional tokens
- Bridge flows — Deposit and withdrawal documentation via the Bridge API, including the new
/withdrawendpoint for cross-chain bridging - Resolution process — How markets resolve via the UMA oracle
- Market Maker program — Setup, trading requirements, liquidity rewards, and data feeds
- Builder Program — Tiers, profile setup, API keys, order attribution, and relayer client
- Order book parameters —
get-book/get-booksreturnmin_order_size,neg_risk, andtick_sizeinline (not full market metadata — use Gamma orgetClobMarketInfofor question/slug/dates) - Subscription limits removed — The 100-token subscription limit on the Markets WebSocket channel has been removed; you can subscribe to unlimited token IDs
- Agent Skills — Polymarket published agent-skills on GitHub, a structured skill pack for AI agents covering auth, orders, WebSocket, CTF, bridge, and gasless transactions
AgentBets guides complement these official docs by providing implementation depth, cross-platform context, and agent-first patterns.
Changelog
| Date | Change |
|---|---|
| September 2, 2026 | Re-verified all endpoints, rate limits, and fee tables against the live API — no changes. |
| August 24, 2026 | Updated rate limits to the June 1 raise (POST /order sustained 120,000/10min) and noted the 1,000-ID cap on DELETE /orders (Jun 15) and per-signer token buckets (Jul 24). Corrected sports taker fee to 0.05 / 1.25% peak and 15% maker rebate (Jul 10). Documented the July 24 tradeIDs order-response change, fixed V2 cancel methods (cancel_order(OrderPayload), cancel_orders, cancel_all endpoint mapping — verified against py-clob-client-v2 v1.1.0), added August Data API fields and Chainlink TWAP resolution notes. |
| May 25, 2026 | Major rewrite for CLOB V2 (live Apr 28, 2026). Migrated SDK examples to the -v2 packages; rewrote authentication for the four signature types (incl. POLY_1271 deposit wallets); switched collateral to pUSD; documented the new order struct, protocol-set fees, and builderCode attribution; corrected fee percentages (Crypto 1.75%, Economics 1.25%, Mentions 1.00%); updated rate limits (POST /order 5,000/10s + 48,000/10min, Apr 8); added keyset pagination; fixed the Bridge /withdraw body and the Pattern 3 WebSocket snippet; corrected positions/balance guidance. |
| April 9, 2026 | Verified against official Polymarket docs. Noted GET /markets now defaults to closed=false (as of today). Documented feeSchedule object (Mar 31), 3.5s liquidity-reward floor (Mar 17), multi-chain Bridge /withdraw for Solana/Bitcoin (Jan 28), and HeartBeats API (Jan 6). |
| March 23, 2026 | Updated fee structure with per-market taker fees (crypto, sports). Added /withdraw endpoint. Expanded Builder Program with Relayer Client docs. Added agent-skills repo. Added polymarket-apis community package. Updated signature_type=2 as default. Documented get-book metadata enrichment. |
| March 2026 | Updated rate limits table with concrete per-endpoint figures. Added Rust SDK setup and examples. Added WebSocket sports channel and RTDS documentation. Expanded neg-risk market guidance. |
| February 2026 | Initial publication. Covers CLOB, Gamma, Data, and Bridge APIs. Python and TypeScript SDK examples. Authentication setup for all wallet types. |
Official Resources
- Polymarket Documentation
- Polymarket Changelog
- Polymarket Agent Skills — Structured skill pack for AI agents
- Python SDK (py-clob-client-v2)
- TypeScript SDK (clob-client-v2)
- Rust SDK (rs-clob-client-v2)
- Builder Relayer Client (Python)
- Builder Relayer Client (TypeScript)
- polymarket-apis (Community) — Unified third-party wrapper
- Polymarket Agents Framework — Official AI agent toolkit
- Discord Community
AgentBets Guides
- Build a Polymarket Trading Bot — From market scanning to production deployment
- Dome vs pmxt vs OddsPapi — Unified prediction market API comparison
- Polymarket WebSocket & Orderbook Guide — All four channels, orderbook reconstruction
- Polymarket Auth Troubleshooting — POLY headers, signatureType, error reference
- Polymarket TypeScript SDK Reference — @polymarket/clob-client methods with examples
- Polymarket Rust SDK Reference — Cargo setup, methods, and error handling
- Polymarket Gamma API Deep Dive — Market discovery, price history, backtesting
- Polymarket Subgraph Guide — On-chain data via GraphQL
- Polymarket US vs. Global API — Dual-stack architecture comparison
- Offshore Sportsbook API Guide — Data access for BetOnline, Bovada, and more
- Sports Betting vs Prediction Markets — When to use each
Frequently Asked Questions
How do I check my balance with py_clob_client?
Use client.get_balance_allowance() to get your pUSD balance plus token allowance info. (CLOB V2 migrated collateral from USDC.e to pUSD.) See our complete method reference for full examples with response structures.
What are Polymarket’s API rate limits?
Polymarket publishes concrete rate limits enforced via Cloudflare throttling. The general limit is 15,000 requests per 10 seconds, with specific limits per endpoint (e.g., POST /order allows 5,000/10s burst and 120,000/10min sustained, raised June 1, 2026), plus per-signer token buckets on order and cancel requests. See our Rate Limits Guide for the full per-endpoint table and retry code.
How do I get my positions using py_clob_client?
Positions come from the Data API, not the CLOB client — query GET data-api.polymarket.com/positions for any wallet address. py-clob-client-v2 exposes balance and allowance via get_balance_allowance(), but position tracking is a Data API job. See the py_clob_client Reference for the client’s balance/allowance methods.
What is MarketOrderArgs in py_clob_client?
MarketOrderArgs is the data class used to specify market orders (fill-or-kill). It takes token_id, amount (in USDC), side, and order_type. Use it with client.create_market_order(). See the MarketOrderArgs reference for the full field reference and examples.
Is there a Polymarket API for the US?
Yes, but it is a separate stack. The global API is geoblocked for US trading. Polymarket US — the CFTC-regulated exchange at api.polymarket.us — is the compliant path for US users: Ed25519 key authentication instead of EIP-712, mandatory KYC, and its own SDKs. Read-only endpoints on the global Gamma and Data APIs work from anywhere. See the Polymarket US vs. Global API Guide for the full comparison.
Where This Fits in the Agent Betting Stack
This guide covers Layer 3 (Trading) of the Agent Betting Stack. Polymarket’s API is the execution layer — where your agent converts intelligence into positions.
To build a complete autonomous agent, you also need:
- Layer 1 — Identity: Register and verify your agent (Moltbook Identity Guide)
- Layer 2 — Wallet: Hold and manage funds autonomously (Wallet Comparison Guide)
- Layer 4 — Intelligence: Agent Intelligence Guide — LLM analysis, sentiment, and strategy
- Arbitrage: Cross-Market Arbitrage Guide — Arb across Polymarket, Kalshi, and sportsbooks
This guide is maintained by AgentBets.ai. Found an error or API change we missed? Let us know on Twitter.
Not financial advice. Built for builders.
