Skip to main content
The quote-request stream is channel 1 of the Convallax maker transport: a Server-Sent Events (SSE) feed that pushes live quote_request events to you as traders open them. It replaces the old WebSocket quote_request broadcast.
ChannelTransportDirectionPurpose
1 — Quote requestsSSEserver → makerReceive live quote_request events (this page)
2 — Quote submissionRESTmaker → serverPOST /v1/mm/quotes and confirm signature
3 — Post-tradeWebSocketserver → makerquote:accepted / quote:confirmed / quote:rejected
To fully participate you must hold both this SSE stream open (to receive requests) and the post-trade WebSocket (to learn when you win). Quotes and confirmation signatures are submitted over REST.

Connecting

GET https://api.convallax.com/v1/mm/quote-requests/stream
This is a standard SSE endpoint (Content-Type: text/event-stream). In a browser, you can use the native EventSource API only if you authenticate via ?apiKey= on the URL (browsers cannot set X-API-Key on SSE). Market-maker bots run in Node.js and should use the eventsource npm package, which supports custom headers:
npm install eventsource

Authentication

Authenticate with your per-MM API key using the X-API-Key header:
X-API-Key: <your-key>
Or, if your SSE client cannot set custom headers, pass the key as a query parameter:
GET https://api.convallax.com/v1/mm/quote-requests/stream?apiKey=<your-key>
The SSE quote-request stream and the REST quote endpoints authenticate via the X-API-Key header (or ?apiKey=). The post-trade WebSocket still uses ?apiKey= on the URL or an auth message. See Authentication.

Connection Handshake

When you connect, the server emits events in a fixed order.
1

connected

The first event confirms your resolved makerId and the server time.
event: connected
data: { "makerId": "mm-alpha", "serverTime": "2026-06-15T12:00:00.000Z" }
2

Replay or snapshot

The server then sends either a replay (if you reconnected with a Last-Event-ID header that is still in the buffer) or a fresh snapshot of all currently open requests:
event: snapshot_begin
data: {}

event: quote_request
id: 1042
data: { "requestId": "req-789", ... }

event: snapshot_complete
data: {}
Between snapshot_begin and snapshot_complete you receive zero or more quote_request events, each carrying an SSE id:.
3

Live events

After the snapshot completes, new quote_request and quote_request_expired events stream in as they happen.

Events

connected

Sent once, immediately on connect.
event: connected
data: { "makerId": "mm-alpha", "serverTime": "2026-06-15T12:00:00.000Z" }

snapshot_begin / snapshot_complete

Frame the initial set of open quote requests. Everything between them reflects the state at connect time.
event: snapshot_begin
data: {}
event: snapshot_complete
data: {}

quote_request — New or replayed quote request

A live quote request. Each event carries a monotonic integer SSE id: — track the last one you processed so the server can replay on reconnect.
event: quote_request
id: 1043
data: {
  "requestId": "req-789",
  "expiresAt": "2026-06-15T12:05:00.000Z",
  "params": {
    "wallet": "0xTrader...",
    "market": {
      "conditionId": "0xa4ddc18895cc7b14810283ef8f113939abffd3969c6a0e37f1897110c67e6f73",
      "yesTokenId": "51508280778202349361616850684455231843716212176724253736363122559269229712002",
      "question": "Will there be a Hantavirus outbreak in 2026?"
    },
    "option": {
      "optionType": "call",
      "strikeBps": 50,
      "expiryMs": 1735689600000
    },
    "trade": {
      "side": "buy",
      "budgetUsd": 100
    }
  }
}
FieldTypeDescription
requestIdstringUnique ID for this quote request — use it when you POST /v1/mm/quotes
expiresAtstringISO 8601 expiry time for the quote request (default 5 min TTL)
params.walletstringTaker wallet address (may be null if not yet provided)
params.market.conditionIdstringPolymarket condition ID (bytes32)
params.market.yesTokenIdstringPolymarket YES CLOB token ID
params.market.questionstringHuman-readable market question
params.option.optionTypestring/number"call" or "put" (or 0/1)
params.option.strikeBpsnumberStrike in basis points of $1
params.option.expiryMsnumberOption expiry (Unix ms)
params.trade.sidestring"buy" or "sell" (taker’s side)
params.trade.budgetUsdnumberBuys only. USDC the taker will spend. Fill = floor(budgetUsd / price) whole options, capped by your quoted size.
params.trade.sizenumberSells only. Number of whole options the taker wants to write.

quote_request_expired — Request closed

The request closed (committed, expired, or cancelled). Drop it from local state.
event: quote_request_expired
data: { "requestId": "req-789" }

Reconnect & Replay

SSE clients should reconnect automatically on disconnect. The standard EventSource API tracks the last received id: and sends it back as the Last-Event-ID header on reconnect; the server replays any events you missed.
  • If the gap is small enough to be covered by the server buffer, you receive a replay of the missed quote_request / quote_request_expired events.
  • If the gap is too large, the server falls back to a fresh snapshot_beginsnapshot_complete sequence reflecting current open requests.
If you use a non-browser client that does not automatically manage Last-Event-ID, store the last SSE id: you processed and set the Last-Event-ID header yourself when reconnecting.

Keep-Alive

The server sends SSE comment lines (: ping) roughly every 25 seconds to keep the connection and any intermediary proxies alive. SSE clients ignore comment lines automatically.

Example

import EventSource from 'eventsource';

const stream = new EventSource(
  'https://api.convallax.com/v1/mm/quote-requests/stream',
  { headers: { 'X-API-Key': process.env.MAKER_API_KEY } }
);

stream.addEventListener('connected', (e) =>
  console.log('connected', JSON.parse(e.data))
);

stream.addEventListener('quote_request', (e) => {
  const req = JSON.parse(e.data);
  console.log(`New request ${req.requestId}: ${req.params.market.question}`);
  // Price it and submit via POST /v1/mm/quotes (channel 2)
});

stream.addEventListener('quote_request_expired', (e) => {
  const { requestId } = JSON.parse(e.data);
  console.log(`Request ${requestId} closed`);
});

stream.onerror = () => console.log('disconnected — EventSource will retry');
See the Market Maker guide for the end-to-end flow across all three channels, and the Quote Request Stream API reference for the endpoint details.