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.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.
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 towss://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
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.
Related
- Trade API — order execution; redeem settled positions via
POST /v2/trade/positions/redeem - Trader Data API — wallet PnL, trade logs, and tax statements
- Market Data — realtime trades and order books over WebSockets
- Polymarket — market coverage and supported features