trading-polymarket

Polymarket Trading - Complete API Reference

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "trading-polymarket" with this command: npx skills add alsk1992/cloddsbot/alsk1992-cloddsbot-trading-polymarket

Polymarket Trading - Complete API Reference

Full access to Polymarket's CLOB (Central Limit Order Book) via the official py_clob_client library.

60+ methods documented. This is the complete reference.

Required Environment Variables

PRIVATE_KEY=0x... # Ethereum private key for signing POLY_FUNDER_ADDRESS=0x... # Your wallet address on Polygon POLY_API_KEY=... # From Polymarket API POLY_API_SECRET=... # Base64 encoded secret POLY_API_PASSPHRASE=... # API passphrase

Installation

pip install py-clob-client requests

Authentication Levels

Level Requirements Capabilities

L0 None Read-only: orderbooks, prices, markets

L1 Private key Create & sign orders (not post)

L2 Private key + API creds Full trading: post orders, cancel, query

Signature Types

Type Use Case

0

Standard EOA (MetaMask, hardware wallets)

1

Magic/email wallets (delegated signing)

2

Proxy wallets (Gnosis Safe, browser proxy)

ClobClient - Complete API (60+ Methods)

Initialization

from py_clob_client.client import ClobClient from py_clob_client.clob_types import ( OrderArgs, MarketOrderArgs, ApiCreds, OrderType, BookParams, TradeParams, OpenOrderParams, BalanceAllowanceParams, AssetType, OrderScoringParams, OrdersScoringParams, DropNotificationParams ) from py_clob_client.order_builder.constants import BUY, SELL from py_clob_client.constants import POLYGON # 137

Level 2 Auth (full trading access)

client = ClobClient( host="https://clob.polymarket.com", key=os.getenv("PRIVATE_KEY"), # Private key for signing chain_id=POLYGON, # 137 for mainnet, 80002 for Amoy testnet funder=os.getenv("POLY_FUNDER_ADDRESS"), # Wallet address (for proxy wallets) signature_type=2 # 0=EOA, 1=MagicLink, 2=Proxy )

Set API credentials for authenticated endpoints

client.set_api_creds(ApiCreds( api_key=os.getenv("POLY_API_KEY"), api_secret=os.getenv("POLY_API_SECRET"), api_passphrase=os.getenv("POLY_API_PASSPHRASE") ))

Health & Configuration

client.get_ok() # Check if server is up client.get_server_time() # Get server timestamp client.get_address() # Your signer's public address client.get_collateral_address() # USDC contract address client.get_conditional_address() # CTF contract address client.get_exchange_address() # Exchange contract (neg_risk=False default)

Market Data - Single Token

Get prices and spreads

client.get_midpoint(token_id) # Mid market price client.get_price(token_id, side="BUY") # Best price for side client.get_spread(token_id) # Current spread client.get_last_trade_price(token_id) # Last executed trade price

Get full orderbook

orderbook = client.get_order_book(token_id)

Returns: OrderBookSummary with bids, asks, tick_size, neg_risk, timestamp, hash

Market Data - Batch (Multiple Tokens)

params = [ BookParams(token_id="TOKEN1", side="BUY"), BookParams(token_id="TOKEN2", side="SELL") ]

client.get_midpoints(params) # Multiple midpoints client.get_prices(params) # Multiple prices client.get_spreads(params) # Multiple spreads client.get_order_books(params) # Multiple orderbooks client.get_last_trades_prices(params) # Multiple last prices

Market Metadata

client.get_tick_size(token_id) # Returns: "0.1", "0.01", "0.001", or "0.0001" client.get_neg_risk(token_id) # Returns: True/False (negative risk market) client.get_fee_rate_bps(token_id) # Returns: fee rate in basis points (0 or 1000)

Order Types

from py_clob_client.clob_types import OrderType

OrderType.GTC # Good Till Cancelled - stays open until filled/cancelled OrderType.FOK # Fill Or Kill - fill entirely immediately or cancel OrderType.GTD # Good Till Date - expires at timestamp (min 60 seconds) OrderType.FAK # Fill And Kill - fill what's possible, cancel rest

When to Use Each Order Type

Type Use Case Example

GTC Entries - wait for fill Place buy at 0.45, wait for dip

FOK Exits - need immediate fill Market sell entire position NOW

GTD Time-limited orders Offer expires in 5 minutes

FAK Partial fills OK Get as much as possible now

OrderArgs - Limit Orders

OrderArgs( token_id: str, # Token ID (outcome to trade) price: float, # Price 0.01-0.99 size: float, # Number of shares side: str, # "BUY" or "SELL" (or use BUY/SELL constants) fee_rate_bps: int = 0, # Optional: fee rate in bps (0 or check market) nonce: int = 0, # Optional: unique nonce for cancellation expiration: int = 0, # Optional: expiry timestamp (0 = GTC, use timestamp for GTD) taker: str = ZERO_ADDRESS # Optional: specific taker (ZERO_ADDRESS = anyone) )

MarketOrderArgs - Market Orders

MarketOrderArgs( token_id: str, # Token ID amount: float, # Total USDC amount to spend (BUY) or shares (SELL) side: str, # "BUY" or "SELL" price: float = 0, # Optional: worst acceptable price (slippage protection) fee_rate_bps: int = 0, # Optional: fee rate nonce: int = 0, # Optional: nonce taker: str = ZERO_ADDRESS, # Optional: taker address order_type: OrderType = FOK # Optional: FOK (default) or FAK )

Complete Order Examples

from py_clob_client.order_builder.constants import BUY, SELL

1. LIMIT BUY (GTC) - sits on book until filled

order = client.create_and_post_order( OrderArgs(token_id=TOKEN_ID, price=0.45, size=100.0, side=BUY) )

2. LIMIT SELL (GTC)

order = client.create_and_post_order( OrderArgs(token_id=TOKEN_ID, price=0.55, size=50.0, side=SELL) )

3. MARKET BUY - spend $100 USDC at current prices (FOK)

signed = client.create_market_order( MarketOrderArgs(token_id=TOKEN_ID, amount=100.0, side=BUY) ) result = client.post_order(signed, orderType=OrderType.FOK)

4. MARKET SELL - sell all shares immediately (FOK)

signed = client.create_market_order( MarketOrderArgs(token_id=TOKEN_ID, amount=my_shares, side=SELL) ) result = client.post_order(signed, orderType=OrderType.FOK)

5. POST-ONLY MAKER ORDER (avoid taker fees, earn rebates)

signed = client.create_order( OrderArgs(token_id=TOKEN_ID, price=0.44, size=100.0, side=BUY) ) result = client.post_order(signed, orderType=OrderType.GTC, post_only=True)

If order would cross spread, it gets REJECTED instead of taking

6. GOOD TIL DATE (GTD) - expires after timestamp

import time expiry = int(time.time()) + 300 # 5 minutes from now signed = client.create_order( OrderArgs(token_id=TOKEN_ID, price=0.50, size=100.0, side=BUY, expiration=expiry) ) result = client.post_order(signed, orderType=OrderType.GTD)

7. FILL AND KILL (FAK) - fill what you can, cancel rest

signed = client.create_market_order( MarketOrderArgs(token_id=TOKEN_ID, amount=1000.0, side=BUY) ) result = client.post_order(signed, orderType=OrderType.FAK)

Order Operations

Create and Post Orders

SIMPLE: Create and post in one call (recommended)

result = client.create_and_post_order( OrderArgs( token_id="123456789012345678901234567890", price=0.45, size=10.0, side="BUY" ) )

Returns: {"orderID": "...", "status": "...", ...}

ADVANCED: Separate create and post

order = client.create_order(OrderArgs(...)) # Returns SignedOrder result = client.post_order(order, orderType=OrderType.GTC, post_only=False)

Market order (calculates price automatically)

result = client.create_market_order( MarketOrderArgs( token_id="...", amount=100.0, # Spend $100 USDC side="BUY" ) )

Calculate expected fill price before market order

price = client.calculate_market_price( token_id="...", side="BUY", amount=100.0, order_type=OrderType.FOK )

Cancel Orders

client.cancel(order_id="ORDER_ID") # Cancel specific order client.cancel_orders(["ID1", "ID2", "ID3"]) # Cancel multiple client.cancel_all() # Cancel ALL open orders client.cancel_market_orders( # Cancel by market/asset market="CONDITION_ID", asset_id="TOKEN_ID" )

Query Orders

Get all open orders

orders = client.get_orders( params=OpenOrderParams( id="ORDER_ID", # Optional: specific order market="COND_ID", # Optional: filter by market asset_id="TOKEN" # Optional: filter by token ), next_cursor="MA==" # For pagination )

Get specific order

order = client.get_order(order_id="ORDER_ID")

Trade History

trades = client.get_trades( params=TradeParams( id="TRADE_ID", # Optional: specific trade maker_address="0x...", # Optional: filter by maker market="CONDITION_ID", # Optional: filter by market asset_id="TOKEN_ID", # Optional: filter by token before="2024-01-01", # Optional: before date after="2023-01-01" # Optional: after date ), next_cursor="MA==" )

Balance & Allowance

Check balance and allowances

balance = client.get_balance_allowance( params=BalanceAllowanceParams( asset_type=AssetType.COLLATERAL, # USDC balance # or AssetType.CONDITIONAL # Token balance token_id="TOKEN_ID" # For conditional tokens ) )

Update/refresh allowance cache

client.update_balance_allowance(params=...)

Market Discovery

Get Markets from CLOB

All active markets

markets = client.get_markets(next_cursor="MA==") simplified = client.get_simplified_markets()

Specific market

market = client.get_market(condition_id="CONDITION_ID")

Market trade events

events = client.get_market_trades_events(condition_id="CONDITION_ID")

Sampling/featured markets

client.get_sampling_markets() client.get_sampling_simplified_markets()

Get Markets from Gamma API (More Details)

import requests

def search_markets(query: str, limit: int = 10): """Search Polymarket markets by keyword""" url = "https://gamma-api.polymarket.com/markets" params = { "_q": query, "active": "true", "closed": "false", "_limit": limit } r = requests.get(url, params=params) return r.json()

Get market details

markets = search_markets("bitcoin") for m in markets: print(f"Question: {m['question']}") print(f"Condition ID: {m['condition_id']}") print(f"Volume: ${m.get('volume', 0):,.2f}") for token in m.get('tokens', []): print(f" {token['outcome']}: {token['token_id']}") print(f" Price: {float(token['price']):.2f}")

On-Chain Operations

Check Token Balance (Position Size)

import requests

CTF_CONTRACT = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" RPC_URL = "https://polygon-rpc.com/"

def get_token_balance(wallet: str, token_id: str) -> float: """Get balance of a specific outcome token in shares""" token_int = int(token_id) # ERC-1155 balanceOf(address,uint256) data = f"0x00fdd58e000000000000000000000000{wallet[2:].lower()}{token_int:064x}"

r = requests.post(RPC_URL, json={
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [{"to": CTF_CONTRACT, "data": data}, "latest"],
    "id": 1
})

result = r.json().get("result", "0x0")
balance = int(result, 16) / 1e6  # Convert from raw to shares
return balance

Usage

balance = get_token_balance( wallet="0x7c2211103e7Fbb257Ac6fa59f972cfd8bc9D4795", token_id="12345678901234567890" ) print(f"Position: {balance} shares")

Check USDC Balance

USDC_CONTRACT = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"

def get_usdc_balance(wallet: str) -> float: """Get USDC balance on Polygon""" # ERC-20 balanceOf(address) data = f"0x70a08231000000000000000000000000{wallet[2:].lower()}"

r = requests.post(RPC_URL, json={
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [{"to": USDC_CONTRACT, "data": data}, "latest"],
    "id": 1
})

result = r.json().get("result", "0x0")
return int(result, 16) / 1e6  # USDC has 6 decimals

API Key Management

Create new API key

creds = client.create_api_key(nonce=0)

Derive existing API key (if you lost creds but have private key)

creds = client.derive_api_key(nonce=0)

Create or derive (tries both)

creds = client.create_or_derive_api_creds(nonce=0)

Get all your API keys

keys = client.get_api_keys()

Delete current API key

client.delete_api_key()

Readonly API keys (for monitoring only)

readonly = client.create_readonly_api_key() client.get_readonly_api_keys() client.delete_readonly_api_key(key="...") client.validate_readonly_api_key(address="0x...", key="...")

Advanced Features

Order Heartbeat (Keep Orders Alive)

Start heartbeat - if not sent within 10s, all orders cancelled

heartbeat_id = client.post_heartbeat(heartbeat_id=None)

Continue sending heartbeats

while trading: client.post_heartbeat(heartbeat_id=heartbeat_id) time.sleep(5)

Order Scoring

Check if order is scoring (earning rewards)

is_scoring = client.is_order_scoring( params=OrderScoringParams(order_id="...") )

Check multiple orders

scores = client.are_orders_scoring( params=OrdersScoringParams(order_ids=["ID1", "ID2"]) )

Notifications

notifications = client.get_notifications() client.drop_notifications(params=DropNotificationParams(...))

Fee Structure

IMPORTANT: Most Polymarket markets have ZERO fees (0% maker, 0% taker).

15-min Crypto Markets (Exception)

Only 15-minute BTC/ETH/SOL/XRP price prediction markets have fees:

fee = shares × 0.25 × (price × (1 - price))²

Entry Price Fee % (per side)

0.50 ~1.56%

0.60 or 0.40 ~1.44%

0.70 or 0.30 ~1.10%

0.80 or 0.20 ~0.64%

0.90 or 0.10 ~0.20%

TAKER = crosses spread = PAYS fee MAKER = adds liquidity = NO fee + earns rebates

To be a maker: Post orders that don't immediately fill (inside the spread).

Decimal Precision Rules

Order Side Price Decimals Size Decimals

BUY 2 4

SELL 2 2

Min order size: $1 per side

Complete Trading Example

#!/usr/bin/env python3 """ Production-ready Polymarket trading script """

import os import time import requests from py_clob_client.client import ClobClient from py_clob_client.clob_types import OrderArgs, ApiCreds, OrderType

Initialize

client = ClobClient( "https://clob.polymarket.com", key=os.getenv("PRIVATE_KEY"), chain_id=137, funder=os.getenv("POLY_FUNDER_ADDRESS"), signature_type=2 ) client.set_api_creds(ApiCreds( api_key=os.getenv("POLY_API_KEY"), api_secret=os.getenv("POLY_API_SECRET"), api_passphrase=os.getenv("POLY_API_PASSPHRASE") ))

TOKEN_ID = "YOUR_TOKEN_ID" WALLET = os.getenv("POLY_FUNDER_ADDRESS") CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"

def get_balance(token_id): """Get position size""" token_int = int(token_id) data = f"0x00fdd58e000000000000000000000000{WALLET[2:].lower()}{token_int:064x}" r = requests.post("https://polygon-rpc.com/", json={ "jsonrpc": "2.0", "method": "eth_call", "params": [{"to": CTF, "data": data}, "latest"], "id": 1 }) return int(r.json().get("result", "0x0"), 16) / 1e6

def get_orderbook(token_id): """Get current bid/ask""" book = client.get_order_book(token_id) return { "best_bid": float(book.bids[0].price) if book.bids else 0, "best_ask": float(book.asks[0].price) if book.asks else 1 }

Check position

position = get_balance(TOKEN_ID) print(f"Current position: {position} shares")

Get market

book = get_orderbook(TOKEN_ID) print(f"Bid: {book['best_bid']:.2f}, Ask: {book['best_ask']:.2f}")

Place a buy order (maker - inside spread)

buy_price = book['best_bid'] + 0.01 # 1 cent above bid if buy_price < book['best_ask']: # Ensure we're maker result = client.create_and_post_order(OrderArgs( token_id=TOKEN_ID, price=buy_price, size=10.0, side="BUY" )) print(f"Buy order placed: {result}")

Place a sell order (market sell via FOK)

if position > 0: result = client.create_and_post_order(OrderArgs( token_id=TOKEN_ID, price=0.01, # Lowest price = immediate fill size=position, side="SELL" )) print(f"Sold position: {result}")

Error Handling

from py_clob_client.exceptions import PolyApiException

try: result = client.create_and_post_order(OrderArgs(...)) except PolyApiException as e: print(f"API Error: {e}") except Exception as e: print(f"Error: {e}")

Common errors:

  • "insufficient balance"

  • Not enough USDC/tokens

  • "invalid price"

  • Price outside 0.01-0.99 or wrong decimals

  • "order too small"

  • Below minimum order size

  • "market closed"

  • Market not accepting orders

CLI Commands (/poly )

Access Polymarket trading directly from Claude Code:

Market Data

/poly search <query> # Search markets /poly market <condition-id> # Market details /poly book <token-id> # View orderbook

Trading

/poly buy <token-id> <size> <price> # Buy shares (limit) /poly sell <token-id> <size> <price> # Sell shares (limit) /poly orders # Open orders /poly cancel <order-id> # Cancel order /poly cancel all # Cancel all orders /poly trades [limit] # Recent trade history /poly balance # USDC + positions

Advanced Orders

/poly twap <buy|sell> <token> <total> <price> [slices] [interval-sec] /poly bracket <token> <size> <tp> <sl> # TP + SL bracket /poly trigger buy <token> <size> <price> # Buy when price drops

Note: TWAP and bracket orders are persisted to the database and will automatically resume after restarts.

Auto-Redeem (Resolved Positions)

/poly redeem # One-time redeem all resolved positions /poly redeem start # Start auto-polling (default: every 60s) /poly redeem stop # Stop auto-polling /poly redeem status # Check auto-redeemer status /poly redeem pending # List positions pending redemption /poly redeem <conditionId> <tokenId> # Redeem specific position

Env vars:

  • POLY_REDEEM_INTERVAL_MS
  • Polling interval in ms (default: 60000 = 1 minute)

Real-Time Fills (WebSocket)

/poly fills # Connect fills WebSocket /poly fills status # Show connection + recent fills /poly fills stop # Disconnect fills WebSocket /poly fills clear # Clear tracked fills

Order Heartbeat

/poly heartbeat # Start heartbeat (keeps orders alive) /poly heartbeat status # Check heartbeat status /poly heartbeat stop # Stop heartbeat (orders cancelled in 10s)

Account & Settlements

/poly settlements # View pending settlements from resolved markets /poly allowance # Check USDC approval status /poly orderbooks <token1> [token2] ... # Batch fetch orderbooks

Complete ClobClient Method Reference

Health & Config (L0 - No Auth)

Method Parameters Returns Description

get_ok()

dict Health check

get_server_time()

dict Server timestamp

get_address()

str Your signer address

get_collateral_address()

str USDC contract

get_conditional_address()

str CTF contract

get_exchange_address(neg_risk)

bool str Exchange contract

Market Data (L0 - No Auth)

Method Parameters Returns Description

get_midpoint(token_id)

str dict Mid price

get_midpoints(params)

list[BookParams] dict Multiple mid prices

get_price(token_id, side)

str, str dict Best price for side

get_prices(params)

list[BookParams] dict Multiple prices

get_spread(token_id)

str dict Bid-ask spread

get_spreads(params)

list[BookParams] dict Multiple spreads

get_order_book(token_id)

str OrderBookSummary Full orderbook

get_order_books(params)

list[BookParams] list Multiple orderbooks

get_last_trade_price(token_id)

str dict Last trade

get_last_trades_prices(params)

list[BookParams] dict Multiple last trades

get_tick_size(token_id)

str TickSize "0.1"/"0.01"/"0.001"/"0.0001"

get_neg_risk(token_id)

str bool Is neg_risk market

get_fee_rate_bps(token_id)

str int Fee in basis points

Market Discovery (L0 - No Auth)

Method Parameters Returns Description

get_markets(next_cursor)

str dict Paginated markets

get_simplified_markets(next_cursor)

str dict Simplified markets

get_sampling_markets(next_cursor)

str dict Featured markets

get_market(condition_id)

str dict Single market

get_market_trades_events(condition_id)

str dict Trade events

Order Creation (L1 - Needs Private Key)

Method Parameters Returns Description

create_order(order_args, options)

OrderArgs, CreateOrderOptions dict Sign limit order

create_market_order(order_args, options)

MarketOrderArgs, CreateOrderOptions dict Sign market order

calculate_market_price(token_id, side, amount, order_type)

str, str, float, OrderType float Expected fill price

Order Posting (L2 - Needs API Creds)

Method Parameters Returns Description

post_order(order, orderType, post_only)

SignedOrder, OrderType, bool dict Post single order

post_orders(args)

list[PostOrdersArgs] dict Post batch orders

create_and_post_order(order_args, options)

OrderArgs, PartialCreateOrderOptions dict Create + post (recommended)

Order Cancellation (L2 - Needs API Creds)

Method Parameters Returns Description

cancel(order_id)

str dict Cancel one order

cancel_orders(order_ids)

list[str] dict Cancel multiple

cancel_all()

dict Cancel ALL orders

cancel_market_orders(market, asset_id)

str, str dict Cancel by market

Order Queries (L2 - Needs API Creds)

Method Parameters Returns Description

get_orders(params, next_cursor)

OpenOrderParams, str list Get open orders

get_order(order_id)

str dict Get specific order

get_trades(params, next_cursor)

TradeParams, str list Trade history

API Key Management (L2 - Needs API Creds)

Method Parameters Returns Description

create_api_key(nonce)

int ApiCreds Create new key

derive_api_key(nonce)

int ApiCreds Derive existing key

create_or_derive_api_creds(nonce)

int ApiCreds Create or derive

set_api_creds(creds)

ApiCreds

Set credentials

get_api_keys()

dict List your keys

delete_api_key()

dict Delete current key

create_readonly_api_key()

ReadonlyApiKeyResponse Readonly key

get_readonly_api_keys()

list[str] List readonly keys

delete_readonly_api_key(key)

str bool Delete readonly key

Balance & Allowance (L2 - Needs API Creds)

Method Parameters Returns Description

get_balance_allowance(params)

BalanceAllowanceParams dict Check balance

update_balance_allowance(params)

BalanceAllowanceParams dict Refresh allowance

Advanced Features (L2 - Needs API Creds)

Method Parameters Returns Description

post_heartbeat(heartbeat_id)

str dict Keep orders alive (10s timeout)

is_order_scoring(params)

OrderScoringParams dict Check if earning rewards

are_orders_scoring(params)

OrdersScoringParams dict Check multiple orders

get_notifications()

dict Get notifications

drop_notifications(params)

DropNotificationParams dict Delete notifications

get_closed_only_mode()

dict Check closed-only status

Contract Addresses (Polygon Mainnet)

USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" # Collateral token CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" # Conditional tokens (ERC-1155) EXCHANGE = "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E" # Regular exchange NEG_RISK = "0xC5d563A36AE78145C45a50134d48A1215220f80a" # Neg risk exchange (crypto)

Quick Reference: Common Patterns

Check Position → Sell All

balance = get_token_balance(wallet, token_id) if balance > 0: client.create_and_post_order(OrderArgs( token_id=token_id, price=0.01, size=balance, side="SELL" ))

Maker Entry (No Fees)

book = client.get_order_book(token_id) best_bid = float(book.bids[0].price) if book.bids else 0 maker_price = best_bid + 0.01 # 1 cent above bid signed = client.create_order(OrderArgs(token_id=token_id, price=maker_price, size=100, side="BUY")) client.post_order(signed, orderType=OrderType.GTC, post_only=True)

Market Buy $50 Worth

signed = client.create_market_order(MarketOrderArgs(token_id=token_id, amount=50.0, side="BUY")) client.post_order(signed, orderType=OrderType.FOK)

Cancel Everything

client.cancel_all()

WebSocket Channels (Real-Time Updates)

Polymarket provides WebSocket channels for real-time updates. No RPC needed - everything goes through CLOB.

WebSocket URLs

MARKET_WS = "wss://ws-subscriptions-clob.polymarket.com/ws/market" USER_WS = "wss://ws-subscriptions-clob.polymarket.com/ws/user"

Market Channel (Public - No Auth)

Subscribe to orderbook updates, price changes, trades for any market.

import websocket import json

def on_message(ws, message): data = json.loads(message) event_type = data.get("event_type")

if event_type == "book":
    # Full orderbook snapshot (on subscribe + after trades)
    print(f"Book update: {data['bids']}, {data['asks']}")

elif event_type == "price_change":
    # Order placed/cancelled affecting price level
    print(f"Price change: {data}")

elif event_type == "last_trade_price":
    # Trade executed
    print(f"Trade: {data['price']} x {data['size']}")

elif event_type == "tick_size_change":
    # Tick size changed (price went extreme)
    print(f"Tick size: {data['old_tick_size']} -> {data['new_tick_size']}")

def on_open(ws): # Subscribe to specific token ws.send(json.dumps({ "type": "subscribe", "channel": "market", "assets_ids": [TOKEN_ID] # List of token IDs }))

ws = websocket.WebSocketApp( "wss://ws-subscriptions-clob.polymarket.com/ws/market", on_message=on_message, on_open=on_open ) ws.run_forever()

User Channel (Authenticated - For Fills)

Subscribe to YOUR order updates, fills, trades. This is how you get fill notifications.

import websocket import json import hmac import hashlib import time import base64

API_KEY = os.getenv("POLY_API_KEY") API_SECRET = os.getenv("POLY_API_SECRET") API_PASSPHRASE = os.getenv("POLY_API_PASSPHRASE")

def get_auth_headers(): """Generate HMAC auth for WebSocket""" timestamp = str(int(time.time())) message = f"GET\n{timestamp}\n/ws/user" signature = hmac.new( base64.b64decode(API_SECRET), message.encode(), hashlib.sha256 ).digest() return { "POLY-ADDRESS": WALLET_ADDRESS, "POLY-SIGNATURE": base64.b64encode(signature).decode(), "POLY-TIMESTAMP": timestamp, "POLY-API-KEY": API_KEY, "POLY-PASSPHRASE": API_PASSPHRASE }

def on_message(ws, message): data = json.loads(message) event_type = data.get("event_type")

if event_type == "trade":
    # YOUR FILL - order matched!
    status = data.get("status")  # MATCHED, MINED, CONFIRMED, FAILED
    print(f"FILL: {data['side']} {data['size']} @ {data['price']}")
    print(f"  Status: {status}")
    print(f"  Trade ID: {data['id']}")
    print(f"  Market: {data['market']}")

    if status == "CONFIRMED":
        print("  ✓ Trade confirmed on-chain!")
    elif status == "FAILED":
        print("  ✗ Trade failed - check logs")

elif event_type == "order":
    order_type = data.get("type")  # PLACEMENT, UPDATE, CANCELLATION
    print(f"ORDER {order_type}: {data['side']} {data['original_size']} @ {data['price']}")
    print(f"  Filled: {data.get('size_matched', 0)}")

    if order_type == "CANCELLATION":
        print("  Order cancelled")

def on_open(ws): # Subscribe with auth ws.send(json.dumps({ "type": "subscribe", "channel": "user", "auth": get_auth_headers(), # Optional: filter to specific market # "markets": [CONDITION_ID] }))

ws = websocket.WebSocketApp( "wss://ws-subscriptions-clob.polymarket.com/ws/user", on_message=on_message, on_open=on_open ) ws.run_forever()

Message Types Summary

Market Channel:

Event Trigger Key Fields

book

Subscribe, trades affect book bids, asks, timestamp

price_change

Order placed/cancelled price, size, side

last_trade_price

Trade executed price, size, side

tick_size_change

Price extreme (>0.96 or <0.04) old_tick_size, new_tick_size

User Channel:

Event Trigger Key Fields

trade

Your order filled status, side, size, price, market

order

Order placed/updated/cancelled type (PLACEMENT/UPDATE/CANCELLATION), size_matched

Trade Status Flow

MATCHED → MINED → CONFIRMED (success) → RETRYING → CONFIRMED/FAILED

Keepalive

Send PING every 10 seconds to keep connection alive:

import threading

def send_ping(): while True: ws.send(json.dumps({"type": "ping"})) time.sleep(10)

threading.Thread(target=send_ping, daemon=True).start()

Real-Time Data Client (Alternative)

Polymarket also provides @polymarket/real-time-data-client for TypeScript:

import { RealTimeDataClient } from "@polymarket/real-time-data-client";

const client = new RealTimeDataClient({ onMessage: (msg) => console.log(msg), onConnect: (c) => { // Subscribe to user fills with auth c.subscribe({ subscriptions: [{ topic: "clob_user", type: "*", clob_auth: { key: API_KEY, secret: API_SECRET, passphrase: API_PASSPHRASE } }] }); } });

client.connect();

No RPC Needed - CLOB Handles Everything

Operation Method

Get positions GET /data/positions?user={address} via Gamma API

Get balance client.get_balance_allowance()

Place orders client.create_and_post_order()

Get fills User WebSocket channel

Get prices client.get_order_book() or Market WebSocket

Cancel orders client.cancel()

The only time you might use RPC is to check on-chain token balances independently, but even that's available via Gamma API positions endpoint.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

binance-futures

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

trading-futures

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

tts

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

auto-reply

No summary provided by upstream source.

Repository SourceNeeds Review