# Deep Dive — RFQ Protocol

Request-for-Quote (RFQ) lets makers respond to quote requests over WebSocket. The SDK exposes the public RFQ event stream, the private delivery stream, and the three maker quote methods.

**Public discovery** (`rfqs()` stream) works from both browser and server entry points — no authentication required. **Quote submission, confirmation, and withdrawal** are authenticated WebSocket operations that require the server entry point.

## The flow

1. A taker submits a request for quote. It appears on the public `rfqs` stream.
2. A maker submits a quote in response (`rfq.submitQuote`).
3. The taker confirms or rejects. The maker sees the outcome on the private `rfqDeliveries` stream.
4. The maker confirms the fill (`rfq.confirmQuote`) or withdraws a live quote (`rfq.withdrawQuote`).

## Watching for requests

The public `rfqs` stream emits [`RfqPublicEvent`](/tools/typescript-sdk/reference/websocket) messages:

```ts
const rfqs = client.websocket.rfqs();

rfqs.on("message", (event) => {
  // event.r  — RFQ ID
  // event.l  — legs (RfqLeg[]): each has c (contract) and o (side)
  // event.S  — lifecycle state
  // event.q  — quantity (optional)
  // event.s  — symbol (optional)
  console.log("RFQ", event.r, "state", event.S);
});

await rfqs.ready;
```

## Submitting a quote

```ts
const quote = await client.websocket.rfq.submitQuote({
  rfqId: event.r,
  price: "0.65",       // decimal string
  quantity: "100",     // decimal string
  validUntil: 1710547200000n, // optional, millisecond timestamp (bigint)
});
// quote: RfqSubmitQuoteResponse
```

`RfqSubmitQuoteParams`:

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `rfqId` | `string` | Yes | The RFQ being quoted |
| `price` | `string` | Yes | Quote price (decimal string) |
| `quantity` | `string` | Yes | Quote quantity (decimal string) |
| `validUntil` | `number \| bigint` | No | Expiry (millisecond timestamp) |

## Confirming a quote

```ts
await client.websocket.rfq.confirmQuote({
  rfqId: event.r,
  quoteId: quote.quoteId,
  confirm: true,
});
```

`RfqConfirmQuoteParams`:

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `rfqId` | `string` | Yes | The RFQ |
| `quoteId` | `string` | Yes | The quote being confirmed |
| `confirm` | `boolean` | Yes | `true` to confirm, `false` to reject |

## Withdrawing a quote

```ts
await client.websocket.rfq.withdrawQuote({
  rfqId: event.r,
  quoteId: quote.quoteId,
});
```

`RfqWithdrawQuoteParams`:

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `rfqId` | `string` | Yes | The RFQ |
| `quoteId` | `string` | Yes | The quote to withdraw |

## Private delivery stream

The authenticated `rfqDeliveries` stream emits [`RfqPrivateDelivery`](/tools/typescript-sdk/reference/websocket) messages — the private outcome of your quotes:

```ts
const deliveries = client.websocket.rfqDeliveries({ scope: "account" });

deliveries.on("message", (delivery) => {
  // delivery.i  — delivery ID
  // delivery.r  — RFQ ID
  // delivery.S  — lifecycle state
  // delivery.qs — quote status (optional)
  // delivery.p  — price (optional)
  // delivery.sz — size (optional)
  console.log("Delivery", delivery.i, "state", delivery.S);
});
```

`rfqDeliveries` takes a `scope` (`"account"` or `"session"`), like the `orders` stream.

## Combos

RFQ often targets multi-leg combos. Create a combo instrument via REST before quoting:

```ts
const combo = await client.predictions.createCombo({ /* legs */ });
const lookup = await client.predictions.getComboByInstrumentSymbol({
  instrumentSymbol: combo.instrumentSymbol,
});
```

See the [Combos Reference](/tools/typescript-sdk/reference/predictions/combos) for combo operations.

## What's next

- [WebSocket Reference](/tools/typescript-sdk/reference/websocket#rfq-quote-methods) — RFQ type signatures
- [Data Types](/tools/typescript-sdk/deep-dives/data-types) — decimal strings and bigint timestamps
