Skip to main content
POST
/
v1
/
orders
curl --request POST \
  --url https://api.polysimulator.com/v1/orders \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: <api-key>' \
  --data '
{
  "market_id": "0xabc123...",
  "side": "BUY",
  "outcome": "Yes",
  "quantity": "10",
  "order_type": "market",
  "price": "0.68"
}
'
{
  "order_id": 123,
  "status": "<string>",
  "order_type": "<string>",
  "side": "<string>",
  "outcome": "<string>",
  "price": "<string>",
  "quantity": "<string>",
  "notional": "<string>",
  "fee": "<string>",
  "filled_at": "<string>",
  "cancelled_reason": "<string>",
  "price_source": "<string>",
  "slippage_bps": 123,
  "quote_age_ms": 123,
  "spread_bps": 123,
  "impact_bps": 123,
  "book_walk_levels": 123,
  "account_balance": "<string>",
  "position": {},
  "client_order_id": "<string>",
  "error": "<string>",
  "error_message": "<string>",
  "amount_interpreted_as": "<string>",
  "is_replay": true,
  "warnings": [
    "<string>"
  ]
}

Authorizations

X-API-Key
string
header
required

Issue from /v1/keys (or admin-issued for enterprise tier).

Headers

Idempotency-Key
string | null
X-API-Key
string | null

Your PolySimulator API key

POLY_API_KEY
string | null

Polymarket-CLOB-compat alias for X-API-Key (underscore form). SDK clients ported from Polymarket can authenticate without changing header names. X-API-Key takes precedence when both are provided.

Poly-API-Key
string | null

PM-CLOB-compat dashed-form alias for X-API-Key. Same value semantics as POLY_API_KEY but with HTTP-conventional dash separators. Audit P1 (staging audit 2026-05-16 0817 PR #1296): the per-tier middleware accepts both spellings but the auth dependency originally only matched the underscore form — now both work end-to-end.

authorization
string | null

PM-CLOB-compat: Authorization: Bearer ps_live_... (or ps_test_...) is accepted as an alias for X-API-Key so py-clob-client and other ported SDKs authenticate without header name changes. Bearer JWTs are NOT accepted here — use the dashboard-auth endpoints for those.

Body

application/json
market_id
string
required

Polymarket condition_id

Maximum string length: 256
side
enum<string>
required
Available options:
BUY,
SELL
outcome
string
required

Outcome label, e.g., Yes or No

Maximum string length: 200
quantity
string | null

Number of shares as decimal string, e.g. '10.5'. Required UNLESS amount is provided (BUY market orders only — Polymarket convention).

amount
string | null

USD amount to spend, as decimal string (e.g. '10.50'). Polymarket convention for BUY market orders: amount=5 means 'spend $5' (versus our quantity=5 which means 'buy 5 shares ≈ $5 × current_price'). Only valid when side=BUY and order_type=market; the handler derives quantity = floor4(amount / price) using the caller-supplied worst-price limit in the price field (NOT the eventual fill price). This is conservative: the trade can't spend more than amount USD even at the worst acceptable price; a better fill means more shares. The result is rounded down to 4 decimal places (the matching engine's share quantum) and capped at the per-trade share limit. For SELL or limit orders, use quantity (shares). Mutually exclusive with quantity — supplying both is a 400 error.

order_type
enum<string>
default:market

Order type

Available options:
market,
limit
price
string | null

For limit orders: the limit price (0.01-0.99, required). For market orders: the worst acceptable price — Polymarket-style slippage protection (required). BUY won't fill above this price; SELL won't fill below it. All market orders are effectively marketable limit orders, matching Polymarket's execution model.

time_in_force
enum<string>
default:GTC

GTC = Good-Til-Cancel (default for limit orders, persists until filled/cancelled), FOK = Fill-Or-Kill (default for market orders — all-or-nothing, matching Polymarket), FAK = Fill-And-Kill (Polymarket term for partial fill, cancel remainder — equivalent to IOC), IOC = Immediate-Or-Cancel (partial fill, cancel remainder), GTD = Good-Til-Date (resting limit auto-expiring at expiration; rolling out — accepted only while ORDER_SEMANTICS_PM_V2_ENABLED is on)

Available options:
GTC,
FOK,
FAK,
IOC,
GTD
client_order_id
string | null

Idempotency key

Maximum string length: 256
expiration
string | null

Unix-seconds expiration timestamp — required for time_in_force=GTD (PM convention: the order auto-cancels once the timestamp passes), ignored for every other TIF. Rolling out behind ORDER_SEMANTICS_PM_V2_ENABLED.

post_only
boolean | null
default:false

Polymarket's postOnly: the order must REST on the book — if it would cross the spread (marketable at placement) it is rejected with 400 INVALID_POST_ONLY_ORDER instead of executing, guaranteeing maker-side execution. Only valid for limit orders with GTC/GTD time-in-force (FOK/FAK/IOC/market combinations are rejected with INVALID_POST_ONLY_ORDER_TYPE, matching PM). Rolling out behind ORDER_SEMANTICS_PM_V2_ENABLED; advisory (ignored) until the flag is on.

wallet_id
integer | null

Multi-wallet (May 8 launch). When set to a SANDBOX wallet the user owns, the trade debits/credits Wallet.balance directly and the resulting Order is tagged with trade_source='ui_sandbox' (excluded from the public leaderboard). When set to a MAIN/API wallet the user owns, the cash flow is routed to that explicit wallet (otherwise we default to API for /v1/orders). Omit for legacy back-compat behaviour: cash flows to the user's API wallet.

Response

Object body → OrderResponse (PolySim single-order) OR OrderAck when the user routes through Order Pipeline V2 (per-user allowlist or global flag — ack-then-reconcile, no fill data in the body; clients poll GET /v1/orders/{order_id} for the post-reconcile fill fields). Array body → List[PmSendOrderResponse] (PM batch, max 15). The OrderAck schema is registered under /v1/orders/{order_id} (DELETE)'s 202 response.

order_id
integer
required
status
string
required
order_type
string
required
side
string
required
outcome
string
required
price
string
required
quantity
string
required
notional
string
required
fee
string
required
filled_at
string | null
cancelled_reason
string | null
price_source
string | null
slippage_bps
integer | null
quote_age_ms
integer | null
spread_bps
integer | null
impact_bps
integer | null
book_walk_levels
integer | null
account_balance
string | null
position
Position · object
client_order_id
string | null
error
string | null
error_message
string | null
amount_interpreted_as
string | null
is_replay
boolean | null
warnings
string[] | null