Real-Time Feed

Subscription Model

Use subscribe and unsubscribe operations to manage channel subscriptions:

json
{"operation": "subscribe", "channel": "orderbook", "params": {"symbols": ["SOMI:USDso"]}}
{"operation": "unsubscribe", "channel": "orderbook", "params": {"symbols": ["SOMI:USDso"]}}

Heartbeat

Send {"operation": "ping"} to receive {"operation": "pong"}. Connections close after 60 seconds of inactivity. Send a ping at least every 30 seconds to avoid being disconnected. The ping doubles as a liveness check: if you do not receive a pong within your own timeout, treat the connection as dead and reconnect (see Reconnecting and resuming). See the Errors page for the full list of close codes and connection-level failures.

Reconnecting and resuming

The feed does not provide a sequence number or resume cursor. There is no way to replay messages missed while disconnected, and no gapless snapshot-to-live handoff - so treat every reconnect as a cold start:

  1. Reconnect with exponential backoff (a 1001 Going Away close or a shutdown message means the server is cycling - back off and retry).
  2. Re-subscribe to every channel you need. Market-data channels (orderbook, ohlcv, trades) reply with a fresh snapshot, so your local state is rebuilt from scratch - discard any pre-disconnect state rather than merging.
  3. Re-fetch authoritative state over REST for anything the stream cannot resnapshot. In particular, after any disconnect re-read open orders and balances via the HTTP API rather than assuming your in-memory view survived.

Because there is no seqNum, a silent mid-stream gap is indistinguishable from a quiet market. Bots that must not miss an update should periodically reconcile against REST (order state, balances) as a backstop, and reconnect on any missed heartbeat.

Order Lifecycle Tracking

There is no account-wide order or fills channel. The order channel is per-orderId - you subscribe to one specific order and receive its lifecycle events. Subscribing once and waiting for fills across all your orders is not supported; track each order you place.

The tracking flow for a single order:

  1. Prepare and submit the order (HTTP API or on-chain), then extract its orderId from the OrderPlaced event / prepared-order response.
  2. Subscribe to the order channel with that orderId:
    json
    {"operation": "subscribe", "channel": "order", "params": {"symbol": "SOMI:USDso", "orderId": "0xYourOrderId"}}
    
  3. Consume order:update events until the order reaches a terminal order.status of filled or cancelled (an expired order surfaces as cancelled). See the order:update message schema below for the full status set.
  4. Unsubscribe once terminal to free the subscription.

Own-fill attribution. The public trades channel carries market-wide executed trades and does not attribute fills to your account - do not use it to detect your own fills. Use the per-order order channel for maker/resting orders. For high-churn IOC/taker loops, subscribing and unsubscribing per order adds latency; reconciling wallet/vault balances (or reading the transaction receipt logs) is usually the better pattern there - see Choosing between REST and WebSocket.

Subscribing to an unsupported channel name returns an unknown_channel error; valid channel names with bad params return subscription_failed. See Errors.

Table of Contents

Connection

Endpoint:

EnvironmentPublic feed
Mainnet (Somnia)wss://api.dreamdex.io/v0/ws/public
Testnet (Somnia Shannon)wss://stg.api.dreamdex.io/v0/ws/public

Close Codes

The server uses standard and application-specific WebSocket close codes. See the Errors page for close codes, connection-level failures, and application-level error messages.

Client Messages

Messages sent by the client to the server.

ping - Heartbeat ping

Receives a ping message from the client. The server immediately responds with a pong message. Clients should send pings periodically to prevent the connection from timing out after 60 seconds of inactivity.

Request Format

FieldTypeDescriptionConstraintsRequired
operationstring-"ping"required

Response

The server responds with:

  • Pong: Server heartbeat response

subscribe - Subscribe to data feed

Receives a subscription request from the client. The server validates the request parameters and, if successful, begins streaming the requested data. The client receives a subscribed confirmation followed by an initial snapshot, then incremental updates as data changes.

Request Format

FieldTypeDescriptionConstraintsRequired
operationstring-"subscribe"required
channelstring-"orderbook", "ohlcv", "trades", "order"required
paramsobjectChannel-specific parameters-required

Examples

Subscribe to order book
json
{
  "operation": "subscribe",
  "channel": "orderbook",
  "params": {
    "symbols": [
      "SOMI:USDso",
      "WBTC:USDso"
    ]
  }
}
Subscribe to OHLCV
json
{
  "operation": "subscribe",
  "channel": "ohlcv",
  "params": {
    "symbol": "SOMI:USDso",
    "timeframe": "1m"
  }
}
Subscribe to trades
json
{
  "operation": "subscribe",
  "channel": "trades",
  "params": {
    "symbols": [
      "SOMI:USDso"
    ],
    "limit": 100
  }
}
Subscribe to order updates
json
{
  "operation": "subscribe",
  "channel": "order",
  "params": {
    "orderId": "0x1234567890abcdef"
  }
}

Response

The server responds with one of:

  • Subscribed: Subscription successful
  • Error: Request failed

unsubscribe - Unsubscribe from data feed

Receives an unsubscription request from the client. The server stops sending updates for the specified data feed and confirms with an unsubscribed message.

Request Format

FieldTypeDescriptionConstraintsRequired
operationstring-"unsubscribe"required
channelstring-"orderbook", "ohlcv", "trades", "order"required
paramsobject--required

Response

The server responds with one of:

  • Unsubscribed: Unsubscription successful
  • Error: Request failed

Server Messages

Messages sent by the server to connected clients.

pong - Heartbeat pong

Sends a pong response to the client after receiving a ping. This confirms the connection is alive and resets the inactivity timeout.

Message Format

FieldTypeDescriptionConstraintsRequired
operationstring-"pong"required

subscribed - Subscription confirmed

Confirms a successful subscription. Sent immediately after processing a valid subscribe request. The confirmation echoes back the subscription parameters so the client can verify which data feed was activated.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring--required
typestring-"subscribed"required
symbolsarray--optional
symbolstring--optional
timeframestring--optional
orderIdstring--optional

Examples

Order book subscription confirmed
json
{
  "channel": "orderbook",
  "type": "subscribed",
  "symbols": [
    "SOMI:USDso"
  ]
}

unsubscribed - Unsubscription confirmed

Confirms a successful unsubscription. After this message, the client will no longer receive updates for the specified data feed.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring--required
typestring-"unsubscribed"required
symbolsarray--optional
symbolstring--optional
timeframestring--optional
orderIdstring--optional

error:error - Error response

Sends an error message when a client request cannot be processed. This may occur due to invalid parameters, unknown channels, or server-side issues. The message field contains a human-readable error description.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"error"required
typestring-"error"required
messagestring--required

orderbook:snapshot - Order book snapshot

Sends the complete order book state immediately after a client subscribes to the orderbook channel. Contains aggregated price levels with total quantity at each price. Bids are sorted by price descending (highest first), asks are sorted ascending (lowest first). Clients should use this to initialize their local order book state before applying incremental updates.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"orderbook"required
typestring-"snapshot"required
symbolstring--required
bidsarray--required
bids[].pricestringPrice as decimal string for precision (e.g., "1.23456789")pattern: ^[0-9]+(\.[0-9]+)?$required
bids[].quantitystringQuantity as decimal string. "0" means remove the level.pattern: ^[0-9]+(\.[0-9]+)?$required
asksarray--required
asks[].pricestringPrice as decimal string for precision (e.g., "1.23456789")pattern: ^[0-9]+(\.[0-9]+)?$required
asks[].quantitystringQuantity as decimal string. "0" means remove the level.pattern: ^[0-9]+(\.[0-9]+)?$required
timestampinteger-format: int64required

Examples

SOMI:USDso order book with 2 bid and 2 ask levels
json
{
  "channel": "orderbook",
  "type": "snapshot",
  "symbol": "SOMI:USDso",
  "bids": [
    {
      "price": "1.24",
      "quantity": "1500"
    },
    {
      "price": "1.23",
      "quantity": "3200"
    }
  ],
  "asks": [
    {
      "price": "1.26",
      "quantity": "800"
    },
    {
      "price": "1.27",
      "quantity": "2100"
    }
  ],
  "timestamp": 1765534169841
}

orderbook:update - Order book update

Sends incremental order book changes as they occur. Each update contains changed price levels in the bids and/or asks arrays. A quantity of zero means the level was removed from the book.

Apply updates by replacing the quantity at each price level, or removing the level if the quantity is zero.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"orderbook"required
typestring-"update"required
symbolstring--required
bidsarray--optional
bids[].pricestringPrice as decimal string for precision (e.g., "1.23456789")pattern: ^[0-9]+(\.[0-9]+)?$required
bids[].quantitystringQuantity as decimal string. "0" means remove the level.pattern: ^[0-9]+(\.[0-9]+)?$required
asksarray--optional
asks[].pricestringPrice as decimal string for precision (e.g., "1.23456789")pattern: ^[0-9]+(\.[0-9]+)?$required
asks[].quantitystringQuantity as decimal string. "0" means remove the level.pattern: ^[0-9]+(\.[0-9]+)?$required
timestampinteger-format: int64required

Examples

New bid and removed ask
json
{
  "channel": "orderbook",
  "type": "update",
  "symbol": "SOMI:USDso",
  "bids": [
    {
      "price": "1.25",
      "quantity": "500"
    }
  ],
  "asks": [
    {
      "price": "1.26",
      "quantity": "0"
    }
  ],
  "timestamp": 1765534170000
}

ohlcv:snapshot - OHLCV candle history

Sends historical candlestick data immediately after a client subscribes to the ohlcv channel. Contains recent candles for the requested symbol and timeframe. Clients should use this to populate charts before receiving live updates.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"ohlcv"required
typestring-"snapshot"required
symbolstring--required
timeframestring-"1m", "5m", "15m", "1h", "4h", "1d"required
candlesarray--required
candles[].timestampinteger-format: int64required
candles[].openstringOpening price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
candles[].highstringHighest price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
candles[].lowstringLowest price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
candles[].closestringClosing price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
candles[].volumestringTrading volume as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required

Examples

Two 1-minute candles for SOMI:USDso
json
{
  "channel": "ohlcv",
  "type": "snapshot",
  "symbol": "SOMI:USDso",
  "timeframe": "1m",
  "candles": [
    {
      "timestamp": 1765534080000,
      "open": "1.24",
      "high": "1.27",
      "low": "1.23",
      "close": "1.26",
      "volume": "15000.5"
    },
    {
      "timestamp": 1765534140000,
      "open": "1.26",
      "high": "1.28",
      "low": "1.25",
      "close": "1.27",
      "volume": "12300"
    }
  ]
}

ohlcv:update - OHLCV candle update

Sends a new or updated candlestick as trading occurs. If the candle timestamp matches an existing candle, the client should replace it (the candle is still forming). A new timestamp indicates the previous candle closed and a new one started.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"ohlcv"required
typestring-"update"required
symbolstring--required
timeframestring--required
candleobject--required
candle.timestampinteger-format: int64required
candle.openstringOpening price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
candle.highstringHighest price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
candle.lowstringLowest price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
candle.closestringClosing price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
candle.volumestringTrading volume as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required

Examples

Updated 1-minute candle
json
{
  "channel": "ohlcv",
  "type": "update",
  "symbol": "SOMI:USDso",
  "timeframe": "1m",
  "candle": {
    "timestamp": 1765534200000,
    "open": "1.27",
    "high": "1.29",
    "low": "1.26",
    "close": "1.28",
    "volume": "8500"
  }
}

trades:snapshot - Recent trades history

Sends recent trade history immediately after a client subscribes to the trades channel. Contains the most recent trades up to the requested limit (default 100). Trades are ordered by timestamp descending (newest first).

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"trades"required
typestring-"snapshot"required
symbolstring--required
tradesarray--required
trades[].idstring--required
trades[].pricestringTrade price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
trades[].quantitystringTrade quantity as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
trades[].sidestring-"buy", "sell"required
trades[].timestampinteger-format: int64required

Examples

Two recent trades for SOMI:USDso
json
{
  "channel": "trades",
  "type": "snapshot",
  "symbol": "SOMI:USDso",
  "trades": [
    {
      "id": "trade001",
      "price": "1.25",
      "quantity": "100",
      "side": "buy",
      "timestamp": 1765534169000
    },
    {
      "id": "trade002",
      "price": "1.26",
      "quantity": "50",
      "side": "sell",
      "timestamp": 1765534168000
    }
  ]
}

trades:update - New trade executed

Sends a trade notification when an order is filled. Each update contains a single trade with its price, quantity, and aggressor side. Clients receive this in real-time as trades execute on the exchange.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"trades"required
typestring-"update"required
symbolstring--required
tradeobject--required
trade.idstring--required
trade.pricestringTrade price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
trade.quantitystringTrade quantity as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
trade.sidestring-"buy", "sell"required
trade.timestampinteger-format: int64required

Examples

Buy order filled
json
{
  "channel": "trades",
  "type": "update",
  "symbol": "SOMI:USDso",
  "trade": {
    "id": "trade003",
    "price": "1.27",
    "quantity": "75",
    "side": "buy",
    "timestamp": 1765534170000
  }
}

order:snapshot - Order state snapshot

Sends the current state of a specific order immediately after a client subscribes to the order channel. Contains full order details including filled quantity and current status. Use this to initialize order tracking before receiving status updates.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"order"required
typestring-"snapshot"required
orderobject--required
order.idstringUnique order identifier-required
order.marketstringMarket symbol (e.g., SOMI:USDso)-required
order.sidestring-"buy", "sell"required
order.pricestringLimit price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
order.quantitystringOriginal order quantity as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
order.filledstringAmount filled so far as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
order.statusstringCurrent order status"open", "partial", "filled", "cancelled"required
order.createdAtintegerUnix timestamp (ms) when order was createdformat: int64required
order.updatedAtintegerUnix timestamp (ms) when order was last updatedformat: int64required

Examples

Partially filled buy order
json
{
  "channel": "order",
  "type": "snapshot",
  "order": {
    "id": "0x1234567890abcdef",
    "market": "SOMI:USDso",
    "side": "buy",
    "price": "1.25",
    "quantity": "1000",
    "filled": "250",
    "status": "partial",
    "createdAt": 1765534160000,
    "updatedAt": 1765534169000
  }
}

order:update - Order status changed

Sends an order status update when the order state changes. This includes partial fills, complete fills, and cancellations. The update contains the complete current order state, not just the changes.

Message Format

FieldTypeDescriptionConstraintsRequired
channelstring-"order"required
typestring-"update"required
orderobject--required
order.idstringUnique order identifier-required
order.marketstringMarket symbol (e.g., SOMI:USDso)-required
order.sidestring-"buy", "sell"required
order.pricestringLimit price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
order.quantitystringOriginal order quantity as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
order.filledstringAmount filled so far as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
order.statusstringCurrent order status"open", "partial", "filled", "cancelled"required
order.createdAtintegerUnix timestamp (ms) when order was createdformat: int64required
order.updatedAtintegerUnix timestamp (ms) when order was last updatedformat: int64required

Examples

Order partially filled
json
{
  "channel": "order",
  "type": "update",
  "order": {
    "id": "0x1234567890abcdef",
    "market": "SOMI:USDso",
    "side": "buy",
    "price": "1.25",
    "quantity": "1000",
    "filled": "500",
    "status": "partial",
    "createdAt": 1765534160000,
    "updatedAt": 1765534175000
  }
}
Order fully filled
json
{
  "channel": "order",
  "type": "update",
  "order": {
    "id": "0x1234567890abcdef",
    "market": "SOMI:USDso",
    "side": "buy",
    "price": "1.25",
    "quantity": "1000",
    "filled": "1000",
    "status": "filled",
    "createdAt": 1765534160000,
    "updatedAt": 1765534180000
  }
}

shutdown - Server shutting down

Notifies all connected clients that the server is shutting down gracefully. Clients should close their connections and reconnect to a different server or retry after a delay. This message is broadcast to all clients before the server terminates connections.

Message Format

FieldTypeDescriptionConstraintsRequired
typestring-"shutdown"required
messagestringHuman-readable shutdown reason-required

Examples

Graceful shutdown notification
json
{
  "type": "shutdown",
  "message": "server shutting down"
}

Data Types

Reusable schema definitions.

PriceLevel

FieldTypeDescriptionConstraintsRequired
pricestringPrice as decimal string for precision (e.g., "1.23456789")pattern: ^[0-9]+(\.[0-9]+)?$required
quantitystringAggregate quantity at this price level as decimal string. "0" means the level was removed.pattern: ^[0-9]+(\.[0-9]+)?$required

Candle

FieldTypeDescriptionConstraintsRequired
timestampinteger-format: int64required
openstringOpening price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
highstringHighest price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
lowstringLowest price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
closestringClosing price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
volumestringTrading volume as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required

Trade

FieldTypeDescriptionConstraintsRequired
idstring--required
pricestringTrade price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
quantitystringTrade quantity as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
sidestring-"buy", "sell"required
timestampinteger-format: int64required

Order

FieldTypeDescriptionConstraintsRequired
idstringUnique order identifier-required
marketstringMarket symbol (e.g., SOMI:USDso)-required
sidestring-"buy", "sell"required
pricestringLimit price as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
quantitystringOriginal order quantity as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
filledstringAmount filled so far as decimal stringpattern: ^[0-9]+(\.[0-9]+)?$required
statusstringCurrent order status"open", "partial", "filled", "cancelled"required
createdAtintegerUnix timestamp (ms) when order was createdformat: int64required
updatedAtintegerUnix timestamp (ms) when order was last updatedformat: int64required