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_tokenonly 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.
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 samepolymarket.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.
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 required by the safe-sweep precondition: confirm the released amount here before creating a sweep.
Stream it instead
- Apply
CreateBalanceLedgerSubscriptionentries (before_balance/after_balance) to your projection as they arrive. - Reserve
GetAccountBalance/ListAccountBalancesfor a true first-time cold start and the safe-sweep confirmation above. - On an ordinary restart, resume from the last
update_timeyou 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
- Call
ListAccountPositionsto 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_tokenand 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
- Open with the default
snapshot_only: false; the first message carries asnapshotof every currently-open order, thenupdatemessages 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/GetOrderfor 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_tokenand no snapshot — hydrate firm-wide historical fills once viaSearchExecutions/SearchTradeson 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.
Stream it instead
- Use
GetAccountBalanceLedgeronly for paginated historical lookups and CSV exports, not as a live feed. - Persist the
update_timeof the last applied entry and pass it back asresume_timeon reconnect — a restart resumes the stream from that point, it does not re-run history from the beginning.
Joining orders to funding. For funded orders,
clord_id equals the funding_request_id returned by CreateFundedOrder — and SearchOrders filters by clord_id directly. Keep the exchange order_id as the canonical venue identifier, and persist the create response’s correlation fields so ledger rows, stream events, and sweeps all join cleanly.Related pages
Settlement Sweeps
The planned 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.