# WebSocket Reference

:::caution
**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.

```
   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:

```
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):

```js
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)

```
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)

```
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](/prediction-markets/combos-rfs/examples#1-two-leg-crypto-spread).

## `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).

<StreamTester streamName="requestForStream" url="wss://ws.gemini.com" />

### 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`).

```json
{
  "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
}
```

| Field | Type | Description |
|---|---|---|
| `e` | string | Event type — always `requestForStream`. |
| `E` | number | Event timestamp (milliseconds). |
| `r` | string | `rfsId` — UUID for this request. Stable across REST / WS / FIX. |
| `s` | string | `comboSymbol`. **The load-bearing field** — the key to every subsequent interaction. |
| `l` | array | Legs, in canonical order. Each: `i` = `instrumentSymbol`, `d` = direction (`RFS_LEG_DIRECTION_YES` / `RFS_LEG_DIRECTION_NO`), `r` = ratio (omitted when 1). |
| `sd` | string | Side (`RFS_SIDE_BUY` / `RFS_SIDE_SELL`). Omitted when the taker didn't share it. Informational only. |
| `sz` | number | Indicative size in whole contracts. Omitted when unset; mutually exclusive with `n`. |
| `n` | string | Indicative dollar amount (string-decimal). Omitted when unset; mutually exclusive with `sz`. |
| `st` | array | `structureTypes` tags. Omitted when empty. |
| `ac` | array | `assetClasses`. **Currently always empty/omitted** (PREDICT-4732); will drive the maker discovery filter when populated. |
| `ev` | string | `eventId` — present only when every leg resolves on the same event (SGP discovery). Omitted otherwise. |
| `S` | string | Lifecycle state (`RFS_STATE_REQUESTED` / `RFS_STATE_OPEN` / `RFS_STATE_CLOSED` / `RFS_STATE_REJECTED`). `RFS_STATE_OPEN` is live and quotable. |
| `c` | number | `comboCreatedAt` 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](/prediction-markets/combo-contracts/overview#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 combo | `orders@account` (authenticated) |
| Your positions on the combo | `positions@account` (authenticated) |
| Combo halts, resumes, status changes | `contractStatus` |
| Balance changes from a combo fill | `balances@account` (authenticated) |

All of the right-hand-side channels are documented in the [standard Stream Reference](/prediction-markets/websocket/streams). 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](/prediction-markets/websocket/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](/prediction-markets/websocket/streams) — every channel referenced on the right-hand side of the mapping table above.
- [WebSocket Introduction](/prediction-markets/websocket/introduction) — connection parameters, performance tiers, heartbeats.
- [Two-leg spread example](/prediction-markets/combos-rfs/examples#1-two-leg-crypto-spread) — end-to-end RFS submit + announcement.
- [Combo Contracts](/prediction-markets/combo-contracts/overview) — orderbook behavior of the resulting combo.
