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

© 2026 Gemini Space Station, Inc.

Examples

Status: Beta (v0.1) — dark-launched. Endpoints are implemented behind the PredictionMarketsRFSEnabled flag (404 while dark). Payloads below match the merged wire shape (PREDICT-4876). Macro instrument-symbol convention is illustrative — the production format is finalized separately. assetClasses is currently always empty pending the PREDICT-4732 categories rework; examples show its eventual populated form for context.

These examples show the RFS-specific surface — submit and announcement — across asset classes. Once the combo book is open, trading is standard combo orderbook (Combo Contracts); these examples don't duplicate the standard orderbook docs.

The first example carries the full walkthrough: both write entry points (dedicated RFS endpoint and combo-create with an rfs block), the WebSocket announcement, and cross-surface identity. The other two show only what's different about same-event and cross-class leg sets — the submit shape and everything after OPEN are otherwise identical.


1. Two-leg crypto spread

A trader wants to trade the joint outcome of "BTC above $120,000 at year-end and ETH above $5,000 at year-end" as a single instrument. The combo doesn't exist on the venue yet, so the request creates it.

ParameterValue
Combo legsGEMI-BTC-EOY26-HI120000 (Yes), GEMI-ETH-EOY26-HI5000 (Yes)
Contract exists already?No — this request creates it (comboCreatedAt is set to now; combo-create returns alreadyExisted: false)
Indicative side / sizeBuy 1,000 (informational)
rfsIda8c7b1d4-9e3f-4b2a-8c5e-1f6d7e8b9a0c
Derived comboSymbolGEMI-CMB-0526-A7F3B2C1D4E5

REST: dedicated RFS endpoint

Code
POST /v1/prediction-markets/combos/rfs Content-Type: application/json X-GEMINI-APIKEY: <taker key> X-GEMINI-PAYLOAD: <base64 payload> X-GEMINI-SIGNATURE: <hmac>
Code
{ "legs": [ { "instrumentSymbol": "GEMI-BTC-EOY26-HI120000", "direction": "Yes" }, { "instrumentSymbol": "GEMI-ETH-EOY26-HI5000", "direction": "Yes" } ], "side": "Buy", "size": 1000, "structureTypes": ["BASKET"] }

Response — 201 Created. The RFS is returned under request:

Code
{ "request": { "rfsId": "a8c7b1d4-9e3f-4b2a-8c5e-1f6d7e8b9a0c", "comboSymbol": "GEMI-CMB-0526-A7F3B2C1D4E5", "legs": [ { "instrumentSymbol": "GEMI-BTC-EOY26-HI120000", "direction": "Yes", "ratio": 1 }, { "instrumentSymbol": "GEMI-ETH-EOY26-HI5000", "direction": "Yes", "ratio": 1 } ], "side": "Buy", "size": 1000, "notional": null, "structureTypes": ["BASKET"], "assetClasses": [], "eventId": null, "state": "RFS_STATE_OPEN", "comboCreatedAt": "2026-05-22T15:04:01.234Z", "comboContractId": 987 } }

The book on GEMI-CMB-0526-A7F3B2C1D4E5 is now live and empty, waiting for makers. From here, all trading uses standard order entry against the comboSymbol. (A later request for the same legs is idempotent: it returns the same active RFS and reuses this same book rather than opening a parallel one.)

:::note size vs notional Supply at most one. To express the indicative interest in dollars instead of contracts, send "notional": "50000.00" and omit size. :::

REST: issue the RFS while creating the combo

If you already have the leg contract ids, you can create the combo and solicit liquidity in one call by adding an rfs block to POST /v1/prediction-markets/combos. This routes through the same merged path; the broadcast legs are derived server-side from the combo legs.

Code
POST /v1/prediction-markets/combos
Code
{ "legs": [ { "contractId": "373432", "requiredOutcome": "Yes" }, { "contractId": "373433", "requiredOutcome": "Yes" } ], "rfs": { "side": "Buy", "size": 1000, "structureTypes": ["BASKET"] } }

Response — 201 Created (or 200 OK if the combo already existed):

Code
{ "combo": { "id": 987, "instrumentSymbol": "GEMI-CMB-0526-A7F3B2C1D4E5", "legCount": 2, "status": "Draft", "instrumentRegistered": true }, "alreadyExisted": false, "rfs": { "rfsId": "a8c7b1d4-9e3f-4b2a-8c5e-1f6d7e8b9a0c", "comboSymbol": "GEMI-CMB-0526-A7F3B2C1D4E5", "legs": [ { "instrumentSymbol": "GEMI-BTC-EOY26-HI120000", "direction": "Yes", "ratio": 1 }, { "instrumentSymbol": "GEMI-ETH-EOY26-HI5000", "direction": "Yes", "ratio": 1 } ], "side": "Buy", "size": 1000, "notional": null, "structureTypes": ["BASKET"], "assetClasses": [], "eventId": null, "state": "RFS_STATE_OPEN", "comboCreatedAt": "2026-05-22T15:04:01.234Z", "comboContractId": 987 } }

alreadyExisted: false because this leg set had no contract yet. Omitting the rfs block creates the combo without soliciting liquidity. The combo object above is abbreviated — see Combo Contracts for the full ComboSummary shape.

WebSocket: announcement on requestForStream

When the RFS reaches RFS_STATE_OPEN, every subscriber receives a requestForStream event. The public broadcast uses abbreviated keys and proto-style enum values, and omits the internal-only fields (comboContractId, row timestamps) and any requester identity:

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 }

See WebSocket Reference for the full field key map. Makers decide whether to quote GEMI-CMB-0526-A7F3B2C1D4E5 and post orders via the standard order-entry path; their orders show up on GEMI-CMB-0526-A7F3B2C1D4E5@depth like any other book.

Cross-surface identity

The same two identifiers appear identically everywhere:

IdentifierREST fieldWebSocket fieldFIX tag (planned)
a8c7b1d4-9e3f-4b2a-8c5e-1f6d7e8b9a0crfsIdr131 QuoteReqID
GEMI-CMB-0526-A7F3B2C1D4E5comboSymbols55 Symbol

:::note FIX A FIX QuoteRequest-based entry point is planned (with rfsId mapped to QuoteReqID tag 131) but is not part of this dark-launched release. The REST and WebSocket surfaces above are the implemented ones. :::

What happens next

Makers posting orders, depth updates, the taker hitting the book, trade reports, position updates — all standard combo orderbook traffic on GEMI-CMB-0526-A7F3B2C1D4E5 (@bookTicker, @depth*, @trade, orders@account). See the standard Predictions API docs.


2. Same-event sports parlay (SGP)

"Chiefs win and Mahomes throws 2+ passing touchdowns and game total goes over 51.5" for one NFL game. The legs reference outcomes of a single event, so the request carries an exchange-derived eventId and is tagged SAME_EVENT for discovery.

Code
POST /v1/prediction-markets/combos/rfs
Code
{ "legs": [ { "instrumentSymbol": "GEMI-NFL-2611261830-KC-BUF-ML-KC", "direction": "Yes" }, { "instrumentSymbol": "GEMI-NFL-2611261830-KC-BUF-TD-MAHOMES2", "direction": "Yes" }, { "instrumentSymbol": "GEMI-NFL-2611261830-KC-BUF-TOT-O515", "direction": "Yes" } ], "side": "Buy", "size": 200, "structureTypes": ["SAME_EVENT"] }

The response is shaped exactly like Example 1, with eventId: "evt_nfl_2611261830_kc_buf", state: "RFS_STATE_OPEN", and comboCreatedAt set. The structureTypes tag is informational; the server also attempts to derive the shared eventId from the legs.

What's specific to SGP:

  1. eventId is populated whenever all legs share one underlying event (null otherwise), independent of whether the combo was just created or already existed. The standard combo surface uses eventId to bind the combo's halt state to the event — a single event-state halt (injury timeout, video review) voids all live orders on the combo book, not just one leg. This is part of the standard sports halt taxonomy.
  2. Maker pricing requires correlation modeling. The product of marginal leg prices is not a useful anchor; expect quoted spreads materially wider than the leg-product would imply. A maker-side concern — the protocol doesn't change.

:::note Discovery routing is client-side at v0.1 The intended end state routes announcements to makers by structureTypes/assetClasses filters. At v0.1 there is no server-side filter and assetClasses is empty (PREDICT-4732): every subscriber receives every requestForStream event and filters client-side. Everything after OPEN is standard combo orderbook. :::


3. Cross-class basket

A joint view across FOMC policy, BTC price, and a sports outcome — three legs spanning three asset classes. The wire payload is identical to a single-class request; RFS is class-agnostic.

Code
POST /v1/prediction-markets/combos/rfs
Code
{ "legs": [ { "instrumentSymbol": "GEMI-FOMC-202609-CUT25", "direction": "Yes" }, { "instrumentSymbol": "GEMI-BTC-EOY26-HI120000", "direction": "Yes" }, { "instrumentSymbol": "GEMI-NFL-2702071830-KC-PHI-ML-KC", "direction": "Yes" } ], "side": "Buy", "size": 500, "structureTypes": ["CROSS_CLASS"] }

The response carries eventId: null (legs don't share one event). When the categories rework lands, assetClasses will be multi-valued (["MACRO", "CRYPTO", "SPORTS"]); today it is returned empty.

What's specific to cross-class:

  • assetClasses will be multi-valued once populated. Single-class requests will carry a single-entry array.
  • Subset filtering (planned). The eventual assetClasses discovery filter matches by subset — a maker receives a request only if all of its classes are in their filter. A crypto-only desk would never see this request even though it contains a crypto leg, because it also touches macro and sports. Until that ships, filtering is client-side.
  • Reach is narrower. Cross-class structures attract fewer makers — typically institutional prop firms with multi-asset risk capacity. Expect wider quoted spreads.

Everything else — order entry, depth, fills, settlement, halts on underlying legs — is standard combo orderbook. The combo clears, margins, and settles identically to a single-class combo.

Last modified on June 17, 2026
On this page
  • 1. Two-leg crypto spread
    • REST: dedicated RFS endpoint
    • REST: issue the RFS while creating the combo
    • WebSocket: announcement on requestForStream
    • Cross-surface identity
    • What happens next
  • 2. Same-event sports parlay (SGP)
  • 3. Cross-class basket
JSON
JSON
JSON
JSON
JSON
JSON
JSON