Stream Reference
Prediction Markets WebSocket streams follow the standard Gemini WebSocket protocol. Symbols use the prediction markets format (e.g. GEMI-BTC05M2606011000-UP). Replace example symbols with active instrumentSymbol values from GET /v1/prediction-markets/events.
Use WebSocket streams for active trading and market making. Use REST endpoints for event discovery and state reconciliation.
Stream Matrix
| Stream | Auth | Use for | Start here |
|---|---|---|---|
{symbol}@bookTicker | Public | Best bid/ask prices and quantities | First price watcher |
{symbol}@depth5, {symbol}@depth10, {symbol}@depth20 | Public | Periodic top-of-book snapshots | Simple dashboards |
{symbol}@depth, {symbol}@depth@100ms | Public | Maintaining a local order book | Market making |
{symbol}@trade | Public | Recent executions | Trade tape and analytics |
{agency}:{index}@indexPrice | Public | Price reference feeds for prediction-market contracts | Contract pricing and settlement |
orders@account | Authenticated | Order lifecycle events | Order state tracking |
balances@account | Authenticated | Balance changes | Risk checks |
positions@account | Authenticated | Low-latency position and settlement deltas | Exposure and settlement tracking |
contractStatus | Public | Contract status and strike updates | Lifecycle monitors |
Authenticated streams require Gemini authentication headers (HMAC or OAuth bearer token) during the WebSocket handshake. Browser WebSocket clients cannot set custom headers; use backend services or proxy servers for account streams.
Index-Keyed Price Streams
Index-keyed price streams provide the live reference price associated with a
prediction-market contract's sourceDetails.agency and sourceDetails.index.
Subscribe using the exact values returned by the contract or event discovery
API:
Code
For example:
Code
These streams are public and event-driven. The server resolves the
agency/index pair to the corresponding price feed and delivers the
reference-price update using the standard third-party price message format.
The matching is case-insensitive, but clients should use the values exactly
as returned by the source-details fields. Unknown pairs are rejected as
invalid stream names.
Book Ticker
| Schema | Frequency | Description |
|---|---|---|
{symbol}@bookTicker | Real-time | Real time updates to the best bid/ask price for an order book. |
GEMI-BTC05M2606011000-UP@bookTickerCode
| Field | Type | Description |
|---|---|---|
u | number | Update ID |
E | number | Event time (nanoseconds) |
s | string | Symbol |
b | string | Best bid price |
B | string | Best bid quantity |
a | string | Best ask price |
A | string | Best ask quantity |
c | string | Last trade price (present once the book has traded; omitted otherwise) |
C | string | Last trade size (present once the book has traded; omitted otherwise) |
L2 Partial Depth Streams
| Schema | Frequency | Description |
|---|---|---|
{symbol}@depth5 | Periodic (1s) | Periodic snapshot of the top 5 levels once per second |
{symbol}@depth10 | Periodic (1s) | Top 10 levels |
{symbol}@depth20 | Periodic (1s) | Top 20 levels |
{symbol}@depth5@100ms | Periodic (100ms) | Top 5 levels every 100 milliseconds |
{symbol}@depth10@100ms | Periodic (100ms) | Top 10 levels |
{symbol}@depth20@100ms | Periodic (100ms) | Top 20 levels |
GEMI-BTC05M2606011000-UP@depth10@100msCode
| Field | Type | Description |
|---|---|---|
lastUpdateId | number | Last update ID |
bids | array | Array of [price, quantity] |
asks | array | Array of [price, quantity] |
Use a depth snapshot as the starting point for any local order book or dollar calculation, then apply differential depth updates to keep it current. Each level is [price, quantity]. Public depth for event contracts is normalized in YES space: for YES notional, compute yesPrice * quantity; for NO notional, compute (1 - yesPrice) * quantity.
L2 Differential Depth Streams
| Schema | Frequency | Description |
|---|---|---|
{symbol}@depth | Periodic (1s) | List of all changed price levels in the last second |
{symbol}@depth@100ms | Periodic (100ms) | In the last 100 milliseconds |
GEMI-BTC05M2606011000-UP@depth@100msInitial Snapshot
Use the snapshot connection parameter to receive an initial orderbook snapshot when subscribing. Connect with wss://ws.gemini.com?snapshot=-1 for a full snapshot, or specify a positive number for top N levels.
Quantity zero indicates price level removal.
There is no separate snapshot message and no lastUpdateId field on this stream. When you subscribe with the snapshot parameter set to a non-zero value, the first depthUpdate frame you receive is the snapshot — it carries the full requested book state in its b/a arrays instead of a delta. Its U and u identify the first and last update IDs covered by the snapshot; use u as the last applied update ID. Every frame after that first one is a normal incremental delta: apply it directly to your local book. If a later frame's U skips ahead of the last applied u, discard the local book and resubscribe to resync. Without the snapshot parameter, or with it set to 0, every frame you receive (including the first) is an incremental delta.
Code
| Field | Type | Description |
|---|---|---|
e | string | Event type ("depthUpdate") |
E | number | Event time (nanoseconds) |
s | string | Symbol |
U | number | First update ID in this event |
u | number | Last update ID in this event |
b | array | Bid updates [price, quantity] |
a | array | Ask updates [price, quantity] |
Trade Stream
| Schema | Frequency | Description |
|---|---|---|
{symbol}@trade | Real-time | Real time trade executions |
GEMI-BTC05M2606011000-UP@tradeCode
| Field | Type | Description |
|---|---|---|
E | number | Event time (nanoseconds) |
s | string | Symbol |
t | number | Trade ID |
p | string | Price |
q | string | Quantity |
m | boolean | Is buyer the maker |
Order Events
Requires an authenticated session
| Schema | Frequency | Description |
|---|---|---|
orders@account | Real-time | Real time order activity for the account associated with the authenticated API key |
orders@session | Real-time | Real time order activity for the authenticated API key |
Order Event - New:
Code
Order Event - Canceled:
Code
| Field | Type | Description |
|---|---|---|
e | string | Event type (orderUpdate) |
E | number | Event time (nanoseconds) |
s | string | Symbol |
i | number | Order ID |
c | string | Client order ID. For RFQ maker fills, this is the clientId supplied to rfq.submit_quote, or Gemini's deterministic RFQ client order ID when omitted. |
S | string | Side, BUY / SELL |
o | string | Type, LIMIT / MARKET / STOP_LIMIT / STOP_MARKET |
X | string | Status, NEW / OPEN / FILLED / PARTIALLY_FILLED / CANCELED / REJECTED / MODIFIED |
O | string | Event outcome, YES / NO |
p | string | Order price |
P | string | Stop price (0 when not a stop order) |
q | string | Original quantity |
z | string | Remaining quantity |
Z | string | Executed quantity. For FILLED / PARTIALLY_FILLED events, this is the quantity filled in the last execution. For CANCELED and other events, this is the cumulative quantity filled over the lifetime of the order. Use Z (not the order status) to determine how much filled — e.g. a fully-filled IOC terminates as CANCELED. |
L | string | Last execution price |
t | number | Trade ID |
n | string | Fee amount (only present in 'FILLED' events) |
m | boolean | Maker flag on fills: true = maker, false = taker (present on fills only) |
r | string | Rejection reason |
T | number | Update time (nanoseconds) |
Fields with empty or zero values may be omitted from the event.
Post-only and immediate time-in-force orders are accepted, then cancelled — they are never REJECTED:
MOC(maker-or-cancel / post-only): if it would take liquidity, the order is cancelled withMakerOrCancelWouldTakeand never fills.IOC(immediate-or-cancel): fills whatever crosses immediately, then cancels the remainder withImmediateOrCancelWouldPost. A fully-filledIOCstill ends with aCANCELEDevent — so determine what filled from the executed quantity (Z), never from the final order status.FOK(fill-or-kill): fills completely and immediately, or is cancelled in full withFillOrKillWouldNotFill(no partial fills).
order.place for these still returns a 200 response with an initial NEW; a true rejection returns a non-200 status with an error code.
Rejection Reasons
When an order is REJECTED, the r field contains one of:
| Reason | Description |
|---|---|
MarketNotOpen | Market is closed or paused |
InsufficientFunds | Account lacks sufficient balance |
InvalidPrice | Price must be between $0.01–$0.99 |
LimitPriceOffTick | Price does not align with tick size |
InvalidQuantity | Quantity below minimum or off increment |
InvalidTotalSpend | Total spend calculation error |
DuplicateOrder | Duplicate client order ID |
InsufficientLiquidity | Not enough liquidity at price |
UnknownInstrument | Trading pair does not exist |
TERMS_NOT_ACCEPTED | Latest Prediction Markets terms not accepted. Use the REST terms endpoints to read, check, and accept terms before retrying. |
Cancellation Reasons
When an order is CANCELED by the system, the r field contains one of:
| Reason | Description |
|---|---|
SelfCrossPrevented | Self-trade prevention triggered |
FillOrKillWouldNotFill | FOK order could not fill completely |
ImmediateOrCancelWouldPost | IOC order would post to book |
MakerOrCancelWouldTake | MOC order would take liquidity |
AuctionCancelled | Auction-related cancellation |
ExceedsPriceLimits | Price moved beyond limits |
Balance Updates
Requires an authenticated session
| Schema | Frequency | Description |
|---|---|---|
balances@account | Real-time | Real time balance updates for the account associated with the authenticated API key |
balances@account@1s | Periodic (1s) | Periodic snapshot of all balances every second for the account associated with the authenticated API key |
The balances@account stream pushes updates in real time whenever a balance change occurs, and only includes the assets that changed. The balances@account@1s stream sends a complete snapshot of all account balances every second, regardless of whether they changed. On subscribe, balances@account@1s will immediately send the current balances if available.
Balance Update:
Code
| Field | Type | Description |
|---|---|---|
e | string | Event type ("balanceUpdate") |
E | number | Event time (nanoseconds) |
u | number | Time of the last account update (nanoseconds) |
B | array | Balance updates |
a | string | Asset code |
f | string | Available balance (amount available to trade) |
c | string | Confirmed balance (total balance including pending) |
Position Updates
Requires an authenticated session
| Schema | Frequency | Description |
|---|---|---|
positions@account | Real-time | Real time event-contract position updates for the account associated with the authenticated API key |
positions@account@1s | Periodic (1s) | Periodic snapshot of all open event-contract positions every second for the account associated with the authenticated API key |
The positions@account stream pushes deltas in real time on fill, position open/close, and event-contract settlement events, and only includes the rows that changed. A settlement close is delivered as a terminal row with position set to "0", followed by a settlement_payout amount carrying the payout currency and outcome. The positions@account@1s stream sends a complete snapshot of all open positions every second, regardless of whether they changed. On subscribe, positions@account@1s will immediately send the current positions if available.
Use positions@account for low-latency event-contract position deltas on the same WebSocket connection you use for trading. Reconcile with POST /v1/prediction-markets/positions after reconnects, missed messages, and settlement windows.
Connect to wss://ws.gemini.com. Authentication must be provided on the WebSocket upgrade — you cannot authenticate after the connection is established. Use either HMAC-signed API key headers (account-scoped only; master/group keys are rejected with HTTP 401) or an OAuth 2.0 bearer token (Authorization: Bearer <access_token>). See Authentication.
Subscribe after the connection opens:
Code
Server acknowledgement:
Code
Snapshot and delta frames share the same shape:
Code
| Field | Type | Description |
|---|---|---|
e | string | Event type, always positionReport |
E | number | Event timestamp in nanoseconds |
u | number | Last account update timestamp in nanoseconds |
A | number | Account ID |
P | array | Position rows for this account; an empty array means no open position rows are included |
P[].t | string | Product type. Event contracts use ec |
P[].s | string | Instrument symbol |
P[].a | array | Named amount array |
P[].a[].t | string | Amount label. Position quantity uses position; a settlement close also includes settlement_payout |
P[].a[].v | string | Decimal string amount. position is signed; settlement_payout is the payout amount |
P[].a[].c | string | Optional asset code. Settlement payouts use usd; position quantities omit this field |
P[].a[].o | string | Settlement outcome on settlement_payout: YES, NO, or UNSPECIFIED |
The first subscription for an account returns a snapshot of currently open positions. Subsequent frames are deltas carrying only rows that changed. A position close emits a row with position value "0" before that row is evicted; a settlement close includes settlement_payout and outcome in that same terminal row. Later snapshots omit zero-position rows. The a array is intentionally extensible; clients should ignore unknown amount labels instead of failing.
Settlements
Requires an authenticated session
There is no standalone settlements@account stream. Settlement details are delivered in the terminal positionReport delta on positions@account.
The terminal row contains a zero position amount and a settlement_payout amount. The payout amount uses c: "usd"; its o value is YES, NO, or UNSPECIFIED. Subscribe using the standard Position Updates request format.
Use POST /v1/prediction-markets/positions/settled for historical settled positions and reconciliation after reconnects or missed messages.
Contract Status
Prediction-market contract lifecycle events — status transitions (e.g. Awaiting Approval → Approved → Active) and strike-populated moments for Up/Down contracts.
| Schema | Frequency | Description |
|---|---|---|
contractStatus | Real-time | Status changes and strike-price updates for prediction-market contracts |
Code
| Field | Type | Description |
|---|---|---|
e | string | Event type (contractStatus) |
E | number | Event time (Unix milliseconds) |
s | string | Instrument symbol |
k | string | Event ticker |
c | string | Contract ticker (e.g. HI78999D63, UP, DOWN) |
i | number | Contract ID |
p | string | Strike price parsed from the contract ticker. Omitted for Up/Down contracts until the strike is set at activation |
o | string | Previous status |
n | string | New status |
For Up/Down contracts, p is omitted while the strike is unknown and included once it is set — subscribers can detect strike availability by the field's presence.