Build trading bots and applications on Polymarket prediction markets. Use when working with Polymarket APIs, py-clob-client SDK, WebSocket streaming, order placement, market data fetching, whale tracking, or arbitrage detection. Triggers: Polymarket, prediction market, CLOB, trading bot, market making, py-clob-client, Magic.Link wallet, polygon trading.
Build trading applications on Polymarket (Polygon chain, USDC settlement).
Gamma API (market discovery) ─┐
CLOB API (trading/orders) ─┼─→ WebSocket API (real-time)
Data API (positions/trades) ─┘
| API | Endpoint | Purpose |
|---|---|---|
| CLOB | https://clob.polymarket.com | Trading, orders |
| Gamma | https://gamma-api.polymarket.com | Market discovery |
| Data | https://data-api.polymarket.com | Positions, trades |
| WebSocket | wss://ws-subscriptions-clob.polymarket.com | Real-time |
pip install py-clob-client
CRITICAL: Magic.Link Users (Google/Email login)
Magic.Link creates TWO wallets:
from py_clob_client.client import ClobClient
client = ClobClient(
host="https://clob.polymarket.com",
key=SIGNER_PRIVATE_KEY, # From wallet.magic.link export
chain_id=137,
signature_type=1, # MUST be 1 for Magic.Link!
funder=PROXY_WALLET_ADDRESS # Address from Polymarket UI
)
# Create/derive API credentials
creds = client.create_or_derive_api_creds()
client.set_api_creds(creds)
EOA Wallets (MetaMask/hardware)
client = ClobClient(
host="https://clob.polymarket.com",
key=PRIVATE_KEY,
chain_id=137,
signature_type=0 # EOA
)
from py_clob_client.clob_types import OrderArgs, MarketOrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY, SELL
# Limit order
order = client.create_order(OrderArgs(
price=0.50,
size=100, # MINIMUM 5 shares!
side=BUY,
token_id="<token-id>"
))
client.post_order(order)
# Market order (FOK = Fill-or-Kill)
market_order = client.create_market_order(MarketOrderArgs(
token_id="<token-id>",
amount=100.0, # USDC for BUY, shares for SELL
side=BUY
))
client.post_order(market_order, OrderType.FOK)
# Cancel
client.cancel(order_id)
client.cancel_all()
# Order book
book = client.get_order_book(token_id)
best_bid = float(book.bids[0].price) # Prices are strings!
best_ask = float(book.asks[0].price)
# Midpoint
mid = client.get_midpoint(token_id)
outcomePrices and clobTokenIds are JSON strings, not arrays:
import json
market = gamma_response
# WRONG: market["clobTokenIds"][0]
# RIGHT:
clob_ids = json.loads(market["clobTokenIds"])
yes_token = clob_ids[0]
no_token = clob_ids[1]
Minimum is 5 shares, not $5 USD:
# WRONG - 404 error
f"https://polymarket.com/event/{position['slug']}"
# RIGHT
f"https://polymarket.com/event/{position['eventSlug']}"
# DOES NOT WORK - returns ALL platform trades
GET /trades?proxyWallet=0x...
# USE THIS for user-specific trades:
GET /activity?user=0x...&limit=100
outcomePrices always sum to $1.00 - can't find arbitrage here.
Use CLOB orderbook for real bid/ask spreads.
# WRONG
best_bid = book.bids[0].price + 0.01
# RIGHT
best_bid = float(book.bids[0].price) + 0.01
import httpx
async def get_positions(wallet: str):
url = "https://data-api.polymarket.com/positions"
async with httpx.AsyncClient() as client:
resp = await client.get(url, params={"user": wallet})
return resp.json()
async def get_whale_trades(wallet: str, limit: int = 100):
url = "https://data-api.polymarket.com/activity"
async with httpx.AsyncClient() as client:
resp = await client.get(url, params={
"user": wallet,
"limit": limit
})
return resp.json()
async def get_leaderboard(period: str = "week"):
url = "https://data-api.polymarket.com/v1/leaderboard"
async with httpx.AsyncClient() as client:
resp = await client.get(url, params={
"timePeriod": period,
"orderBy": "PNL",
"limit": 20
})
return resp.json()
For detailed documentation, see:
POLYMARKET_PRIVATE_KEY=0x... # Signer key
POLY_FUNDER_ADDRESS=0x... # Proxy wallet (Magic.Link users)
POLY_SIGNATURE_TYPE=1 # 0=EOA, 1=PolyProxy
POLY_API_KEY=... # After credential creation
POLY_SECRET=...
POLY_PASSPHRASE=...
| Error | Cause | Solution |
|---|---|---|
invalid signature | Wrong signature_type | Use 1 for Magic.Link |
not enough balance / allowance | Missing funder | Add funder=PROXY_ADDRESS |
Unauthorized/Invalid api key | Stale creds | Re-derive credentials |