Skip to main content
This guide shows market makers how to handle Combo RFQs. You will open a quoting session, respond to incoming requests, cancel submitted quotes when needed, confirm fills through Last Look, and monitor execution updates.
For development updates on market making for Combos, join the Combos market maker Telegram group.

Start Quoting

Start by preparing an authenticated quoting session with the RFQ system. You need a Polymarket account; create one at polymarket.com.
1

Install the Package

Install the Unified TypeScript SDK with the package manager of your choice.
This page uses Viem for wallet signing. See the TypeScript tooling guide for other wallet library integrations.
2

Create a Secure Client

Create an instance of SecureClient with a wallet that has funds for fulfilling user requests and its signer details.
The Relayer API key is necessary for setting up trading approvals in the next step. Create a Relayer API key from polymarket.com → Settings → API Keys.
3

Set Up Trading Approvals

Set up the approvals required to fill user requests.
4

Open an RFQ Session

Open the RFQ session.
5

Close the Session

You can close the session at any time by calling session.close().

Handle Quote Requests

Quote requests describe a user’s intent to buy or sell shares in a Combo defined by a given set of legs. A quote request can currently only buy or sell the YES side of a Combo. The following cases show how a market maker can satisfy a user’s buy or sell request using collateral or inventory. See Combinatorial Positions for more detail on the YES/NO position model. The diagram below shows the maker-side quote lifecycle, from receiving a quote request through its terminal outcome.

Authorize the Quote

Authorize each quote by pricing the request and returning a signed order to the RFQ system. Quoters should respond within the 400 ms submission window.
1

Switch on Event Type

First, switch on event.type to handle quote requests from the session stream.
2

Evaluate Request

Then, inspect the RfqQuoteRequestEvent before pricing it.requestedSize is an RfqRequestedSize value that describes how the user sized the request.
Where:
  • notional: the target value of the request in collateral currency. For example, "3" means the user wants roughly 3 pUSD worth of the Combo, with the resulting share size derived from the quote price. notional is always and only used by BUY requests.
  • shares: the target number of Combo outcome tokens. For example, "10" means the user wants 10 shares, or 10,000,000 base units. shares is always and only used by SELL requests.
In both cases, value is a normalized decimal string.
3

Submission

Finally, handle pricing, quote submission, and persistence outside the session loop before the event.submissionDeadline deadline. Price the request as pUSD per YES Combo share; for example, 0.45 means 0.45 pUSD per share. If you do not want to quote the request, skip submission.

Quote Partial Fills

If you only want to fill part of the requested size, pass size with the quote. size is a normalized decimal value: "10" means 10 shares, or 10,000,000 base units. When omitted, the SDK quotes the full requested size.

Use Inventory

By default, quotes use collateral (pUSD) to buy YES or NO tokens as needed to satisfy the quote request according to the combinatorial position logic. Pass source: "inventory" when you want to quote from existing inventory instead.

Cancel Quotes

After you submit a quote, keep the returned quote reference. If your price, inventory, or risk changes before the quote is selected, use that reference to request cancellation.
A cancellation acknowledgement means the RFQ system processed the cancellation request. It does not guarantee the quote was withdrawn from an RFQ that was already selected.
1

Store the Quote Reference

First, keep the quote reference returned by event.quote(…). It contains the rfqId and quoteId needed to cancel the quote.
2

Cancel the Quote

Then, pass that reference to session.cancelQuote(…) on the same live RFQ session.

Last Look

Last Look is a separate final review step for makers that have it enabled. If a selected quote requires Last Look, run a final risk check before the deadline and accept or reject the fill. Last Look is offered to makers with approximately $2,500 in Combo notional volume and an established line of communication with Polymarket. This keeps the program reliable and helps Polymarket resolve system issues quickly. To request access, complete the Last Look request form.
Makers are expected to accept most selected quotes. We track acceptance rates, and makers who reject more than 15% of selected quotes over a one-hour lookback window may be paused from quoting for a few minutes.
Once access is enabled, your quoting system will immediately be asked to review selected fills. Make sure it is ready to evaluate and answer them before approval is activated.
1

Switch on the Event Type

First, switch on event.type to handle confirmation requests from the same session stream.
2

Inspect the Confirmation Request

Then, inspect the confirmation request before running your final risk check. It includes the selected quote, the final fill size, and the event.confirmBy deadline for your Last Look response.
3

Confirm or Decline

Finally, run your final risk check outside the session loop and respond before the event.confirmBy deadline.

Manage Combo Positions

Use Combo position workflows to manage inventory throughout the quote lifecycle.

List Combo Positions

List Combo positions as part of your background inventory sync. Keep this state fresh outside the quote path.
Default listings omit open positions with a share balance below 0.001, such as dust left after a sell-all cashout. Resolved positions are always returned, and incremental sync requests return every position regardless of balance.
Use client.listComboPositions(...) to page through Combo positions for the authenticated account.
You can filter positions by the following criteria. conditionId accepts one Combo condition ID or an array of Combo condition IDs.
Each returned item is a ComboPosition.
For redeemed positions, shares and entryCostUsdc track remaining inventory, so both can read as zero after a winning Combo is redeemed. Use realizedPayoutUsdc for gross redemption proceeds and totalCostUsdc for original cost basis; net result is realizedPayoutUsdc - totalCostUsdc.

List Combo Activity

Use Combo activity when you need an audit trail for inventory-changing events, including splits, merges, conversions, wraps, unwraps, and redeems. Use Combo positions for current inventory state.
Use client.listComboActivity(...) to page through Combo lifecycle activity for the authenticated account.
Filter to one or more Combos with conditionId.
Each returned item is a discriminated ComboActivity union. All lifecycle rows share the base fields; redeem rows also include the redeemed position ID and payout.

Inventory Management

If you want to quote from inventory, build the inventory before quote requests arrive. Splitting converts collateral into complementary Combo positions for a set of legs. Merging converts matching complementary Combo positions back into collateral.
Use client.splitPosition(...) with legs to create Combo inventory from collateral. amount is in pUSD base units.
Use client.mergePositions(...) with the same legs to merge complementary Combo positions back into collateral. Pass amount: "max" to merge the largest matching amount available.

Redeem Resolved Positions

When a Combo position resolves, redeem the winning position to settle it back to collateral.
Use client.redeemPositions(...) with a Combo positionId. The SDK redeems the available balance for that resolved position.
You can list resolved winning positions first, then redeem each one.

Get Combo Markets

Use the Combo markets catalog to retrieve active markets that can be used as Combo legs. Markets are ordered by volume descending.
Use client.listComboMarkets(...) to page through markets that can be used as Combo legs.
Use exclude to omit markets you have already shown or selected.
The SDK returns structured YES and NO outcomes.

Map Legs to Markets

Market makers should build their own view of the markets that support Combos before quote requests arrive. Combo-enabled markets expose a list of position IDs with two entries: the first is the YES position ID and the second is the NO position ID. These IDs identify the outcome positions your pricing system can map back to market data.
Fetch non-closed markets and index them by position ID in your own market data store.
You can also fetch markets by leg position ID on demand, but most market makers will want this context ready before the 400 ms quote window starts.

Listen to Execution Updates

Execution updates tell you what happened after one of your quotes was selected. Use them to reconcile RFQ state, transaction hashes, and terminal execution outcomes in your own systems.
1

Switch on the Event Type

First, switch on event.type to handle execution updates from the same session stream.
2

Inspect the Execution Update

Then, inspect the execution update before reconciling the selected RFQ. Execution updates are correlated by rfqId.
where RfqExecutionStatus could be:
3

Reconcile Execution State

Finally, persist the update and treat RfqExecutionStatus.Confirmed and RfqExecutionStatus.Failed as terminal states.

Listen to Trade Broadcasts

Confirmed trade broadcasts tell connected market makers when any Combo RFQ trade has completed successfully. Use them to build a public trade tape, update risk, or reconcile market activity that was filled by another maker. Trade broadcasts are best-effort and may be replayed after reconnects. Deduplicate them by RFQ ID: rfqId in TypeScript or rfq_id in Python and raw WebSocket messages.
1

Switch on the Event Type

First, switch on event.type to handle trade broadcasts from the same session stream.
2

Inspect the Trade

Then, inspect the confirmed trade before storing or applying it. Trade broadcasts exclude maker identity and per-maker fill allocations.
price is the accepted blended price in pUSD per YES Combo share. size is the matched Combo share size. Both values are normalized decimal strings.
3

Store the Trade

Finally, persist the trade by RFQ ID and execution timestamp for downstream reconciliation.

Handle Errors

In this section, we will talk you through how to handle errors with the RFQ system.

Open the RFQ Session

Wrap client.openRfqSession() in try/catch and use OpenRfqSessionError.isError(…) to narrow the error type.

Submit a Quote

Wrap event.quote(…) in try/catch and use RfqQuoteError.isError(…) to narrow the error type.

Cancel a Quote

Wrap session.cancelQuote(…) in try/catch and use RfqCancelQuoteError.isError(…) to narrow the error type.

Confirm or Decline

Wrap event.confirm() or event.decline() in try/catch and use RfqConfirmationError.isError(…) to narrow the error type.