Endpoint
traded_qty, average_price, fees_paid) — this stream delivers each discrete execution with its true exchange_trade_id, price, qty, fee, maker/taker flag, and counterparty.
Query parameters
Authentication
Browser clients
Browsers cannot set request headers on a WebSocket upgrade, so a first-party web client passes its Supabase JWT in the subprotocol list rather than the URL. Offer two values — the bare marker and the token-bearing one — and the server selects the marker:?access_token= is no longer accepted. Programmatic
clients are unaffected: the signed-handshake params are safe to log, because
sig is bound to the path, query and timestamp and is single-use.
Browsers can’t set custom headers on the WebSocket handshake, so the signed-request
flow moves to query params. The signature covers
WS\nPATH\nSORTED_QUERY (excluding key_id/ts/sig)\nTIMESTAMP.
Signed handshake
subaccount_id — otherwise the connection is closed with code 4401. A missing or malformed subaccount_id is closed with 4400.
Protocol
All frames are JSON. Server frames are bytes (orjson-serialized UTF-8). Client frames are accepted but ignored — there is no subscribe/unsubscribe action; the subaccount is fixed at handshake time. This is a pure live-delta stream — there is no snapshot frame. Backfill history withGET /v1/fills and dedup any overlap against the live stream by the composite fill identity: (exchange_trade_id, exchange_order_id, counterparty_address, counterparty_exchange_order_id). exchange_trade_id alone is not unique — one Polymarket trade produces one fill per matched maker order.
Server → client
connectedis sent immediately after the handshake completes.reconnectis sent during graceful pod shutdown. Reconnect with a small jitter.
Fill payload
Keepalive
Liveness is handled at the WebSocket protocol layer (RFC 6455 PING/PONG control frames). Standard clients (Pythonwebsockets, browser WebSocket) reply to server PINGs automatically — no application-level heartbeat is needed.
Minimal client
Using the SDK (handles signing automatically):msg.exchange_trade_id, msg.qty, …). The subaccount is fixed
at handshake time — there is no subscribe / unsubscribe on this stream;
open one connection per subaccount.
Or signing the handshake manually:
Errors
Recoverable problems arrive as anerror frame followed by a close. code is stable and safe to branch on; message is human-readable.

