Skip to main content
The Rails WebSocket API provides real-time contracts, quotes, order books, trades, positions, and account state, and is used to place and manage orders — with the guarantees required by professional trading systems. It is designed to remain predictable, secure, and low-latency even during periods of extreme market activity. The API adopts a subscription model that gives you control over which real-time streams your connection receives. Streams can be requested at connection time via query parameters, or added and removed afterwards using explicit requests.

URL


Authorizations

See Get Access Token on how to retrieve the token. Set Sec-WebSocket-Protocol during the handshake or on connect().
string
required
Example value (authorization token):

Query Parameters

string
required
Always options for this API.
string
required
Market name. Example value: BTC-USDT. To connect across every contract on every market, use the value ALL.
string
Expiration of the contracts to filter on. Day, three-letter month, two-digit year — e.g. 24JUN26, 1JUN26, 31DEC26. Omit to match every expiration for the market.
string
Strike price of the contracts to filter on — e.g. 62000. Must be a positive number. Requires expiration. Omit to match every strike.
string
Option type: C (call) or P (put). Requires strike. Omit to match both calls and puts.
string
Comma-separated list of streams to subscribe on connect — e.g. optionsQuotes,optionsPositions. Any of the Supported Streams may be listed. Defaults to optionsOrders if omitted.
string
UUID identifying a session. Enables WebSocket Session on the Order Creation Stream (subscription type optionsOrders). Omit to opt out.

Contract Filter

The market, expiration, strike, and type query parameters compose into a contract filter that scopes the connection: The filter narrows left to right, and each level requires the one before it: expiration requires market, strike requires expiration, and type requires strike. Each may be omitted to widen the match; a parameter sent with a blank value is treated as omitted. market takes the market only — the rest of the contract goes in expiration, strike, and type. An invalid filter is reported with one of these error slugs: At connect time, all of them reject the WebSocket handshake with 400 Bad Request: Invalid filter parameters provided — except a wholly missing market, which returns 400 Bad Request: Missing required market parameter instead. No connection is established, so the slug is not delivered on the socket. The same filter composes on subscribe and unsubscribe requests, where an invalid one is answered with a 400 error message carrying the slug in data.error while the connection stays open.
The contract filter applies to the connection and to subscribe / unsubscribe requests. The emitOptions* snapshot requests are different: they take a packed contract name in content.market (e.g. BTC-10JUL26-55000-C, or ALL), while emitOptionsContracts and emitOptionsQuotes take underlying and expirationDate instead, and emitOptionsAccountSummary takes no market at all. When content.market is omitted, the connection’s own filter is used, and the request can fail with invalid_market if that filter does not resolve to a value the request accepts.
While the WebSocket API supports connecting with market=ALL for convenience, we strongly recommend keeping each connection’s contract filter as narrow as possible — one contract, or one expiration, per connection. Why? Using market=ALL means a single WebSocket connection is responsible for all contract data and events. If that connection experiences issues (e.g., network instability, client-side bugs, or resource exhaustion), it can disrupt data for all contracts at once. In contrast, narrow connections isolate risk: a problem with one connection will not impact the others. Best Practice:
  • Use a narrow filter (e.g. market=BTC-USDT&expiration=24JUN26&strike=62000&type=C) to create one connection per contract — or per expiration — you care about.
  • Reserve market=ALL for development, quick testing, or when you are certain your client can robustly handle all contracts in a single connection.
This approach ensures greater reliability and fault isolation for production trading systems.

Request Envelope

All WebSocket requests follow the same top-level structure:
  • message defines the request type
  • content contains request-specific parameters (can be omitted if no parameters)
  • An optional clientRequestId field is supported for correlation, and must be a UUID, unique per request
Reusing a clientRequestId on createOrder, modifyOrder, or cancelOrder within 60 seconds returns a 409 — the original request stands and is not executed a second time.
resultType echoes the message of the request that was rejected.

Response Envelope

All WebSocket responses and stream messages follow a consistent top-level structure:
  • resultType identifies the type of response or message (e.g., “optionsContracts”, “publicOrderBookDelta”)
  • data contains the response or message payload, including a statusCode
  • Where relevant, market appears as a top-level field alongside resultType and data

Dynamic Subscriptions

Streams are added and removed after connecting with explicit subscribe and unsubscribe requests. Subscriptions are scoped by product: only options streams can be subscribed on a product=options connection. Stream names are validated the same way wherever you send them, and a single bad name rejects the whole request — no subscription is applied. At connect, an unrecognized name in subscriptions, or a perpetuals one (orders, trades, publicTrades, publicOrderBook), rejects the handshake with 400 Bad Request: Invalid subscription parameter provided. In a subscribe or unsubscribe request, an unrecognized name is rejected with invalid_subscriptions and a perpetuals one with wrong_product_subscriptions. Every stream follows the connection’s contract filter, or the filter composed on the subscribe request that added it. The one exception is optionsAccountSummary, which is account-wide — any contract filter is ignored for it.

Common Requests

Ping, subscribe, unsubscribe, and the connection shutdown notice - available even without any subscription

Supported Streams

Check out their respective documentation for details on the data they provide and any supported requests.

Order Creation Stream

Create, modify, and cancel orders, with fill notifications

Contracts Stream

Contract definitions with live mark price, IV, and Greeks

Quotes Stream

Top-of-book bid/ask with implied volatility per contract

Order Book Stream

Full order book snapshots and deltas for a contract

Public Trades Stream

Real-time public trade executions for a contract

Positions Stream

Open positions with mark price, margin, and PnL

Open Orders Stream

Your open orders and incremental updates

Recent Orders Stream

Recent order history

Account Summary Stream

Balance, margin used, and PnL

Settlements Stream

Settlement results at expiry

Deterministic Delivery

Multiple WebSocket connections with an identical contract filter and identical subscription parameters receive the same sequence of events with no per-connection filtering or divergence. This enables:
  • Multiple parallel connections for redundancy
  • Hot standby consumers for failover
  • Independent processes handling the same events
  • Focused connections for specific stream subsets