Polymarket Raw-HTTP Endpoints
PolySimulator exposes the exact path + payload shapes Polymarket’s public CLOB API uses. SDK clients written againsthttps://clob.polymarket.com (e.g. py-clob-client,
@polymarket/clob-client) can be pointed at PolySimulator by changing
only the base URL and credentials — no payload rewrites, no
field renames.
This page covers the raw-HTTP shape only. PolySimulator also
offers two simpler shapes for new code:
POST /v1/orders— native (market_id+outcome+quantity+price+time_in_force). See Placing Orders.POST /v1/clob/order— legacy SDK convenience (token_id+sidesize+price+order_type). See CLOB Compatibility.
Order Placement
POST /v1/order — single order
Mirror of Polymarket’s POST /order.
Request body:
| Side | makerAmount | takerAmount | Implied price | Implied quantity |
|---|---|---|---|---|
BUY | round(price × qty × 1e6) USDC | round(qty × 1e6) shares | makerAmount / takerAmount | takerAmount / 1e6 |
SELL | round(qty × 1e6) shares | round(price × qty × 1e6) USDC | takerAmount / makerAmount | makerAmount / 1e6 |
makerAmount=500000,
takerAmount=1000000.
On-chain fields are accepted and ignored: salt, maker, signer,
taker, nonce, feeRateBps, signatureType, signature,
timestamp, metadata, builder. PolySimulator is paper trading —
there is no chain to settle against.
orderType enum: GTC | FOK | FAK | GTD. We don’t support
good-til-date natively; GTD coerces to GTC so SDK callers get a
working order rather than a 422.
Response:
status enum on write (POST /v1/order, POST /v1/orders): live
(resting on book) / matched (filled immediately) / unmatched
(rejected). PolySimulator does not return PM’s delayed status —
we don’t delay matching.
TypeScript / Node example
TypeScript users: the PolySimulator API
Mintlify spec is auto-generated from the live OpenAPI; if you’re
using
openapi-typescript to generate types, run it against
https://docs.polysimulator.com/openapi.json (auto-rebuilds on every
deploy).POST /v1/orders — single object or PM batch array
POST /v1/orders dispatches on the JSON body type:
- A JSON object is the native single order:
{market_id, side, outcome, quantity, order_type, price, time_in_force}. - A JSON array is a Polymarket-shape batch of up to 15
PmSendOrderRequestentries — each entry is validated and executed independently (per-entry failure isolation, matching PM’s “failures in one entry do not abort the others” contract). A malformed entry surfaces as a failed result at its array index rather than rejecting the whole batch. More than 15 entries returns400.
POST /v1/order
(singular):
Order Lifecycle
GET /v1/data/orders — list user’s orders, PM envelope
Polymarket-shaped OrdersResponse:
next_cursor back as ?next_cursor=... (PM’s request param —
what py-clob-client sends) or the ?cursor=... alias to paginate.
Cursor is urlsafe-base64 and opaque; the SDK’s initial MA== seed and
the LTE= terminal sentinel both behave exactly as on real PM.
Default scope matches PM: OPEN orders only (since 2026-06-11).
Pass the polysim-extension ?status= param (ORDER_STATUS_MATCHED,
ORDER_STATUS_CANCELED, ALL, or friendly aliases like matched /
canceled) to read history.
Filters: id, market, asset_id (token id — resolves to the
market+outcome and filters both), status, before / after
(unix-seconds timestamps, PM convention; ISO accepted as an extra;
garbage returns 400 instead of being silently dropped), limit
(max 500).
GET /v1/order/{orderID} — single order
Returns a single OpenOrder with the same shape as data[] above.
Hex order IDs (PM uses on-chain hashes; we use integer DB ids
serialised as strings) cleanly 404 with error: ORDER_NOT_FOUND
instead of crashing.
DELETE /v1/order — cancel by body
{canceled: ["6391"], not_canceled: {}} — PM’s exact shape.
DELETE /v1/orders — bulk cancel (array body)
not_canceled with an explanation.
POST /v1/cancel-all — cancel all open orders
No body. Returns the same {canceled, not_canceled} envelope.
Read Endpoints (public — no auth)
These mirror Polymarket’s public market-data endpoints. All return the exact shape PM emits.| Endpoint | Purpose | PM equivalent |
|---|---|---|
GET /v1/markets-by-token/{token_id} | Resolve tokenId → (condition_id, outcome) | (PolySim convenience; PM does not expose this directly) |
GET /v1/midpoint?token_id= | Midpoint price | GET /midpoint |
POST /v1/midpoints | Batch midpoints | POST /midpoints |
GET /v1/spread?token_id= | Bid/ask spread (capped at $0.10 per PM parity) | GET /spread |
POST /v1/spreads | Batch spreads | POST /spreads |
GET /v1/book?token_id= | L2 order book | GET /book |
POST /v1/books | Batch books | POST /books |
GET /v1/last-trade-price?token_id= | Last trade {price, side} | GET /last-trade-price |
GET /v1/tick-size/{token_id} | Minimum tick size: {minimum_tick_size: number} ∈ {0.1, 0.01, 0.001, 0.0001} | GET /tick-size/{token_id} |
GET /v1/neg-risk/{token_id} | {neg_risk: bool} for multi-outcome markets | GET /neg-risk/{token_id} |
GET /v1/time | Bare integer Unix-epoch seconds (e.g. 1779147906), not an object | GET /time |
Field-type details:
GET /v1/tick-size/{token_id}returnsminimum_tick_sizeas a JSON number (0.01), matching live Polymarket. Note that thetick_sizefield inside a/v1/booksnapshot is a string — see String Numerics.GET /v1/timereturns a bare integer (1779147906), not a{"server_time": ...}object — this matches Polymarket’s wire.
bid=0.001 ask=0.999
book report spread="0.10", not 0.998. This stops arbitrage
filters from treating every illiquid book as a free-money signal.
Tick-Size Enforcement
PolySimulator rejects limit orders whoseprice doesn’t conform to
the market’s minimum tick size — exactly as Polymarket does.
GET /v1/tick-size/{token_id} before submitting. SDKs that already
implement PM’s quantisation (e.g. py-clob-client.utilities.price_valid)
work without modification.
Market orders use price as a slippage bound, not a strict price,
so off-grid price values are not tick-rejected on market orders.
Beta Cohort Header
Beta-issued keys carryX-API-Beta-Cutoff: expired on every response
once the cohort cutoff date passes. SDKs can treat this header as the
signal to enter read-only mode:
SDK Migration Checklist
Porting apy-clob-client bot? Three lines of config:
@polymarket/clob-client (TypeScript) is the same: change host,
swap auth headers. salt, signer, signature continue to be
generated client-side and ignored server-side — no SDK changes
needed.
Next Steps
- Placing Orders — Native
/v1/ordersshape - CLOB Compatibility — Three trading paths compared
- Error Handling — Full error code reference
- Authentication —
X-API-Keyand thePOLY_API_KEYalias