Skip to main content

Overview

The RfqClient provides Request-for-Quote (RFQ) functionality, allowing users to create price requests and respond with quotes. This is accessible via client.rfq on any ClobClient instance.

Accessing RfqClient

import { ClobClient } from '@polymarket/clob-client';

const client = new ClobClient(host, chainId, signer, creds);
const rfqClient = client.rfq;

// Or use directly
await client.rfq.createRfqRequest(...);

RFQ Workflow

  1. Requester creates an RFQ request with desired trade parameters
  2. Quoters respond with quotes offering prices
  3. Requester reviews quotes and accepts the best one
  4. Quoter approves the order to finalize the trade

Methods

createRfqRequest

Create a new RFQ request asking for quotes on a trade.
async createRfqRequest(
  userOrder: RfqUserOrder,
  options?: Partial<CreateOrderOptions>
): Promise<RfqRequestResponse>
userOrder
RfqUserOrder
required
options
Partial<CreateOrderOptions>
return
Promise<RfqRequestResponse>
Example:
// Request quotes to buy 100 tokens at $0.52
const request = await client.rfq.createRfqRequest({
  tokenID: '123456789',
  price: 0.52,
  size: 100,
  side: Side.BUY,
});

console.log('RFQ Request ID:', request.requestId);

getRfqRequests

Get RFQ requests with optional filtering.
async getRfqRequests(
  params?: GetRfqRequestsParams
): Promise<RfqRequestsResponse>
params
GetRfqRequestsParams
return
Promise<RfqRequestsResponse>
RfqRequest object:
interface RfqRequest {
  requestId: string;        // Unique request ID
  userAddress: string;      // User wallet address
  proxyAddress: string;     // Proxy wallet address
  token: string;            // Token ID
  complement: string;       // Complement token ID
  condition: string;        // Market condition ID
  side: string;             // "BUY" or "SELL"
  sizeIn: string;           // Input size
  sizeOut: string;          // Output size
  price: number;            // Target price
  acceptedQuoteId: string;  // ID of accepted quote (if any)
  state: string;            // Request state
  expiry: Date;             // Expiration time
  createdAt: Date;          // Creation time
  updatedAt: Date;          // Last update time
}
Example:
// Get all active RFQ requests
const requests = await client.rfq.getRfqRequests({
  state: 'active',
  limit: 100,
});

console.log(`Found ${requests.count} active requests`);

cancelRfqRequest

Cancel an RFQ request.
async cancelRfqRequest(
  request: CancelRfqRequestParams
): Promise<"OK">
request
CancelRfqRequestParams
required
Example:
await client.rfq.cancelRfqRequest({
  requestId: 'abc-123-def-456',
});

createRfqQuote

Create a quote in response to an RFQ request.
async createRfqQuote(
  userQuote: RfqUserQuote,
  options?: Partial<CreateOrderOptions>
): Promise<RfqQuoteResponse>
userQuote
RfqUserQuote
required
options
Partial<CreateOrderOptions>
return
Promise<RfqQuoteResponse>
Example:
// Quote to sell at $0.53 in response to request
const quote = await client.rfq.createRfqQuote({
  requestId: 'abc-123-def-456',
  tokenID: '123456789',
  price: 0.53,
  size: 100,
  side: Side.SELL,
});

console.log('Quote ID:', quote.quoteId);

getRfqRequesterQuotes

Get quotes on your RFQ requests (requester’s view - quotes others made on your requests).
async getRfqRequesterQuotes(
  params?: GetRfqQuotesParams
): Promise<RfqQuotesResponse>
params
GetRfqQuotesParams
return
Promise<RfqQuotesResponse>
RfqQuote object:
interface RfqQuote {
  quoteId: string;          // Unique quote ID
  requestId: string;        // Associated request ID
  userAddress: string;      // Quoter wallet address
  proxyAddress: string;     // Quoter proxy address
  complement: string;       // Complement token ID
  condition: string;        // Market condition ID
  token: string;            // Token ID
  side: string;             // "BUY" or "SELL"
  sizeIn: string;           // Input size
  sizeOut: string;          // Output size
  price: number;            // Quoted price
  state: string;            // Quote state
  expiry: Date;             // Expiration time
  matchType: string;        // "COMPLEMENTARY" | "MERGE" | "MINT"
  createdAt: Date;          // Creation time
  updatedAt: Date;          // Last update time
}
Example:
// Get all quotes on a specific request
const quotes = await client.rfq.getRfqRequesterQuotes({
  requestIds: ['abc-123-def-456'],
  state: 'active',
});

console.log(`Received ${quotes.count} quotes`);
quotes.data.forEach(q => {
  console.log(`Quote ${q.quoteId}: price ${q.price}`);
});

getRfqQuoterQuotes

Get quotes you’ve created (quoter’s view - quotes you made on others’ requests).
async getRfqQuoterQuotes(
  params?: GetRfqQuotesParams
): Promise<RfqQuotesResponse>
Parameters and return type are identical to getRfqRequesterQuotes, but returns quotes where you are the quoter. Example:
// Get all quotes you've created
const myQuotes = await client.rfq.getRfqQuoterQuotes({
  state: 'active',
  sortBy: 'created',
  sortDir: 'desc',
});

getRfqBestQuote

Get the best quote for a specific RFQ request.
async getRfqBestQuote(
  params?: GetRfqBestQuoteParams
): Promise<RfqQuote>
params
GetRfqBestQuoteParams
return
Promise<RfqQuote>
The best quote based on price
Example:
const bestQuote = await client.rfq.getRfqBestQuote({
  requestId: 'abc-123-def-456',
});

console.log('Best quote price:', bestQuote.price);

cancelRfqQuote

Cancel a quote you’ve created.
async cancelRfqQuote(
  quote: CancelRfqQuoteParams
): Promise<"OK">
quote
CancelRfqQuoteParams
required
Example:
await client.rfq.cancelRfqQuote({
  quoteId: 'xyz-789-uvw-012',
});

acceptRfqQuote

Accept a quote on your RFQ request (requester accepting quoter’s offer).
async acceptRfqQuote(
  payload: AcceptQuoteParams
): Promise<"OK">
payload
AcceptQuoteParams
required
return
Promise<'OK'>
Success confirmation
This method:
  1. Fetches the quote details
  2. Creates a matching order
  3. Submits the acceptance to the server
Example:
// Accept the best quote
const bestQuote = await client.rfq.getRfqBestQuote({
  requestId: 'abc-123-def-456',
});

await client.rfq.acceptRfqQuote({
  requestId: 'abc-123-def-456',
  quoteId: bestQuote.quoteId,
  expiration: Math.floor(Date.now() / 1000) + 3600, // 1 hour from now
});

console.log('Quote accepted!');

approveRfqOrder

Approve an accepted quote (quoter finalizing the trade).
async approveRfqOrder(
  payload: ApproveOrderParams
): Promise<"OK">
payload
ApproveOrderParams
required
return
Promise<'OK'>
Success confirmation
This method:
  1. Fetches the quote details
  2. Creates a matching order
  3. Submits the approval to finalize the trade
Example:
// Approve a quote that was accepted
await client.rfq.approveRfqOrder({
  requestId: 'abc-123-def-456',
  quoteId: 'xyz-789-uvw-012',
  expiration: Math.floor(Date.now() / 1000) + 3600,
});

console.log('Order approved and trade finalized!');

rfqConfig

Get RFQ configuration from the server.
async rfqConfig(): Promise<any>
return
Promise<any>
RFQ system configuration

Complete RFQ Example

As a Requester

import { ClobClient, Side } from '@polymarket/clob-client';

const client = new ClobClient(host, chainId, signer, creds);

// Step 1: Create RFQ request
const request = await client.rfq.createRfqRequest({
  tokenID: '123456789',
  price: 0.52,
  size: 100,
  side: Side.BUY,
});

console.log('Created request:', request.requestId);

// Step 2: Wait for quotes, then fetch them
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s

const quotes = await client.rfq.getRfqRequesterQuotes({
  requestIds: [request.requestId],
  state: 'active',
  sortBy: 'price',
  sortDir: 'asc', // Best price first
});

console.log(`Received ${quotes.count} quotes`);

// Step 3: Accept best quote
if (quotes.data.length > 0) {
  const bestQuote = quotes.data[0];
  console.log('Best quote:', bestQuote.price);
  
  await client.rfq.acceptRfqQuote({
    requestId: request.requestId,
    quoteId: bestQuote.quoteId,
    expiration: Math.floor(Date.now() / 1000) + 3600,
  });
  
  console.log('Quote accepted! Waiting for quoter approval...');
}

As a Quoter

import { ClobClient, Side } from '@polymarket/clob-client';

const client = new ClobClient(host, chainId, signer, creds);

// Step 1: Find active RFQ requests
const requests = await client.rfq.getRfqRequests({
  state: 'active',
  markets: ['0x1234...'], // Filter by market
  limit: 50,
});

console.log(`Found ${requests.count} active requests`);

// Step 2: Create quote on interesting request
const targetRequest = requests.data[0];

const quote = await client.rfq.createRfqQuote({
  requestId: targetRequest.requestId,
  tokenID: targetRequest.token,
  price: 0.53, // Your offered price
  size: parseFloat(targetRequest.sizeOut),
  side: Side.SELL, // Opposite of their BUY
});

console.log('Quote created:', quote.quoteId);

// Step 3: Monitor your quotes
const myQuotes = await client.rfq.getRfqQuoterQuotes({
  state: 'active',
});

// Step 4: Approve when requester accepts
// (In practice, you'd use webhooks or polling)
for (const q of myQuotes.data) {
  // Check if quote was accepted (you'd need to track state changes)
  await client.rfq.approveRfqOrder({
    requestId: q.requestId,
    quoteId: q.quoteId,
    expiration: Math.floor(Date.now() / 1000) + 3600,
  });
  
  console.log('Trade finalized for quote:', q.quoteId);
}

Match Types

RFQ quotes have different match types that determine how orders are matched:
  • COMPLEMENTARY: Buy/Sell or Sell/Buy on opposite sides of the same token
  • MINT: Both buying the same outcome (minting a position)
  • MERGE: Both selling the same outcome (merging positions)
The SDK automatically handles the order creation logic for each match type.

Build docs developers (and LLMs) love