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:CreateComboandGetCombos.polymarket.v1.RFQAPI: RFQ and quote reads/writes plusStreamRFQEvents.
combo.proto and rfq.proto; the retired combos.proto interface is no longer part of the contract.
Maker Startup
- Call
GetRFQUserIDand retain the pseudonymous ID returned for your participant. - Open one
StreamRFQEventsstream withread:orders. - Load open RFQs with
GetRFQs { status: RFQ_STATUS_OPEN }. - Load your quotes with
GetQuotes { user_filter: USER_FILTER_SELF }. - Read ordered legs from
rfq.combo_legs. CallGetComboswhen you need current combo state or tick size, or when a historical RFQ has no leg snapshot.
Maker Flow
Successful acceptance produces bothrfq_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 a0.001tick. - A quantity RFQ uses its
qtyDecimalfor 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
buyQtyDecimalandsellQtyDecimal; use those values rather than recomputing them.
Replace a Quote
Each maker has one deterministic quote ID for an RFQ. CallingCreateQuote 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 fromQUOTE_STATUS_ACTIVE quotes independently for requester buy and sell:
- For requester
SIDE_BUY,buyPriceis the maker’s ask; lower price wins. - For requester
SIDE_SELL,sellPriceis the maker’s bid; higher price wins. - Equal prices use the earlier
createdTime. - An exact tie uses the lexicographically smaller
quoteId.
Last Look and Execution
When a requester accepts one side:- The RFQ becomes
RFQ_STATUS_CLOSED, and publicrfq_closedis emitted. - The selected quote becomes
QUOTE_STATUS_ACCEPTED. - The selected maker receives private
quote_acceptedwith the authoritativeconfirmationDeadline. - The maker calls
ConfirmQuoteto trade orDeleteQuoteto decline before the deadline. - Confirmation changes the quote to
QUOTE_STATUS_CONFIRMEDand emitsquote_confirmedwithexecutionDeadline. - Paired orders are submitted maker first, then requester.
- Successful paired submission changes the quote to
QUOTE_STATUS_EXECUTEDand emits participant-privatequote_executedevents with the durable Quote state embedded.
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
UseGetQuotes 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. ReserveGetRFQs and GetQuotes for startup, recovery, and targeted reconciliation. See Rate Limits for current per-firm limits.
Related Documentation
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