GeminiGemini
SandboxGet API key
  • Crypto Trading
  • Prediction Markets
Changelog
Gemini Crypto Exchange LogoGemini Crypto Exchange Logo

© 2026 Gemini Space Station, Inc.

WebSocket Reference

Status: Beta (v0.1) — dark-launched. The requestForStream channel is implemented (anonymous, public). Endpoint is wss://ws.gemini.com (same as orderbook streams). At v0.1 there is no server-side filtering — the channel broadcasts every event and you filter client-side (PREDICT-4732). These pages are intentionally not linked from the sidebar during the rollout.

TL;DR

RFS adds one channel: requestForStream. It announces incoming requests — each one a signal that there's demand on a comboSymbol (the combo book is created if the leg set is new). Everything else flows through the standard Predictions WebSocket channels for that comboSymbol — the same channels you already use for any other instrument.

Code
requestForStream → comboSymbol announced → {comboSymbol}@depth, @trade, @bookTicker, orders@account ──────────────── ──────────────────── ───────────────────────────────────────────────────────── RFS-specific handoff standard combo orderbook channels

Subscribe to requestForStream once, learn the comboSymbol, and from then on you're on the standard orderbook surface.

End-to-end maker flow

A market maker's complete WebSocket workflow to quote on combos surfaced by RFS:

Code
1. Connect to wss://ws.gemini.com 2. Subscribe to the requestForStream stream 3. Subscribe to orders@account (your existing maker subscription, authenticated) ── for each requestForStream event that matches your interest ── 4. Read comboSymbol (field `s`) from the message 5. Subscribe to {comboSymbol}@depth (see makers' resting orders, including yours) 6. Subscribe to {comboSymbol}@trade (see executions on the combo) 7. Post orders to comboSymbol via your existing order-entry path 8. Manage those orders the same way you manage every other order on the venue

The pseudocode (v0.1 — filter client-side, since the channel broadcasts every event):

Code
ws.subscribe(["requestForStream"]) ws.subscribe(["orders@account"]) // existing maker subscription ws.onMessage(msg => { if (msg.e === "requestForStream" && msg.S === "RFS_STATE_OPEN") { const comboSymbol = msg.s // client-side interest filter (no server-side filter at v0.1) if (!interestedIn(msg.l, msg.st)) return ws.subscribe([`${comboSymbol}@depth`, `${comboSymbol}@trade`]) if (shouldQuote(msg.l)) { const orders = priceCombo(msg.l) for (const o of orders) submitOrder(comboSymbol, o) // standard order entry } } // orders@account events for your own fills flow through here as for any combo })

There is no RFS-specific order shape, no "quote" object, no acceptance handshake — once comboSymbol is known, this is standard market making against a standard combo book.

End-to-end taker flow

The protocol surface is the same for institutional bots and retail-facing clients; the difference is purely in how the client wraps it. Two patterns:

Retail-facing client (RFQ-style UX)

Code
1. User builds a combo in the UI; client validates legs. 2. Client submits RFS via REST: POST /v1/prediction-markets/combos/rfs ── response carries rfsId and comboSymbol ── 3. UI shows "Fetching prices..." (typical window: 5–15 seconds). 4. Client connects to wss://ws.gemini.com and subscribes to: {comboSymbol}@bookTicker (best bid/ask as the book fills in) {comboSymbol}@depth (full picture if useful) orders@account (for the eventual fill, authenticated) 5. As maker orders arrive, the UI shows the current best price. 6. User chooses to accept → client submits an aggressive market order against comboSymbol via standard order entry. OR user declines / the window times out → client closes the UI; the combo book stays open on the venue, but the user has moved on. 7. If accepted, the fill arrives on orders@account; position lands in the user's standard position ledger.

The "Fetching prices" window is a client-side UX bound, not a protocol feature. The combo book on comboSymbol persists beyond the window — other takers may come along later and find resting maker depth.

Institutional bot (direct orderbook integration)

Code
1. Submit RFS via REST: POST /v1/prediction-markets/combos/rfs 2. Subscribe to {comboSymbol}@depth and orders@account 3. Wait until depth meets your execution criteria (price, size, timing model) 4. Submit aggressive order against comboSymbol via standard order entry 5. Fill arrives on orders@account

No UI window, no "fetching" abstraction — the bot interacts with the depth feed directly. Same protocol underneath as the retail client; just no UX wrapper.

In both cases, the taker can optionally subscribe to requestForStream to see their own request announcement, but it's not required — the REST response already carries rfsId and comboSymbol.

For full REST-side flow, see Two-leg spread example.

requestForStream

Every incoming request as it reaches RFS_STATE_OPEN — a demand signal on a comboSymbol, which may be brand new or already existing. Anonymized: carries no taker identity, and the internal-only fields on the persisted RFS (comboContractId, server-internal row timestamps) are stripped before broadcast.

Auth: public. Anyone can subscribe.

Filtering: at v0.1, none server-side — every subscriber receives every event and filters on the message contents client-side. Server-side assetClasses/structure filtering is deferred (PREDICT-4732).

Try ItrequestForStream
disconnected

Message shape

The broadcast uses abbreviated JSON keys and proto-style enum values (note: these differ from the REST encoding — REST uses Buy/Yes; the stream uses RFS_SIDE_BUY/RFS_LEG_DIRECTION_YES).

Code
{ "e": "requestForStream", "E": 1780000000000, "r": "a8c7b1d4-9e3f-4b2a-8c5e-1f6d7e8b9a0c", "s": "GEMI-CMB-0526-A7F3B2C1D4E5", "l": [ { "i": "GEMI-BTC-EOY26-HI120000", "d": "RFS_LEG_DIRECTION_YES", "r": 1 }, { "i": "GEMI-ETH-EOY26-HI5000", "d": "RFS_LEG_DIRECTION_YES", "r": 1 } ], "sd": "RFS_SIDE_BUY", "sz": 1000, "st": ["BASKET"], "S": "RFS_STATE_OPEN", "c": 1780000001000 }
FieldTypeDescription
estringEvent type — always requestForStream.
EnumberEvent timestamp (milliseconds).
rstringrfsId — UUID for this request. Stable across REST / WS / FIX.
sstringcomboSymbol. The load-bearing field — the key to every subsequent interaction.
larrayLegs, in canonical order. Each: i = instrumentSymbol, d = direction (RFS_LEG_DIRECTION_YES / RFS_LEG_DIRECTION_NO), r = ratio (omitted when 1).
sdstringSide (RFS_SIDE_BUY / RFS_SIDE_SELL). Omitted when the taker didn't share it. Informational only.
sznumberIndicative size in whole contracts. Omitted when unset; mutually exclusive with n.
nstringIndicative dollar amount (string-decimal). Omitted when unset; mutually exclusive with sz.
starraystructureTypes tags. Omitted when empty.
acarrayassetClasses. Currently always empty/omitted (PREDICT-4732); will drive the maker discovery filter when populated.
evstringeventId — present only when every leg resolves on the same event (SGP discovery). Omitted otherwise.
SstringLifecycle state (RFS_STATE_REQUESTED / RFS_STATE_OPEN / RFS_STATE_CLOSED / RFS_STATE_REJECTED). RFS_STATE_OPEN is live and quotable.
cnumbercomboCreatedAt in milliseconds — when the combo's order book was created, not when the request was submitted. Omitted when unset.

The comboSymbol is content-addressable per the combo ticker format. Identical leg sets always produce the same comboSymbol; a request for a leg set that already has a contract reuses it rather than creating a duplicate. To tell a brand-new book from a re-solicited one, compare c (comboCreatedAt) against the event time E.

Replay on reconnect

requestForStream is an event stream of demand signals, not a state snapshot. Requests that arrived while you were disconnected are not replayed. To enumerate combos that currently exist (regardless of how recently they were requested), use the standard combo instrument listing in the REST API.

Channel mapping

Things integrators might expect on an rfs.* channel but that actually live on the standard combo orderbook surface:

You want to see...Subscribe to...
Incoming requests (new or re-solicited combos)requestForStream (this page)
Best bid/ask on the combo{comboSymbol}@bookTicker
Full depth of the combo orderbook{comboSymbol}@depth, {comboSymbol}@depth@100ms
Top-N snapshots of the combo orderbook{comboSymbol}@depth5, @depth10, @depth20
Trades / fills on the combo (public tape){comboSymbol}@trade
Your own orders and fills on the comboorders@account (authenticated)
Your positions on the combopositions@account (authenticated)
Combo halts, resumes, status changescontractStatus
Balance changes from a combo fillbalances@account (authenticated)

All of the right-hand-side channels are documented in the standard Stream Reference. RFS does not duplicate them or rename them.

Connection notes

  • Same endpoint as all other Predictions streams: wss://ws.gemini.com.
  • Same subscribe message shape and connection parameters as documented in the Introduction.
  • requestForStream is public — no auth headers required.
  • Cancel-on-disconnect for orders on combo books follows the venue-wide setting on the connection (cancelOnDisconnect query parameter); RFS does not add a separate disconnect policy.

See also

  • Standard Stream Reference — every channel referenced on the right-hand side of the mapping table above.
  • WebSocket Introduction — connection parameters, performance tiers, heartbeats.
  • Two-leg spread example — end-to-end RFS submit + announcement.
  • Combo Contracts — orderbook behavior of the resulting combo.
Last modified on June 17, 2026
On this page
  • TL;DR
  • End-to-end maker flow
  • End-to-end taker flow
    • Retail-facing client (RFQ-style UX)
    • Institutional bot (direct orderbook integration)
  • requestForStream
    • Message shape
    • Replay on reconnect
  • Channel mapping
  • Connection notes
  • See also
Javascript
JSON