Commands

Commands & Subscriptions

This page covers the request/response commands available on the WebSocket API: querying instruments, managing subscriptions, and recovering missed messages.

Server Message Envelope

Every message sent by the server (both events and responses) includes the following fields:

FieldTypeDescription
kindstringMessage category: "event" or "response"
typestringSpecific message type (e.g., "trade", "auth", "index_price")
timestamp_msnumberServer timestamp in milliseconds (Unix epoch)
message_idstringUnique message identifier (UUID v4) for deduplication. If you receive the same message_id twice, the second is a duplicate and can be safely discarded.
seq_idnumberMonotonically increasing sequence number per connection, starting at 1. Used for message ordering and gap detection. If you observe a gap in seq_id values (e.g., received 5 then 7, missing 6), messages were lost and can be recovered using resend.

Example:

{
  "kind": "event",
  "type": "trade",
  "timestamp_ms": 1677721600000,
  "message_id": "550e8400-e29b-41d4-a716-446655440000",
  "seq_id": 42,
  "data": { ... },
  "subscription": { ... }
}

Request ID Correlation

All requests support an optional id field. The server echoes it back in the response for request-response matching:

// Request
{ "type": "auth", "id": "auth-request-1", "api_key": "your-api-key-here" }

// Response
{
  "kind": "response",
  "type": "auth",
  "id": "auth-request-1",
  "timestamp_ms": 1677721600000,
  "message_id": "550e8400-e29b-41d4-a716-446655440000",
  "seq_id": 1,
  "success": true
}

get_instruments

Retrieve available instruments for specified markets.

Request:

{
  "type": "get_instruments",
  "markets": ["BTC", "ETH", "ARB"]
}

The markets array should contain base tokens only (not pairs).

Response:

{
  "kind": "response",
  "type": "get_instruments",
  "id": "optional-request-id",
  "timestamp_ms": 1677721600000,
  "success": true,
  "instruments": [
    "BTC_USDC-31OCT25-130000-C",
    "BTC_USDC-PERPETUAL",
    "ETH_USDC-31OCT25-4700-P"
  ]
}

get_ob_state_by_instruments

Get the current orderbook state for specified instruments.

Request:

{
  "type": "get_ob_state_by_instruments",
  "instrument_names": ["BTC_USDC-31OCT25-130000-C", "BTC_USDC-PERPETUAL"]
}

The instrument_names parameter is optional. If not provided, returns orderbook state for all instruments.

get_ob_state_by_market

Get the current orderbook state for all instruments in a specific market.

Request:

{
  "type": "get_ob_state_by_market",
  "market": "BTC",
  "maturity": "31OCT25"
}

The maturity parameter is optional. If provided, filters instruments by expiration date.

Orderbook State Response Format

Both get_ob_state_by_instruments and get_ob_state_by_market return responses with type get_ob_state. The response structure varies by instrument type:

Options:

{
  "kind": "response",
  "type": "get_ob_state",
  "id": "optional-request-id",
  "timestamp_ms": 1677721600000,
  "success": true,
  "state": {
    "BTC_USDC-31OCT25-130000-C": {
      "timestamp": 1677721600000,
      "instrument_name": "BTC_USDC-31OCT25-130000-C",
      "index_price": 45000.5,
      "open_interest": 150.5,
      "last_price": 2500.0,
      "best_bid_price": 2495.0,
      "best_bid_amount": 1.5,
      "best_ask_price": 2505.0,
      "best_ask_amount": 1.0,
      "bids": [
        [2495.0, 1.5, "order_id_abc123"],
        [2490.0, 2.0, "order_id_def456"]
      ],
      "asks": [
        [2505.0, 1.0, "order_id_ghi789"],
        [2510.0, 1.8, "order_id_jkl012"]
      ],
      "positions": 25,
      "mark_iv": 0.65,
      "bid_iv": 0.64,
      "ask_iv": 0.66,
      "interest_rate": 0.05,
      "settlement_price": 0,
      "greeks": {
        "delta": 0.45,
        "gamma": 0.0012,
        "theta": -45.5,
        "vega": 125.3,
        "rho": 85.2
      }
    }
  }
}

Perpetuals:

{
  "kind": "response",
  "type": "get_ob_state",
  "id": "optional-request-id",
  "timestamp_ms": 1677721600000,
  "success": true,
  "state": {
    "BTC_USDC-PERPETUAL": {
      "timestamp": 1677721600000,
      "instrument_name": "BTC_USDC-PERPETUAL",
      "index_price": 45000.5,
      "open_interest": 2500000,
      "last_price": 45010.0,
      "current_funding": 0.0001,
      "best_bid_price": 45000.0,
      "best_bid_amount": 20000,
      "best_ask_price": 45020.0,
      "best_ask_amount": 30000,
      "bids": [
        [45000.0, 20000, "order_id_xyz789"],
        [44980.0, 40000, "order_id_uvw456"]
      ],
      "asks": [
        [45020.0, 30000, "order_id_rst123"],
        [45040.0, 20000, "order_id_mno789"]
      ]
    }
  }
}

Orderbook Array Format:

The bids and asks arrays contain price level information: [price, amount, order_id]

IndexFieldDescription
0pricePrice level (number)
1amountTotal volume at this price level (number)
2order_idUnique identifier for the order (string)

subscribe

Subscribe to specific data channels.

Request:

{
  "type": "subscribe",
  "subscriptions": [
    {
      "channel": "index_price",
      "query": {
        "pair": "BTC_USDC"
      }
    },
    {
      "channel": "orderbook_options",
      "query": {
        "instrument_name": "BTC_USDC-31OCT25-130000-C"
      }
    }
  ]
}

Response:

{
  "kind": "response",
  "type": "subscribe",
  "id": "optional-request-id",
  "timestamp_ms": 1677721600000,
  "success": true,
  "subscriptions": [
    {
      "channel": "index_price",
      "query": { "pair": "BTC_USDC" }
    },
    {
      "channel": "orderbook_options",
      "query": { "instrument_name": "BTC_USDC-31OCT25-130000-C" }
    }
  ]
}

unsubscribe

Unsubscribe from specific data channels.

Request:

{
  "type": "unsubscribe",
  "subscriptions": [
    {
      "channel": "index_price",
      "query": { "pair": "BTC_USDC" }
    }
  ]
}

Response:

{
  "kind": "response",
  "type": "unsubscribe",
  "id": "optional-request-id",
  "timestamp_ms": 1677721600000,
  "success": true,
  "subscriptions": [
    {
      "channel": "index_price",
      "query": { "pair": "BTC_USDC" }
    }
  ]
}

unsubscribe_all

Unsubscribe from all data channels.

Request:

{
  "type": "unsubscribe_all"
}

Response:

{
  "kind": "response",
  "type": "unsubscribe_all",
  "id": "optional-request-id",
  "timestamp_ms": 1677721600000,
  "success": true
}

get_subscriptions

List your active subscriptions.

Request:

{
  "type": "get_subscriptions"
}

Response:

{
  "kind": "response",
  "type": "get_subscriptions",
  "id": "optional-request-id",
  "timestamp_ms": 1677721600000,
  "success": true,
  "subscriptions": [
    {
      "channel": "index_price",
      "query": { "pair": "BTC_USDC" }
    },
    {
      "channel": "orderbook_options",
      "query": { "instrument_name": "BTC_USDC-31OCT25-130000-C" }
    }
  ]
}

resend (Message Recovery)

Request the server to re-send previously delivered messages by their seq_id range. Use this when you detect a gap in seq_id values, indicating missed messages.

Request:

{
  "type": "resend",
  "id": "resend-request-1",
  "begin_seq_id": 10,
  "end_seq_id": 15
}

Parameters:

ParameterRequiredDescription
begin_seq_idYesFirst sequence ID to resend (inclusive)
end_seq_idYesLast sequence ID to resend (inclusive)
  • begin_seq_id must be less than or equal to end_seq_id
  • Maximum range: 100 messages per request
  • end_seq_id must not exceed the current connection's sequence ID

Success Response:

The server first re-delivers the cached messages (each with their original seq_id and message_id), then sends the resend confirmation:

{
  "kind": "response",
  "type": "resend",
  "id": "resend-request-1",
  "timestamp_ms": 1677721600000,
  "message_id": "550e8400-e29b-41d4-a716-446655440000",
  "success": true,
  "begin_seq_id": 10,
  "end_seq_id": 15,
  "messages_sent": 6
}

Error - Range too large:

{
  "kind": "response",
  "type": "error",
  "id": "resend-request-1",
  "timestamp_ms": 1677721600000,
  "success": false,
  "error": {
    "type": "PAYLOAD_VALIDATION_ERROR",
    "message": "Resend range too large: 150 messages requested, maximum is 100"
  }
}

Error - Messages expired from cache:

{
  "kind": "response",
  "type": "error",
  "id": "resend-request-1",
  "timestamp_ms": 1677721600000,
  "success": false,
  "error": {
    "type": "PAYLOAD_VALIDATION_ERROR",
    "message": "Some messages in the requested range are no longer available in the cache (expired or evicted)",
    "data": {
      "missing_seq_ids": [10, 11]
    }
  }
}

Messages are cached per connection with a limited capacity (LRU eviction) and time-to-live. Old messages may no longer be available. Resent messages retain their original seq_id and message_id values — use message_id for deduplication. The resend request requires authentication. Rate limited to 5 requests per 10 seconds per API key owner.

Gap Detection Example

let expectedSeqId = 1;

function handleMessage(message: any) {
  if (message.seq_id && message.seq_id > expectedSeqId) {
    // Gap detected - request missing messages
    ws.send(JSON.stringify({
      type: 'resend',
      begin_seq_id: expectedSeqId,
      end_seq_id: message.seq_id - 1
    }));
  }
  // Only advance for new in-sequence messages;
  // resent messages have lower seq_id and should not rewind the counter
  if (message.seq_id && message.seq_id >= expectedSeqId) {
    expectedSeqId = message.seq_id + 1;
  }
}

Subscription Filtering

Many channels support advanced filtering to reduce the volume of events you receive.

Orderbook Filtering

For orderbook_options and orderbook_perps channels, you can filter events by:

  • pair (optional): Subscribe to all instruments for a specific trading pair
  • direction: Filter for only "buy" or "sell" orders
  • options.skip_snapshot: Skip initial orderbook state, receive only incremental updates

Maker filtering has been moved to the dedicated orderbook_maker channel.

Example - Subscribe to all BTC options with buy orders:

{
  "channel": "orderbook_options",
  "query": {
    "pair": "BTC_USDC",
    "direction": "buy"
  }
}

Example - Subscribe to all perpetual markets without initial snapshots:

{
  "channel": "orderbook_perps",
  "query": {
    "options": {
      "skip_snapshot": true
    }
  }
}

Query Options

OptionTypeDefaultDescription
skip_snapshotbooleanfalseSkip the initial orderbook snapshot when subscribing. Only applies to orderbook_options and orderbook_perps channels. When set to true, you'll only receive incremental updates (post_order, cancel_order, update_order events) without the initial state. Note: Skipping the snapshot and relying only on duplicate subscription detection prevents sending snapshots for already-subscribed channels.