Skip to main content
Connect to the authenticated partner door wss://partner-api.bravadotrade.com/stream/polymarket/partner and subscribe to open_orders:all to receive a live, normalized view of one user’s own open Polymarket orders. Bravado maintains the authoritative state for you — an initial REST snapshot merged under Polymarket’s user WebSocket, reconciled automatically after any disconnect — so you integrate against one stream instead of Polymarket’s REST and WebSocket, their auth, their heartbeats and their reconnect logic.
This is private, account-level data. Where the Live Trades and Order Books feeds are market-wide, this one is per-user: the request must resolve to one bound user — see Authentication. It is part of the Market Data product (stream.read scope), and Bravado’s own client never sees the user’s Polymarket credentials.

Authentication

The upgrade is signed with the same HMAC-SHA256 scheme as every other partner request — X-BRAVADO-API-KEY, X-BRAVADO-TIMESTAMP and X-BRAVADO-SIGNATURE over the canonical path, hashing the empty body of the bodyless GET. See Authentication for the signing rules. Because the channel is per-user, the request must resolve to one bound user:
  • A per-user key carries its binding — nothing more is needed.
  • A master key must name the user with an X-Partner-User-Id header (the partner_user_id you provisioned the user under). This header is not part of the signed payload; it travels alongside the signed headers.
Without a bound user the channel answers a typed BINDING_REQUIRED error and does not open a session. (The public book channel on the same door needs no user and is unaffected.)
Authentication runs on the upgrade. A bad credential ends the request as an HTTP status (for example 401) before the WebSocket exists — it is never delivered as a frame.

Connect

Sign the bare partner-door path, pass X-Partner-User-Id for a master key, then subscribe in-band once the socket is open. (You may instead pass ?streams=open_orders:all on the URL; if you do, sign the path with that query.)
The only subscription key today is all — every open order for the account. Market, asset and side filters are a later addition; the open_orders:<…> namespace is reserved for them. open_orders is not an asset and holds no quota, so it does not count against the per-organisation asset limit — a book subscription and open_orders can share one socket.

Frames

Every frame carries channel: "open_orders", venue, seq (ours, monotonic per session — a snapshot resets it) and ts (our clock, in milliseconds). Sizes and prices are exact decimal strings, never JSON numbers — parse them with a decimal-safe type, not a float. An order is removed from active state once its order_closed frame is emitted.

snapshot

order_opened / order_updated

order_closed

reconciled

The normalized order

Status model

The normalized status moves OPEN → PARTIALLY_FILLED → (FILLED | CANCELLED | EXPIRED) and is derived from sizes (filled_size against original_size), never from a venue string — a cancellation event is what sets CANCELLED. The raw venue status always rides along in venue_status, so an unrecognized venue status never silently changes the normalized one, and no venue information is lost.
Polymarket’s own order statuses are live / matched / delayed / unmatched (the last two are sports matching-delay states), spelled both bare (LIVE) and prefixed (ORDER_STATUS_LIVE), case varying — all of which you receive verbatim in venue_status. delayed and unmatched are reported as a size-derived OPEN (an unmatched order is resting on the book, so it is open — we do not guess it cancelled).

size_matched_final

On order_closed, this flags whether filled_size is the final, event-confirmed value. An event-driven close carries true. A close inferred by reconcile — an order that vanished from a fresh snapshot while the upstream was disconnected — carries false, because filled_size is the last value we saw and may be stale. Unknown is labelled, never guessed as zero.

Reconnect and reconcile

The upstream Polymarket connection is managed for you. On an upstream drop the session emits one error with code: "UPSTREAM_DISCONNECTED" (your downstream socket stays open), reconnects with jittered backoff, re-fetches the REST snapshot to completeness, diffs it against local state, emits the resulting order_opened / order_updated / order_closed frames, and closes with one reconciled summary. A periodic reconcile — and a verify reconcile shortly after a subscription goes live — runs even on a healthy connection and always emits reconciled. So a client that stops seeing reconciled frames knows its data may be stale. Reconnect and resubscribe if your own socket drops; you will receive a fresh snapshot. The server pings and closes a connection after missed pings; most WebSocket clients answer automatically.

Error codes

Error frames carry only { code, message } and never expose Polymarket credentials or raw upstream errors.

Coverage

Polymarket only. Predict.fun publishes no order feed of this shape, so open_orders is absent from the Predict.fun channel table and a subscription there answers UNKNOWN_STREAM.

Guarantees

  • No Polymarket credential ever reaches you or a log — the wire shape has no credential field, and upstream identity fields (owner, maker_address) are dropped.
  • No double-counting of fills — filled_size is the venue’s authoritative cumulative; trade events refine fill tracking but never move it.
  • No leak onto a market-wide route — open_orders lives only in the authenticated partner door’s per-user channel table; no public or market-wide route can address it.