Skip to main content
Polymarket markets do not settle themselves. When a market’s event concludes, the outcome has to be reported on-chain and accepted before holders can redeem winning shares. Polymarket uses UMA’s Optimistic Oracle (V2) for that step, and the Bravado UMA API exposes the resolution lifecycle as both queryable data (REST) and a realtime stream (WebSocket).
The UMA REST endpoints and stream are served from partner-api.bravadotrade.com, the same host as the rest of the Bravado API. Requests require an active paid plan, a WebSockets API key with stream.read, and HMAC authentication. Coverage today is Polymarket.

Why Bravado over reading the chain

Resolution data exists on-chain, so this is not about access. It is about not having to build an indexer to answer a question every prediction market application eventually has to answer: is this position actually finished? The practical payoff is that a “concluded” event and a redeemable position stop being the same thing in your data model. An application that conflates them will show users balances they cannot access, and book PnL that has not been realised.

How UMA resolution works

Bravado decodes UMA’s Optimistic Oracle V2 directly, so you see each step as it happens.
1

Proposal

Once the event concludes, a proposer posts the outcome to the oracle with a bond. This is the proposed stage; answer carries the proposed result. Bravado decodes the proposer’s transaction straight from the mempool, so the proposal is delivered with "seen_pending":true ~0.3–1.4 s before it is mined, then a confirming frame follows with the block and tx.
2

Challenge window

The proposal stays open for a fixed liveness period. If nobody disputes it, it settles automatically on the proposed answer.
3

Dispute (optional)

Any party may dispute within the window by posting their own bond (disputed stage). A disputed request escalates to UMA’s token-holder vote rather than settling on the proposer’s word.
4

Settlement

The final answer is written on-chain (settled stage, with the payout). Winning outcome tokens become redeemable at $1; losing tokens go to $0.
A market whose event has visibly concluded is not necessarily settled. Always confirm settled: true before treating a position as realized — an undisputed proposal can still be disputed until its challenge window closes.

Identifiers

Every lifecycle record carries two ids:
  • question_id — keccak256(ancillaryData), the UMA adapter’s question id. This is the stable, exact key for a resolution.
  • condition_id — the CTF condition id used everywhere else in Bravado to identify the market. Use it to join resolution state to positions and trades.
The answer field classifies the oracle’s int256 price: yes, no, 50-50, too-early, or other; price_raw preserves the exact value.

REST — query resolution state

Base URL: https://partner-api.bravadotrade.com. Sign every REST request with HMAC, including its sorted query parameters. JSON; ids are hex, payout is an integer micro-USDC string.

GET /uma/question

The full lifecycle of one question.
string
required
The 0x 32-byte question_id.
string
Hex question id (keccak256(ancillaryData)).
string
Hex CTF condition id for the market.
string
Human-readable market question (from the ancillary data).
string
Latest answer: yes · no · 50-50 · too-early · other.
boolean
Whether the resolution has finalized on-chain.
object
object
Same shape as proposed, plus disputer. Present only if the proposal was disputed.
object
Same shape, plus payout (micro-USDC string). Present once settled.
integer
When Bravado last updated this record (unix ms).
Example response

GET /uma/market

The same record, keyed by the market’s CTF condition id.
string
required
The 0x 32-byte CTF condition id.

GET /uma/recent

Recently-updated questions, newest first — a feed of live proposals, disputes, and settlements.
string
Filter by current stage: proposed · disputed · settled. Omit for all.
integer
default:"100"
Max records (1–500).
array
Array of question records (same shape as GET /uma/question).
integer
Number of records returned.

WebSocket — stream the lifecycle

For push instead of poll, connect to wss://partner-api.bravadotrade.com/uma/ws. Authenticate the upgrade with HMAC. No subscription message is needed — every Polymarket proposal, dispute, and settlement is pushed to you as a uma frame. To follow a single market, filter on question_id (or condition_id) client-side.
Node.js
For browser clients, have your server sign GET /uma/ticket and return the ticket only to an authorised user. Connect to /uma/ws?ticket=.... Tickets expire after 60 seconds and can be redeemed once. Each reconnect needs a new ticket. Never put the API secret in browser code. The Console playground handles this flow. Successful REST reads cost one credit. Stream payloads use the authenticated WebSocket credit model. Missing credentials are rejected; the Free plan cannot access UMA. A pending proposal is not a final settlement. The uma frame carries stage, answer, question_id, condition_id, proposer, disputer, price_raw, payout, request_ts, title, block, tx, and log_index. A proposal or dispute decoded from the mempool carries "seen_pending":true with block:0; the same question_id is re-sent once mined with the real block/tx (the pending→mined pair). Settlements are mined-only and never carry seen_pending.