Place Order Dispatcher
Authorizations
Issue from /v1/keys (or admin-issued for enterprise tier).
Headers
Your PolySimulator API key
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.
PM-CLOB-compat dashed-form alias for X-API-Key. Same value semantics as POLY_API_KEY but with HTTP-conventional dash separators. Both spellings are accepted end-to-end.
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
- PlaceOrderRequest · object
- PmSendOrderRequest · object[]
Polymarket condition_id
256BUY, SELL Outcome label, e.g., Yes or No
200Number of shares as decimal string, e.g. '10.5'. Required UNLESS amount is provided (BUY market orders only — Polymarket convention).
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
market, limit 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.
GTC = Good-Til-Cancel (default for limit orders, persists until filled/cancelled; on a market order it is replaced by IOC), FOK = Fill-Or-Kill (all-or-nothing: fills only if displayed depth within the limit covers the full size), FAK = Fill-And-Kill (Polymarket term for partial fill, cancel remainder — equivalent to IOC), IOC = Immediate-Or-Cancel (partial fill, cancel remainder; the default for market orders), GTD = Good-Til-Date (limit orders only; resting limit auto-expiring at expiration; live on production, gated by the ORDER_SEMANTICS_PM_V2_ENABLED rollout flag — where that flag is off, GTD is rejected as an invalid value)
GTC, FOK, FAK, IOC, GTD Idempotency key
256Unix-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.
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.
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.
Bot / strategy identifier (MetaTrader 5 style magic number), 0..9223372036854775807. Not unique: every order a bot places can share it, so the bot can later filter GET /v1/orders, export trades and cancel-all with ?magic= without touching other bots on the same account. Omitted: the API key's default_magic applies, if configured.
0 <= x <= 9223372036854776000Optional human-readable bot name shown next to the magic number (max 32 printable characters, trimmed; blank means none), e.g. 'arb-v1'. Omitted: the API key's default_magic_label applies, if configured.
32Response
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.
- OrderResponse · object
- OrderAck · object
- PmSendOrderResponse · object[]
Why a CANCELLED order was cancelled - a stable snake_case machine tag. An order cancelled inside the request that created it (a marketable IOC/FAK that could not fill) reports the no-fill cause, for example 'price_did_not_cross', 'fok_insufficient_depth', 'book_depleted', 'depth_required', 'no_live_price' or 'no_book_price'. An order cancelled while resting on the book reports for example 'gtd_expired', 'stale_market', 'stale_or_mismatched_book' or 'reset'. Null on non-cancelled statuses and on legacy rows, so branch on status to detect cancellation and on this field to learn the cause.