Skip to main content
Your integration maintains a local projection of each participant’s orders, positions, and cash. This page describes the operating pattern that keeps that projection correct, and the read APIs that anchor it to authoritative state.

The operating pattern

Streams are the system of record; reads are anchors. The firm-scoped Drop Copy execution and position streams drive your projection in real time. Unary reads exist for discovery, user-driven views, and reconciliation — they are not polling feeds.
  • Replay before new work. Persist a stream response’s resume_token only after every record in it is durably applied. Reconnect with the last committed token; deduplicate replayed events by stable exchange IDs.
  • Single active subscriber. Run one leader-elected consumer per firm, environment, and stream. Followers take over from the durable cursor — never one subscription per pod, and never one stream per customer.
  • Reconcile after gaps. After an outage: resume and replay the streams first, then compare your projections against the reads below, and surface freshness caveats rather than presenting incomplete state as final.
  • No cron pollers. Reads are triggered by onboarding, user views, bounded workflow recovery, reconnect reconciliation, or an incident — not recurring schedules.
A process restart is not a cold start. Resume from your persisted checkpoint against your existing local database — don’t re-run the unary reads below.
“Cold start” means true first contact for a firm/account/environment your integration has never seen before — no persisted resume_token or resume_time, and no local projection to reconcile against. If you already persist your checkpoint, a restart just reconnects with it and keeps applying deltas to the state you already have, deduplicating anything replayed. Only a genuine no-checkpoint start (or a checkpoint too old to resume) falls back to the reads below.

Reconciliation reads

The anchors are the standard gRPC read APIs — the same polymarket.v1 services documented under Institutional API, called with your partner credentials over TLS with a Bearer token. Full message definitions are in the proto download; the tables below map each reconciliation concern to its RPC.
These are low-volume anchors, not a data-access layer. Every RPC below is rate-limited per firm and must not be polled.
The correct architecture is stream-first: build your local database from Drop Copy and Order Stream, serve reads from that database, and call these RPCs only for cold-start hydration, point-in-time queries, and gap recovery — never as a substitute for a subscription. See Rate Limits for the full list; SearchOrders, SearchExecutions, and SearchTrades, for example, are capped at 12 requests/minute, and sustained call volume against any of these endpoints will get throttled.

Cash balances — polymarket.v1.PositionAPI

An account balance is the authoritative cash figure for one account and currency, plus the risk context used to size orders — see Balance Data for the full field reference. This balance read is the authoritative confirmation to take before initiating a WITHDRAWAL transfer — confirm the participant’s free cash covers the amount (net of accrued vendor fees) before creating the transfer.

Stream it instead

Streaming equivalent: no dedicated balance-push stream exists — derive live balances from Balance Ledger deltas instead of polling this RPC.
  • Apply CreateBalanceLedgerSubscription entries (before_balance / after_balance) to your projection as they arrive.
  • Reserve GetAccountBalance / ListAccountBalances for a true first-time cold start and the pre-withdrawal confirmation above.
  • On an ordinary restart, resume from the last update_time you persisted and keep applying deltas to the balance you already have — don’t re-fetch it.

Positions — polymarket.v1.PositionAPI

A position tracks net quantity, cost basis, and realized P&L for one account and symbol — see Position Data for the full field reference.

Stream it instead

Streaming equivalent: CreatePositionChangeSubscription on the Drop Copy stream keeps positions current in real time.
  • Call ListAccountPositions to hydrate a brand-new projection (true cold start) or to answer point-in-time (as_of_time / as_of_date) queries a stream can’t answer — not on every process restart.
  • A restarting service persists its position projection alongside the stream’s resume_token and reconnects with that token; a routine restart is never a reason to re-fetch positions.

Orders — polymarket.v1.ReportAPI

An order carries its full lifecycle state — quantity, price, fills, and status — see Order Message Structure for the full field reference (the same fields these reads return).

Stream it instead

Streaming equivalent: CreateOrderSubscription on the Order Stream is snapshot and stream on one connection — no unary call is needed for cold start.
  • Open with the default snapshot_only: false; the first message carries a snapshot of every currently-open order, then update messages push executions continuously.
  • This request carries no resume_token, so a restart simply reconnects and gets a fresh snapshot for free — there’s no checkpoint to persist for this one.
  • Reserve SearchOrders / GetOrder for one-off lookups the live snapshot doesn’t cover (e.g. a specific historical/closed order by ID).
  • Drop Copy’s execution and Trade Capture Report subscriptions, by contrast, carry a resume_token and no snapshot — hydrate firm-wide historical fills once via SearchExecutions / SearchTrades on true cold start, then resume the stream with the persisted token on every subsequent restart instead of re-querying.

Cash ledger — polymarket.v1.FundingAPI

A ledger entry records a single cash-balance change with its before/after amounts — see BalanceLedgerEntry Fields for the full field reference. The cash ledger is where every transfer (deposits, withdrawals, vendor fee collections), fill, exchange fee, and settlement credit lands with before/after balances — it is the platform-side record your funding entity’s books reconcile against, per account.

Stream it instead

Streaming equivalent: CreateBalanceLedgerSubscription is the streaming equivalent here — it replays from resume_time and then pushes new entries live.
  • Use GetAccountBalanceLedger only for paginated historical lookups and CSV exports, not as a live feed.
  • Persist the update_time of the last applied entry and pass it back as resume_time on reconnect — a restart resumes the stream from that point, it does not re-run history from the beginning.

Firm-wide ledger consumption

The ledger subscription is per-account — one fully-qualified account per stream — and concurrent ledger streams per firm are tightly capped. Opening one stream per customer does not scale and is not the intended pattern.
COMING SOON — firm-wide balance ledger subscription. A firm-scoped subscription that delivers ledger entries for all accounts under your Firm on a single stream — with the same resume_time replay semantics and entry.account on every row for routing — is planned. The final consumption pattern will be documented when it ships; contact institutional@polymarket.us if your rollout depends on it.
Until then, cover the firm-wide need with the surfaces that are already firm-scoped:
  • Executions and positions: the Drop Copy streams are firm-wide — one execution stream and one position stream cover every account’s trading activity.
  • Cash events: drive per-account cash projections from your own transfer records (you initiate every deposit, withdrawal, and fee collection) plus firm-wide execution data, and reconcile against GetAccountBalanceLedger / CSV export per account on a batch cadence — not with per-account live streams.
Decoding fees on fills. Commission fields on execution reports are fixed-point notional units, scaled by both price_scale and fractional_quantity_scale — see Fees on execution reports before reconciling fill-level fees against the fee schedule.
Joining orders to fees and funding. For orders placed through the partner order API, the clord_id on execution streams is the partner-assigned order.clord_id from CreateVendorOrder, and the execution account is the same DCM identifier supplied as order.account. SearchOrders filters by clord_id directly. Keep the exchange order_id as the canonical venue identifier: it and your clord_id are the join keys on the Vendor Fees report. Persist the create response’s correlation fields so ledger rows, stream events, fee records, and transfers all join cleanly.

Transfers

The cash-movement API these reads gate.

Drop Copy Stream

The firm-scoped execution stream that drives your projection.

Order Stream

Real-time order and execution updates for your accounts.

Rate Limits

Per-endpoint limits for the reads on this page.