WS Events
Every frame the maker stream can deliver
Connect to wss://<host>/maker/stream with X-API-Key on the upgrade
request (for example, the Node ws package's headers option). Browser-native
WebSocket cannot set that header and cannot authenticate this maker stream.
Every frame is a JSON object:
{ "type": "rfq.created", "payload": { … } }On connect the server replays a snapshot of your current state and then streams live events; reconnecting is how you resync. The exact snapshot contents and the reconnect discipline are in Subscribe to RFQs.
Event catalog
type | payload | When |
|---|---|---|
rfq.created | RfqDto | You are invited to a new RFQ (and once per active RFQ in the snapshot) |
rfq.closed | {rfqId} | The RFQ ended — cancelled or filled by another maker (deliberately indistinguishable) |
rfq.expired | {rfqId} | The RFQ deadline passed unaccepted |
quote.created | QuoteDto | Snapshot replay of your active quote |
quote.status | {quoteId, rfqId, status} | Your quote moved: pending / won / lost / expired / revoked |
quote.anchored | {quoteId, rfqId, proposalCid} | An asynchronously-signing maker's proposal pair got signed (passkey browser, or a bot maker's /tx/execute) — the quote is now on-ledger |
trade.step | {tradeId, rfqId, step, refs} | Settlement phase completed: trade_dvp → fee_dvp → allocated; refs = contract ids the phase created |
trade.settled | TradeDto | The atomic settle executed; ledger.updateId + receiptCids are the proof |
trade.failed | {tradeId, rfqId, reason} | Settlement failed terminally (underfunding, expired Dvp window) — nothing moved |
balances.updated | BalancesDto | Your holdings changed (after settlement) |
sign.requested | SignActionDto | Something needs your party key — the push form of GET /tx/pending (sign queue) |
sign.completed | {actionId} | That action was signed and submitted |
resync | {} | Server state was reset — reconnect and consume the fresh snapshot |
Forward compatibility: ignore unknown types
Events are routed by party, not by socket kind: if the same party is also open in a browser somewhere, both sockets see the same frames — and new event types may be added at any time. A robust bot validates each frame and silently skips types it does not know:
const parsed = wsEventSchema.safeParse(JSON.parse(data)); // or your own subset schema
if (!parsed.success) return; // never crash, never log-spamErrors
The only auth failure is close code 4401 (missing or unknown X-API-Key), sent
before any frame. Anything else is operational — reconnect with backoff.