
Polymarket API: Endpoints, API Keys and Trading Guide
Learn the Gamma, CLOB and Data API endpoints and how to get a Polymarket API key. Place orders in Python and read positions on Polygon.
The Polymarket API has three public HTTP services and a WebSocket feed. The Gamma API lists markets. The CLOB API serves prices and order books and takes orders. The Data API returns a wallet's positions and activity. Trades settle on Polygon, so you read balances and resolutions through a Polygon RPC endpoint.
You need no API key to read markets or prices. To trade on polymarket.com, you derive a CLOB API key from your wallet's private key. The section How to get a Polymarket API key shows that step in Python and with raw HTTP. It also covers the Relayer and Builder keys in polymarket.com Settings, and the separate keys from the Polymarket US developer portal.
Each section below has a working call. We checked the public reads against the live APIs. The trading calls use the official py-clob-client-v2 SDK.
Note: Polymarket shipped CLOB V2 on April 28, 2026. Collateral moved to pUSD and order signing changed. Polymarket also retired the legacy py-clob-client. This guide uses py-clob-client-v2 (import name py_clob_client_v2). Polymarket now recommends its unified SDK, polymarket-client, for new projects. It wraps every API in one package and has a migration guide from the older clients. The py-clob-client-v2 calls below still work. Pin your versions.
What you will learn
- Which Polymarket API endpoint to call for markets, prices, trading, positions and on-chain data
- How to get a Polymarket API key for trading, and which keys you don't need
- How to find markets and outcome token IDs with the Gamma API
- How to read live prices and order books from the CLOB API
- How to place and cancel orders, stream book and fill updates over WebSocket, and read positions on Polygon
Prerequisites
- Python 3.11+ (
python3 --version) - A Polygon RPC endpoint for on-chain reads. Get a free Polygon key from the Dwellir dashboard. The code reads it from
DWELLIR_POLYGON_URL. - For trading only: a Polygon wallet funded with pUSD and its private key.
pip install "py-clob-client-v2" web3 requests websocket-clientPolymarket API endpoints and docs
An integration uses four endpoints:
| API | Base URL | Auth | Use it for |
|---|---|---|---|
| Gamma API | https://gamma-api.polymarket.com | None | Find markets and events, get outcome token IDs |
| CLOB API | https://clob.polymarket.com | Public reads, API key to trade | Prices, order books, placing and cancelling orders |
| Data API | https://data-api.polymarket.com | None | A wallet's positions, activity and trades |
| Polygon RPC | your endpoint | Your key | Outcome-token and pUSD balances, settlement events |
Order matching happens off-chain on the CLOB. Settlement happens on Polygon. Because of this split, a production integration pairs the CLOB with a Polygon RPC endpoint.
Two small public endpoints are useful for health checks. GET https://clob.polymarket.com/time returns the CLOB server time as a Unix timestamp. GET https://polymarket.com/api/geoblock returns {"blocked": false, "country": ...} for the calling IP. Check it before you send orders from a new server region.
The official reference is at docs.polymarket.com. Polymarket US has separate docs at docs.polymarket.us.

The image shows the four endpoints your app uses:
- The Gamma API returns markets and outcome-token IDs. It needs no key.
- The CLOB API returns prices and order books and takes orders. Trading needs a key.
- The Data API returns a wallet's positions, activity and trades. It needs no key.
- A Polygon RPC endpoint (Dwellir) returns outcome-token and pUSD balances and settlement events. It needs your key.
The CLOB matches orders off-chain. Settlement happens on-chain on Polygon.
Find markets with the Gamma API
Every integration starts with a market and its outcome token IDs. The Gamma API lists markets and events and needs no auth.
# gamma.py
import json
import requests
GAMMA = "https://gamma-api.polymarket.com"
def active_markets(limit: int = 20) -> list[dict]:
resp = requests.get(
f"{GAMMA}/markets",
params={"active": "true", "closed": "false", "limit": limit},
timeout=10,
)
resp.raise_for_status()
return resp.json()
m = active_markets(1)[0]
print(m["question"])
print("conditionId:", m["conditionId"])
print("outcomes:", json.loads(m["outcomes"]))
print("token ids:", json.loads(m["clobTokenIds"]))Xi Jinping out before 2027?
conditionId: 0xa467b14d...
outcomes: ['Yes', 'No']
token ids: ['32338220190071351435...', '25659310674993675562...']clobTokenIds is a JSON-encoded string that holds two ERC-1155 token IDs, one per outcome. Every CLOB call expects one of these as token_id. To resolve a token ID back to its market, query ?clob_token_ids=<id>.
Read prices and the order book from the CLOB API
The CLOB serves prices and order books publicly. Pass a token ID from Gamma.
# clob_reads.py
import requests
CLOB = "https://clob.polymarket.com"
def order_book(token_id: str) -> dict:
return requests.get(f"{CLOB}/book", params={"token_id": token_id}, timeout=10).json()
def midpoint(token_id: str) -> float:
return float(requests.get(f"{CLOB}/midpoint", params={"token_id": token_id}, timeout=10).json()["mid"])
book = order_book("32338220190071351435...")
print("best bid:", book["bids"][-1], "best ask:", book["asks"][-1])
print("tick size:", book["tick_size"], "neg_risk:", book["neg_risk"])
print("midpoint:", midpoint("32338220190071351435..."))best bid: {'price': '0.026', 'size': '3908.99'} best ask: {'price': '0.027', 'size': '23288.44'}
tick size: 0.001 neg_risk: False
midpoint: 0.0265The book includes tick_size and neg_risk. You need both when you place an order. Tick size varies by market. This market trades in steps of 0.001. Many others trade in steps of 0.01. The /price?token_id=...&side=buy and /spread endpoints return single values without the full book.
How to get a Polymarket API key
Which key you need depends on what you build:
| Key | Where you get it | Needed for |
|---|---|---|
| None | - | Gamma, Data API, CLOB prices and books, market WebSocket |
| CLOB API credentials (key, secret, passphrase) | Derived from your wallet's private key | Placing, cancelling and listing your orders, and the user WebSocket channel |
| Relayer API key | polymarket.com → Settings → API Keys → Relayer API Keys | Gasless wallet operations for a polymarket.com account |
| Builder API key | polymarket.com → Settings → Builders | Creating Deposit Wallets for your own users |
| Polymarket US Key ID and Secret Key | polymarket.us/developer after KYC | The separate Polymarket US exchange only |
Most bots and scripts need only the CLOB credentials. You do not fill in a form to get them. The CLOB uses two auth levels. L1 is your wallet's private key. You use it once to sign a message that proves you own the address. L2 is the API key, secret and passphrase that the CLOB returns for that signature. You send them on every trading request.
Get the key with the Python SDK
# client.py
import os
from py_clob_client_v2 import ClobClient
HOST = "https://clob.polymarket.com"
def make_client() -> ClobClient:
# L1: the private key proves wallet ownership
l1 = ClobClient(host=HOST, chain_id=137, key=os.environ["PRIVATE_KEY"])
creds = l1.create_or_derive_api_key() # ApiCreds(api_key, api_secret, api_passphrase)
# L2: the same client with credentials attached can trade
return ClobClient(host=HOST, chain_id=137, key=os.environ["PRIVATE_KEY"], creds=creds)create_or_derive_api_key() creates credentials on the first call. On later calls, it derives the same credentials again from the same key and nonce. You don't need to store them. Store them anyway if you want to skip the extra signing call at startup.
If you trade from a polymarket.com account instead of a bare wallet, pass two more arguments to ClobClient:
funder, the account wallet address from your profile menu.signature_type, the value for the account's wallet type:1for a Proxy wallet,2for a Safe wallet. A bare wallet uses0, the default.
Accounts created on or after May 4, 2026 use a Deposit Wallet. Older accounts use a Proxy or Safe wallet. For a Deposit Wallet, Polymarket's wallets and authentication docs use the unified SDK's SecureClient.
Get the key with raw HTTP
Without the SDK, sign the ClobAuth EIP-712 message (domain ClobAuthDomain, version 1, chain ID 137) with your wallet. Then send the signature to the CLOB:
# create a new key
curl -X POST "https://clob.polymarket.com/auth/api-key" \
-H "POLY_ADDRESS: <signer_address>" \
-H "POLY_SIGNATURE: <clob_l1_signature>" \
-H "POLY_TIMESTAMP: <unix_seconds>" \
-H "POLY_NONCE: <nonce>"
# or derive the existing one
curl "https://clob.polymarket.com/auth/derive-api-key" -H "POLY_ADDRESS: ..." # same headersBoth return {"apiKey": "...", "secret": "...", "passphrase": "..."}. Keep the secret and passphrase on your server.
Polymarket US developer portal
Polymarket US is a separate, CFTC-regulated exchange with its own markets, accounts and API. To get a key, create an account in the Polymarket US app and pass identity verification. Then sign in at polymarket.us/developer with the same login method and create a key. You get a Key ID and a Secret Key. The portal shows the secret only once. Each request carries an Ed25519 signature in the X-PM-Access-Key, X-PM-Timestamp and X-PM-Signature headers. The polymarket-us SDK (pip install polymarket-us) does the signing for you.
These keys do not work on the polymarket.com CLOB. Nothing on Polymarket US settles on Polygon. The rest of this guide covers the international polymarket.com API.
Place and cancel orders
With an L2 client, build an order from a token ID, price, size and side. The order must use the market's tick size and neg-risk flag. If you pass None, the SDK gets both values from the CLOB. If you pass a tick size larger than the market's, the SDK accepts it and rounds the price to it. A tick size of "0.01" on a 0.001-tick market sends a 0.026 bid as 0.03.
# orders.py
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions, Side
from py_clob_client_v2.clob_types import OrderPayload
def place_limit(client, token_id, price, size, tick_size=None, neg_risk=None):
# None makes the SDK get the market's tick size and neg-risk flag from the CLOB
return client.create_and_post_order(
order_args=OrderArgs(token_id=token_id, price=price, size=size, side=Side.BUY),
options=PartialCreateOrderOptions(tick_size=tick_size, neg_risk=neg_risk),
order_type=OrderType.GTC, # rest on the book until filled or cancelled
)
def cancel(client, order_id):
return client.cancel_order(OrderPayload(orderID=order_id))The CLOB accepts four order types:
GTCrests on the book until it fills or you cancel it.GTDexpires at a timestamp.FOKandFAKfill immediately and cancel any remainder. Use them for market-style orders.
Read open orders with client.get_open_orders(). Read your fills with client.get_trades().
Note: Orders settle in pUSD. Before your first trade, approve the CTF Exchange (0xE111180000d2663C0091e4f400237545B87B996B) to spend pUSD, and call setApprovalForAll on the Conditional Tokens contract (0x4D97DCd97eC945f40cF65F87097ACe5EA0476045). If you hold bridged USDC.e, wrap it into pUSD through Polymarket's collateral onramp first.
Stream updates with the Polymarket WebSocket API
For live data, the CLOB WebSocket pushes book and trade updates. The market channel is public. The user channel needs your CLOB API credentials and reports your own fills.
# stream.py
import json, websocket
WS = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
def stream_book(token_ids: list[str]):
ws = websocket.create_connection(WS)
ws.send(json.dumps({"assets_ids": token_ids, "type": "market"}))
while True:
msg = json.loads(ws.recv())
print(msg.get("event_type"), msg.get("asset_id"))
stream_book(["32338220190071351435..."])Market messages include book snapshots, price_change and last_trade_price. For your own orders, connect to .../ws/user with your API credentials and the condition IDs of the markets you follow. You receive trade and order events. Send a PING about every 10 seconds to keep the socket open.
Read positions and balances on Polygon
There are two ways to read holdings. The Data API gives a decoded view of any wallet's positions. Polygon RPC gives you the raw on-chain state.
# positions.py
import os, requests
from web3 import Web3
DATA = "https://data-api.polymarket.com"
w3 = Web3(Web3.HTTPProvider(os.environ["DWELLIR_POLYGON_URL"]))
PUSD = Web3.to_checksum_address("0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB")
def positions(address: str) -> list[dict]:
return requests.get(f"{DATA}/positions", params={"user": address, "limit": 100}, timeout=10).json()
def pusd_balance(address: str) -> float:
addr = Web3.to_checksum_address(address)
data = "0x70a08231" + addr[2:].rjust(64, "0") # balanceOf(address)
return int(w3.eth.call({"to": PUSD, "data": data}).hex(), 16) / 1_000_000
for p in positions(os.environ["WALLET_ADDRESS"])[:3]:
print(p["title"], p["outcome"], p["size"], "@", p["curPrice"], "redeemable:", p["redeemable"])
print("pUSD:", pusd_balance(os.environ["WALLET_ADDRESS"]))Will ETH close above $4k in June? Yes 120 @ 0.41 redeemable: False
pUSD: 142.50The Data API decodes positions into PnL, current price and redeemable/mergeable flags. Dashboards can use that view. Settlement logic should trust the on-chain read. Call ERC-1155 balanceOf on the Conditional Tokens contract, or pUSD balanceOf as shown, through your Polygon RPC endpoint.
Going to production
Pair the CLOB with Polygon RPC. Prices and orders come from the CLOB, but balances, fills and resolutions are on-chain. Production integrations read both. Your Polygon RPC latency sets how fresh your position and settlement data is.
Manage pUSD and approvals. Check approvals with allowance reads at startup. Wrap USDC.e to pUSD when needed. Redeem resolved positions with redeemPositions so capital does not sit idle.
Plan for rate limits. Implement retry with backoff and treat HTTP 429 as a signal to slow down.
Pin your SDK. V2 changed order signing, so a stale client fails to place orders. Pin py-clob-client-v2 and test order placement with a small size before you scale.
Next steps
- Build on these calls with our guide to a Polymarket copy-trading bot.
- For the basics, read what a prediction market is and how Polymarket works.
- To pick the Polygon endpoint for these calls, see the best Polygon RPC for Polymarket bots.
This guide read and traded against Polygon through a Dwellir endpoint. To run it yourself, create a free Dwellir account and point DWELLIR_POLYGON_URL at your Polygon endpoint.
Frequently Asked Questions
Does Polymarket have an API?
Yes. Polymarket has three public HTTP APIs. The Gamma API (gamma-api.polymarket.com) lists markets and events. The CLOB API (clob.polymarket.com) serves prices and order books and takes orders. The Data API (data-api.polymarket.com) returns wallet positions and activity. Polymarket also runs a WebSocket feed. Settlement and balances are on Polygon.
How do I get a Polymarket API key?
For trading on polymarket.com, you derive CLOB API credentials (key, secret, passphrase) from your wallet's private key. In Python, call create_or_derive_api_key() on a py-clob-client-v2 ClobClient, or POST a signed L1 message to clob.polymarket.com/auth/api-key. You create Relayer and Builder API keys separately in polymarket.com Settings. Reading market data needs no key.
Do I need an API key to read Polymarket prices?
No. The Gamma API, the Data API and the CLOB's price and order book endpoints are public. You only need CLOB credentials to place, cancel or list your own orders.
What is the Polymarket US developer portal?
Polymarket US is a separate CFTC-regulated exchange with its own API. After you create an account in the Polymarket US app and pass identity verification, you create a Key ID and Secret Key at polymarket.us/developer. Those keys do not work on the international polymarket.com CLOB, and polymarket.com credentials do not work on Polymarket US.
Where do Polymarket positions and balances live?
On Polygon. Outcome tokens are ERC-1155 tokens on the Conditional Tokens contract and collateral is pUSD. You read them with balanceOf calls through a Polygon RPC endpoint. The Data API also returns them in decoded form.
How to Find the Wallet Behind a Hyperliquid Order
Turn a Hyperliquid transaction hash or order ID (oid) into the wallet address that placed it. A tested Python script using txDetails, orderStatus, and Dwellir's indexed fills.
Build a Real-Time Robinhood Chain Whale Tracker in Python
Track whale trades on Robinhood Chain in real time. Subscribe to on-chain logs over Dwellir's WebSocket, decode large USDG and Stock Token transfers, and alert instantly.