Skip to main content
REST and gRPC unary calls are supported. RFQ events are gRPC-only. FIX support is coming later.
A combo is an instrument with 2–10 component legs. Each leg contains an existing market symbol and a buy or sell side. Combo instruments trade through normal order entry, but most combo price discovery starts with a request for quote (RFQ). This guide covers the market-maker workflow. The public contract is split between:
  • polymarket.v1.ComboAPI: CreateCombo and GetCombos.
  • polymarket.v1.RFQAPI: RFQ and quote reads/writes plus StreamRFQEvents.
Download the current proto bundle. Use combo.proto and rfq.proto; the retired combos.proto interface is no longer part of the contract.

Maker Startup

  1. Call GetRFQUserID and retain the pseudonymous ID returned for your participant.
  2. Open one StreamRFQEvents stream with read:orders.
  3. Load open RFQs with GetRFQs { status: RFQ_STATUS_OPEN }.
  4. Load your quotes with GetQuotes { user_filter: USER_FILTER_SELF }.
  5. Read ordered legs from rfq.combo_legs. Call GetCombos when you need current combo state or tick size, or when a historical RFQ has no leg snapshot.
The stream is live and best-effort. It does not replay missed events or guarantee gap-free handoff, ordering, or deduplication. Repeat the durable reads after every reconnect.

Maker Flow

Successful acceptance produces both rfq_closed and quote_accepted. A maker may receive public rfq_closed first. Stop creating or replacing quotes for that RFQ, but do not discard existing quote state. The selected maker then receives private quote_accepted, which starts last look. Confirm or delete the selected quote before its confirmationDeadline. quote_confirmed means paired order submission is scheduled; quote_executed means both exchange orders were accepted for submission. Use Drop Copy as the source of truth for fills.

Read an RFQ

An RFQ supplies either a contract quantity or a cash notional:
Each combo leg contains its symbol, combo side, and optional settlementPrice. Settlement is the raw YES/LONG result normalized to [0,1]; do not invert it for SIDE_SELL. A present "0" is a valid settlement and differs from an absent field. Exact and list reads hydrate the latest available settlements, while rfq_created contains those available when the event was published. Historical RFQs can have no inline legs. Use GetCombos { symbol: rfq.symbol } as the fallback and whenever you need current combo metadata. An RFQ still has no requested side, expiration time, or client request ID.

Construct a Quote

CreateQuote is dual-sided:
Do not send a side, symbol, quantity, expiration, or client request ID. The API obtains the symbol and sizing from the RFQ.

Price and Quantity Rules

  • Each positive price must be within the instrument’s price limits and land on its tickSize. Current combo instruments use a 0.001 tick.
  • A quantity RFQ uses its qtyDecimal for each offered side.
  • A cash RFQ derives each side independently as floor(cashOrderQty / sidePrice) at the instrument’s fractional quantity scale.
  • A derived quantity must meet the instrument minimum. A positive price can therefore be invalid even when the other side is valid.
  • The persisted quote reports the derived buyQtyDecimal and sellQtyDecimal; use those values rather than recomputing them.

Replace a Quote

Each maker has one deterministic quote ID for an RFQ. Calling CreateQuote again replaces the existing quote’s economics, resets its status to QUOTE_STATUS_ACTIVE, preserves its quoteId, and emits another quote_created event. Treat replacement as a state update, not a second live quote.

Quote Selection

The RFQ Engine considers positive prices from QUOTE_STATUS_ACTIVE quotes independently for requester buy and sell:
  1. For requester SIDE_BUY, buyPrice is the maker’s ask; lower price wins.
  2. For requester SIDE_SELL, sellPrice is the maker’s bid; higher price wins.
  3. Equal prices use the earlier createdTime.
  4. An exact tie uses the lexicographically smaller quoteId.
A two-sided quote may win both sides; different quotes may win each side.

Last Look and Execution

When a requester accepts one side:
  1. The RFQ becomes RFQ_STATUS_CLOSED, and public rfq_closed is emitted.
  2. The selected quote becomes QUOTE_STATUS_ACCEPTED.
  3. The selected maker receives private quote_accepted with the authoritative confirmationDeadline.
  4. The maker calls ConfirmQuote to trade or DeleteQuote to decline before the deadline.
  5. Confirmation changes the quote to QUOTE_STATUS_CONFIRMED and emits quote_confirmed with executionDeadline.
  6. Paired orders are submitted maker first, then requester.
  7. Successful paired submission changes the quote to QUOTE_STATUS_EXECUTED and emits participant-private quote_executed events with the durable Quote state embedded.
The requester’s canonical side determines the selected economics: The durable Quote returned by GetQuotes and embedded in stream events records: Both the requester and quoter can see both exchange order IDs. Client order IDs are not stored on the public Quote. Existing recipient-specific stream wrapper fields remain available for compatibility. Current pre-production timing is: These durations are configuration, not client-side timers. Use the deadlines on durable Quote state; existing event wrapper deadlines remain available for compatibility.

Stream Visibility

There are no expiration, done-away, pending-risk, pending-end-trade, action-rejected, or status-rejected events in the current public stream.

Recovery Reads

Use GetQuotes according to the visibility you need: Use opaque cursors only with the same participant, query path, and filters. If a write returns an unknown result because the connection fails, read the exact RFQ or quote before deciding whether to act again. GetQuotes is the durable recovery path when a stream event is missed. It returns the current execution timestamps and, once available, both the requester’s rfqCreatorOrderId and the quoter’s creatorOrderId to either participant.

Rate Limits

Use the stream for live state. Reserve GetRFQs and GetQuotes for startup, recovery, and targeted reconciliation. See Rate Limits for current per-firm limits.

RFQ API

Complete RFQ and quote REST and unary gRPC contract

Combos API

Combo instrument REST and unary gRPC contract

RFQ Events Stream

Event payloads and Python example

Drop Copy

Exchange order and fill reconciliation

Positions and Risk

Position and balance monitoring