Skip to main content
A single trade crosses four channels and changes names twice on the way. This page maps a trade’s full lifecycle across every channel side by side, and lists the field aliases and noun changes you’d otherwise piece together from How parlays work, Real time & data channels, WebSocket, webhooks, and the Quote Service reference pages.

Naming conventions across channels

Each channel has its own event naming grammar. Knowing the pattern up front makes every table below scannable at a glance:
  • SSE events are bare or underscore-separated names — best_quote, quote_request, quote_request_expired.
  • WebSocket events are resource:verb, colon-namespaced — quote:accepted, position:settled.
  • Webhook events are resource.verb, dot-namespaced — position.settled, parlay.status_changed.
There’s no deeper logic to the separator choice beyond which channel it’s on. The MM SSE stream isn’t even internally consistent: quote_request and quote_request_expired use underscores, while quote_request:updated uses a colon (see the summary table on that page).

One trade, across every channel

Read this left to right for any given moment, or top to bottom to follow one trade start to finish. ”—” means the moment has no representation on that channel.
quote:* WebSocket events (quote:accepted, quote:confirmed, quote:executed, quote:expired, quote:rejected, quote:withdrawn) deliver only to the awarded market maker, on their private mm:quotes:{mm_id} channel. position:* events deliver on rfq:{rfq_id}, the channel a user (or anyone tracking a specific trade) subscribes to. The two families are not interchangeable views of the same moment — several rows below have a WebSocket event for the MM and nothing for the user, or vice versa.

The transfer notification gap

An early cashout resolves one of two ways, and only one of them notifies you live. A closing exit is delivered over WebSocket. position:bought_back carries rfq_id, position_pda, amount, mm_pays_user, tx_signature and quote_id, and it fans out to four places at once: the rfq:{rfq_id} channel (the canonical one for position:* events, and the one to subscribe to), the mm:quotes:{mm_id} channel of the market maker whose exposure closed, and directly to any connection authenticated as the seller or as that market maker. Those last two need no subscription — they arrive on identity alone, so you may see the same event twice if you also hold the rfq:{rfq_id} subscription. Dedupe on tx_signature. The position.bought_back webhook carries the same moment for integrations that prefer webhooks.
A bid that acquires a position notifies the buyer of nothing. When the winning bid comes from a market maker that was not the position’s counterparty, the position transfers to them and stays open — and today there is no WebSocket event and no buyer-side webhook for that (position.transferred is attributed to the seller). If you bid on auctions for positions you do not already back, reconcile acquisitions from your position reads rather than waiting for a push.

Same value, different name

The same economic figures go by different names at the quote stage versus the settlement stage:

Market maker identity across channels

All three spellings hold a market maker id, but they do not all mean the same market maker. mm_id and market_maker_id are channel-dependent spellings of the maker in question — usually you, or the one whose quote is being described. counterparty_mm_id is different in kind: it names the maker who already backs the position, which on a broadcast cashout auction is generally not the maker whose bid wins. Treating it as the bidder is how an acquisition gets routed to the wrong maker.

The noun stack

The same trade is called something different at each stage of its life. How parlays work introduces this progression; here it’s gathered in one place: