Skip to main content

CLOB Compatibility

PolySimulator mirrors Polymarket’s real execution model:
  • All orders are limit orders — market orders are just limit orders with FOK/IOC time-in-force at marketable prices
  • BUY fills at best ask, SELL fills at best bid — not the midpoint
  • The price field is the worst-price limit — slippage protection built into the order, not a separate parameter
  • FOK (Fill-or-Kill) and IOC (Immediate-or-Cancel) — immediate execution order types
The POST /v1/clob/order endpoint mirrors Polymarket’s real CLOB API schema, enabling one-URL-swap migration from paper trading to live trading.

The Migration Promise

┌──────────────────────────────────────────────────────────────────┐
│  Change ONLY the base URL and credentials to go live             │
│                                                                  │
│  Virtual: https://api.polysimulator.com/v1/clob/order            │
│  Live:    https://clob.polymarket.com/order                      │
└──────────────────────────────────────────────────────────────────┘
import requests

BASE = "https://api.polysimulator.com/v1"
headers = {"X-API-Key": "ps_live_kJ9mNx2p..."}

order = requests.post(f"{BASE}/clob/order", headers=headers, json={
    "token_id": "71321045679252...",
    "side": "BUY",
    "price": "0.65",
    "size": "10",
    "order_type": "GTC",
}).json()
Authentication difference: PolySimulator uses the X-API-Key header. Polymarket’s live CLOB requires L2 HMAC credentials (API key + secret + passphrase) derived from your wallet’s private key via py_clob_client. See the Live Migration Guide for full credential setup.

Request Schema

{
  "token_id": "71321045679252212594626385532706912750332728571942532289631379312455583992563",
  "side": "BUY",
  "price": "0.65",
  "size": "10",
  "order_type": "GTC",
  "fee_rate_bps": 0,
  "nonce": "optional-nonce",
  "client_order_id": "my-order-001"
}
All numeric fields (price, size) must be strings. Both PolySimulator and Polymarket’s real CLOB API expect string-encoded decimals, e.g. "0.65" not 0.65. Using floats will be rejected.
FieldTypeRequiredDescription
token_idstringYesCLOB outcome token ID
sidestringYesBUY or SELL
pricestringYesLimit price as decimal string (“0.01”–“0.99”)
sizestringYesNumber of shares as decimal string (> 0)
order_typestringNoGTC (default), FOK, IOC, GTD
fee_rate_bpsintNoAccepted but ignored in virtual mode
noncestringNoAccepted but ignored in virtual mode
takerstringNoAccepted but ignored in virtual mode
client_order_idstringNoIdempotency key

Response Schema

Mirrors the Polymarket CLOB response shape. Status values use lowercase strings matching Polymarket’s insert-order convention:
{
  "success": true,
  "orderID": "42",
  "status": "matched",
  "transactID": "42",
  "errorMsg": null,
  "price": "0.65",
  "size": "10.0",
  "side": "BUY",
  "takingAmount": "6.50",
  "makingAmount": "10.0"
}
Status ValueMeaning
matchedOrder fully filled
liveOrder pending (limit order resting)
unmatchedOrder cancelled or rejected

Field Mapping

Polymarket CLOBPolySimulator /v1/clob/orderNotes
tokenId / token_idtoken_idResolved to condition_id via Redis
side (0=BUY, 1=SELL)side (“BUY”/“SELL”)String enum
price (string)price (string)Decimal string: "0.65"
size (string)size (string)Decimal string: "10"
feeRateBpsfee_rate_bpsAccepted; no fees in virtual mode
orderTypeorder_typeGTC/FOK/IOC/GTD
signatureNot required (virtual mode)
saltNot required (virtual mode)
Fields like signature, salt, maker, and signer that are required for Polymarket’s blockchain settlement are accepted but ignored in virtual mode. This means you can develop your bot with (or without) these fields — either way works.
String vs Float numerics: Both PolySimulator and Polymarket require price and size as strings (e.g., "0.65" not 0.65). Always pass strings to ensure compatibility.

Public CLOB Read Endpoints

These endpoints mirror Polymarket’s public CLOB data API and require no authentication. They accept token_id (the CLOB outcome token) as query parameter.
MethodEndpointDescription
GET/v1/price?token_id=...Single token price with bid/ask
POST/v1/pricesBatch prices for multiple token IDs
GET/v1/midpoint?token_id=...Best-bid/best-ask midpoint
GET/v1/spread?token_id=...Spread (best bid, best ask, spread)
GET/v1/book?token_id=...Full order book snapshot
GET/v1/prices-history?token_id=...Historical OHLC candles
import requests
price = requests.get(
    "https://api.polysimulator.com/v1/price",
    params={"token_id": "71321045679252..."}
).json()
# {"token_id": "71321...", "price": "0.65", "bid": "0.64", "ask": "0.66"}
These endpoints use the same Redis price cache as the authenticated API. Data is refreshed every 30 seconds by the price poller.

Cancel Endpoints

Bulk cancel endpoints match Polymarket’s cancel response shape: {canceled: [...], not_canceled: {...}}.
MethodEndpointDescription
DELETE/v1/cancel-allCancel all pending limit orders
DELETE/v1/cancel-market-orders?market=...Cancel pending orders for a specific market
The cancel-market-orders endpoint accepts either market (condition_id) or asset_id (token_id) as query parameters.
// Response shape (both endpoints)
{
  "canceled": ["42", "43"],
  "not_canceled": {"44": "Cannot cancel order with status: FILLED"}
}

When to Use CLOB-Compat vs Native API

Use CaseRecommended Endpoint
New bot developmentPOST /v1/orders — richer features, string numerics
Porting existing Polymarket botPOST /v1/clob/order — minimal code changes
Planning to go live on PolymarketPOST /v1/clob/order — URL-swap ready
Advanced features (batch, limit, slippage)POST /v1/orders — full feature set

Next Steps