Subscribe to RFQs
The WebSocket stream, snapshot semantics, and the REST fallback
The stream
import WebSocket from "ws";
const ws = new WebSocket("wss://<host>/maker/stream", {
headers: { "X-API-Key": process.env.CESSIO_API_KEY },
});The key rides the X-API-Key upgrade header. Browser-native WebSocket
cannot set upgrade headers and therefore cannot authenticate this maker
stream; use a Node client such as ws. A missing or unknown key closes the
socket with code 4401 before you receive anything.
Every frame is JSON {type, payload} — the full catalog is on
WS Events.
Snapshot: reconnect IS resync
On connect the server immediately replays the current state:
rfq.createdfor every active RFQ you are invited to;quote.created+quote.statusfor each of your active quotes.
Then live events follow. This means you never need a separate bootstrap call and never need to persist state across reconnects — drop your local state on disconnect and rebuild it from the snapshot:
ws.on("close", () => {
tracked.clear(); // stale by definition
setTimeout(connect, 1000); // snapshot rebuilds everything
});If the server itself loses state it sends resync {} — treat it exactly
like a disconnect: close, reconnect, consume the fresh snapshot.
REST fallback for simple bots
The socket is not just a feed — it is also presence: the desk only
offers a taker your hint while your /maker/stream socket is open, so a
bot with no open socket is never invited and /rfq/incoming stays empty
forever, no error, nothing to catch. Keep the socket connected even if you
drive everything off REST; then, if reacting to events is inconvenient,
poll instead of parsing frames:
curl -H "X-API-Key: $API_KEY" $API_URL/rfq/incomingIt returns the same RFQs as the snapshot, each with myQuote — your
active quote or null. The honest trade-offs: polling latency eats into
the RFQ deadline, and you do not see quote statuses or settlement progress
(trade.step, trade.settled) — you would have to infer outcomes from
GET /maker/trades and GET /wallet/holdings. The WebSocket is the
canonical path.