- User creates an unsigned Request for a Combo price.
- RFQ system sends the Request to connected market makers.
- Market makers submit signed Quotes within the 400 ms submission window.
- RFQ system returns the best Quote to the user.
- User accepts the Quote by signing the trade within the 5-second acceptance window.
- RFQ system requests Last Look confirmation when Last Look is enabled.
- Market maker confirms or declines within the 1-second confirmation window.
- RFQ system executes the accepted Combo.
- User receives execution updates.
- Market maker receives execution updates.
Combo position IDs are complementary to CLOB token IDs. A user can trade the
market on the CLOB or can include the market as a leg of a Combo.
Start Quoting
Start by preparing an authenticated quoting session with the RFQ system.- TypeScript
- Python
- API
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.
Create a Secure Client
Create an instance of The Relayer API key is necessary for setting up trading approvals in the next
step. Create a Relayer API key
from Settings > API Keys.
SecureClient with a wallet that has funds for fulfilling
user requests and its signer details.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.| Quote Request | Using Collateral | From Inventory |
|---|---|---|
| Buy YES | Buy NO at 1 - price | Sell YES at price |
| Sell YES | Buy YES at price | Sell NO at 1 - price |
Authorize the Quote
- TypeScript
- Python
- API
Evaluate Request
Then, inspect the
Where:
RfqQuoteRequestEvent before pricing it.| Field | Type | Description |
|---|---|---|
rfqId | RfqId | RFQ identifier used to correlate responses |
requestorPublicId | RfqRequestorPublicId | Public identifier for the user request |
conditionId | ComboConditionId | Derived Combo condition ID |
direction | RfqDirection | Whether the user wants to buy or sell |
side | RfqSide.Yes | Currently always RfqSide.Yes |
requestedSize | RfqRequestedSize | User-requested notional or share size |
yesPositionId | PositionId | Derived YES Combo position ID |
noPositionId | PositionId | Derived NO Combo position ID |
legPositionIds | PositionId[] | Underlying leg position IDs |
submissionDeadline | EpochMilliseconds | Unix-millisecond quote submission deadline |
requestedSize is an RfqRequestedSize value that describes how the user sized
the request.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.shares: the target number of Combo outcome tokens. For example,"10"means the user wants 10 shares, or 10,000,000 base units.
value is a normalized decimal string.Quote Partial Fills
- TypeScript
- Python
- API
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
- TypeScript
- Python
- API
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.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.- TypeScript
- Python
- API
Use Each returned item is a You can filter positions by the following criteria:
client.listComboPositions(...) to page through Combo positions for the
authenticated account. Filter by status, Combo condition ID, or Combo position
ID when you only need a subset of positions.ComboPosition.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.- TypeScript
- Python
- API
Use Use
client.splitPosition(...) with legs to create Combo inventory from
collateral. amount is in pUSD base units.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.- TypeScript
- Python
- API
Use You can list resolved winning positions first, then redeem each one.
client.redeemPositions(...) with a Combo positionId. The SDK redeems the
available balance for that resolved position.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.- API
- TypeScript
- Python
Fetch the first page of Combo-enabled markets.Use The response includes markets and an opaque The entries in
cursor to fetch the next page, and use exclude to omit markets you have
already shown or selected.next_cursor. A null cursor means
there are no more pages.position_ids, outcomes, and outcome_prices correspond by
array index.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.- TypeScript
- Python
- API
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.- TypeScript
- Python
- API
Switch on the Event Type
First, switch on
event.type to handle execution updates from the same session
stream.Inspect the Execution Update
Then, inspect the execution update before reconciling the selected RFQ. Execution
updates are correlated by where
rfqId.RfqExecutionStatus could be:| Status | Meaning |
|---|---|
RfqExecutionStatus.Matched | The quote was selected and handed off to execute. |
RfqExecutionStatus.Mined | The execution transaction was mined. |
RfqExecutionStatus.Retrying | Execution is being retried. |
RfqExecutionStatus.Confirmed | Execution completed successfully. |
RfqExecutionStatus.Failed | Execution failed. |
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.
- TypeScript
- Python
- API
Last Look
Last Look is a separate confirmation step for makers that have it enabled. If a selected quote requires confirmation, run a final risk check before the confirmation deadline and either confirm or decline the quote.- TypeScript
- Python
- API
Switch on the Event Type
First, switch on
event.type to handle confirmation requests from the same
session stream.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.Handle Errors
In this section, we will talk you through how to handle errors with the RFQ system.- TypeScript
- Python
- API
Open the RFQ Session
Wrapclient.openRfqSession() in try/catch and use
OpenRfqSessionError.isError(…) to narrow the error type.Submit a Quote
Wrapevent.quote(…) in try/catch and use RfqQuoteError.isError(…) to
narrow the error type.Cancel a Quote
Wrapsession.cancelQuote(…) in try/catch and use
RfqCancelQuoteError.isError(…) to narrow the error type.Confirm or Decline
Wrapevent.confirm() or event.decline() in try/catch and use
RfqConfirmationError.isError(…) to narrow the error type.