Skip to main content
Notable changes to the Polymarket Perps API.
OI reward eligibility threshold increased to $5M
The OI reward eligibility threshold is now 5MofcombineddailyaveragegrossOIperrewardsentity,upfrom5M of combined daily average gross OI per rewards entity, up from 1M. Accounts without an entity mapping qualify independently. The 6% APR rate and calculation on the account’s full daily average gross OI across all instruments are unchanged.
Concurrent WebSocket posts and HTTP overload shedding
Concurrent WebSocket posts and HTTP overload shedding. No breaking changes.Added
  • Concurrent WebSocket posts (MM gateway). Up to 16 signed writes per connection now run concurrently. Posts touching the same order, by client order id or engine order id, still reach the engine in send order. cancelAll and leverage or margin updates act as barriers. Responses can arrive out of order across different orders: send a unique id and match on it. Ordering is per connection.
  • HTTP overload shedding. Requests over the server or per-IP concurrency limit are shed before execution: 503, {"status":"err","error":"service_unavailable"}, with Retry-After. Batch routes return a one-element array. The request did not execute, so retry with backoff. The per-IP cap is 128 in-flight on the MM API against healthy usage under 10. Tell us if you NAT many bots through one IP.
Changed
  • Cancel by client order id. A recently completed order now returns order_already_terminal, not order_unknown. A cancel racing its own order’s creation waits briefly (~1ms, capped at 150ms) and succeeds instead of answering order_unknown. TP/SL coids are unchanged.
  • Funding. Funding for a just-closed window now settles even if you flattened or flipped just before settlement was sequenced; previously the window could be skipped for the whole instrument. Drop any assumption that a closed position means no funding.
  • Reduce-only market closes. These now fill only within the price band around the last mark. Expect partial fills or ioc_no_fill on a dislocated book. Quotes resting far outside the band will no longer be hit by them.
  • Balances. REST value is now the USD equivalent at the asset’s index price, not the raw amount: same for pUSD, different for other collateral. balance uses asset-native decimals, matching WebSocket.
  • 429 shape on modify routes. PATCH /v1/trade/orders and PATCH /v1/trade/orders-coid return the one-element array instead of a bare object.
  • Idle connections. HTTP connections with no complete header for 120s are closed. A per-pod ceiling resets excess connections rather than serving a 503.
Fixed
  • Deposits. Many-per-transaction deposits credit reliably; a batching edge case could previously delay or drop credits.
  • Price continuity. The index survives a full outage of one oracle source, with marks, margin, and funding still updating. Don’t assume prices freeze when a provider goes down.
  • Referrals. Concurrent binds for one account resolve to one winner; the loser gets HTTP 400, account already has a referrer.
Not Yet Active
  • Pending-modify expiry. A modify left risk-undecided for 200ms will be swept: the order stays open and you retry with a new modify_id. We’ll notify before enabling.
  • Per-account rate-limit tiers. Still inactive. We’ll notify before activation.
RolloutThe public gateway fleet moves to dedicated hardware during this window. WebSocket connections drop once; standard reconnects cover it.
Response timestamps, rejection references, and liquidation metadata
Rejections and acknowledgements now carry inspectable timing, every WebSocket push is stamped with engine event time, and backstop liquidation fills include optional metadata.Added
  • Timestamps on rejections. All rejection responses — orders, cancels, modifies, withdrawals, and transfers — now include ts (engine decision time), arts (gateway arrival time), and ref (a support reference for locating the server-side trace). All three are nullable, except on cancel rejections where ts is always present.
  • Timestamps on acknowledgements. Accepted create-order items now include ts and arts. Accepted cancels, which already carried ts, now also include arts.
  • Event time on every WebSocket push. Push envelopes across all channels now carry ets, the engine event time for the update. This field is always present and is the one to use for event-time analysis.
  • Liquidation metadata on fills. Fills and trades from backstop liquidations carry an optional liquidation_details object with mark, method, and liquidated_user. Available on private WebSocket fills, GET /v1/account/fills, position fills, and public trades. The anonymous trade tape omits liquidated_user. Ordinary order-book liquidations do not carry this object yet — only backstop liquidations, where method is backstop. The object is absent where metadata was not captured.
Changed
  • WebSocket envelope ts is now server send time. Push frames previously stamped the envelope ts with internal stream time, which could lag actual send time on quiet channels or during catch-up. Engine event time is now carried separately in ets. Per-item ts inside data is unchanged. If you measure latency as local_receive − envelope_ts, your values will decrease after this release. Earlier measurements included server-internal lag and are not comparable — re-baseline at the deploy timestamp.
  • Backstop liquidations publish fills to both parties. The liquidated account and each absorbing account now receive private WebSocket fills for backstop liquidations. The liquidated account previously received no fills event. These fills are system-generated, with order id 0 and no client order id, matching the shape of ADL fills.
  • order_already_terminal replaces order_not_in_orderbook for terminal orders. Canceling an order that has already filled or canceled now returns order_already_terminal to the order’s owner. Unknown and foreign order ids continue to return order_not_in_orderbook. Treat unrecognized error codes as non-retryable.
Fixed
  • FillsUpdate.data and TradesUpdate.data are documented as arrays. The specification previously described objects. The wire format is unchanged; regenerate your client/bindings if you generated the object form.
Current position fills endpoint added
Added GET /v1/info/position-fills, a public endpoint returning every fill in a registered account’s current open position cycle for one instrument. A cycle begins when the position opens from flat or flips direction, and a multi-leg flip stays in one cycle. Pages of up to 100 fills are linked by an opaque cursor returned alongside the data; the cursor is validated against the live position on every page and returns 400 if the position changed mid-pagination. GET /v1/account/fills has returned the same opaque cursor field since Jul 24 — passing the last fill’s trade ID as cursor still works there.
Equity and PnL history honour the requested interval
GET /v1/account/equity and GET /v1/account/pnl now bucket the returned series by the interval query parameter. Previously the parameter was validated but ignored: every accepted value returned the same fixed-granularity series (per minute for equity, per hour for PnL), and long windows were truncated at 1000 rows instead of aggregated. Each equity point is now the last sample in its interval bucket; each PnL point is the PnL realized inside its bucket — not a running total — and empty buckets are omitted. Buckets are aligned to the Unix epoch, points keep real sample timestamps, and the 1000-entry cap now counts buckets, so a coarser interval covers a longer window before more is set. Responses for the finest intervals (1m equity, 1h PnL) are unchanged.
Deposit and withdrawal history amounts are always decimal token units
GET /v1/account/deposits and GET /v1/account/withdrawals now serialize every amount (and withdrawal fee) in decimal token units, e.g. "10" for 10 pUSD. Previously, deposit rows in pending or removed status reported raw on-chain base units ("10000000" for the same 10 pUSD), and pending withdrawal rows could serve base-unit amounts and fees as well, so rows for the same transfer disagreed on units across statuses. Clients that divided pending amounts by 10^decimals to compensate must drop that conversion. Confirmed rows and the WebSocket deposits and withdrawals channels are unchanged — they were already decimal. Signed operation inputs (POST /v1/account/withdraw) still take base-unit amounts matching the EIP-712 signature.
Fill history flags maker fills executed under liquidation
GET /v1/account/fills and account trade history previously reported liquidation: false on every maker fill, even when the maker’s own account was under liquidation on the instrument — while the WebSocket fills channel already reported liq: true for the same fill. The two surfaces now agree: any maker or taker fill on an instrument in the account’s active liquidation scope reports liquidation: true. Rows written before the change are unaffected. Such maker legs are also excluded from leaderboard win counts.
Fills gain an adl flag; liq no longer set on ADL counterparty legs
Fill entries now carry a required boolean adl field on both the WebSocket fills channel and GET /v1/account/fills, set on both legs of an auto-deleveraging match. Behavior change: the counterparty leg of an ADL match previously reported liq: true on the WebSocket fills channel; it now reports liq: false. liq marks only the leg whose own position is being liquidated. Clients that detect forced closes via liq alone will no longer see ADL counterparty fills — check adl as well.
Position deleveraged notification added
Added the position_deleveraged notification, sent to the counterparty of an auto-deleveraging match when its profitable position is closed or reduced to settle a liquidation on the other side. Delivered on the WebSocket notifications channel and in the notifications history.
Exchange info reports engine version and cancel-only state
GET /v1/info/exchange now includes engine_version, the engine release version of the build serving the response. The response also documents cancel_only, which reports whether the exchange is in cancel-only (maintenance) mode; the flag has been returned since maintenance mode shipped on Jul 15.
Portfolio margin summary includes available order margin
The portfolio response and portfolio WebSocket channel now include margin.available_order_margin: the collateral available for additional order initial margin after existing exposure, open orders, orders and isolated-margin additions awaiting risk processing, and pending withdrawals or transfers.
Cancel all orders added
Added DELETE /v1/trade/orders/all to cancel all open orders in one request, optionally scoped to a single instrument. Available in the SDKs as cancelAllOrders (TypeScript) and cancel_all_orders (Python).
Cancel responses include order IDs
Cancel responses now include oid and coid fields.
Taker delay added for immediately matching orders
Added a 20ms taker delay for orders that immediately match on entry.
Reduce-only orders added
Added the reduce-only field to order submission and order updates.
Auto-cancel and rate-limit updates
  • Added PATCH /v1/trade/auto-cancel to arm or clear a dead man’s switch that cancels all open orders at a specified time.
  • Added GET /v1/account/auto-cancel to check the current auto-cancel status, trigger count, and daily reset time.
  • Auto-cancel is limited to 1000 triggers per UTC day per account.
  • Added updateLeverage and autoCancel WebSocket post messages.
  • portfolio and balances WebSocket channels no longer push updates on every order or fill, only periodically.
  • Rate limit error messages now distinguish between ip_rate_limited, action_rate_limited, and message_rate_limited.