WebSockets
The WebSocket gateway provides real-time streaming access to market data and trading updates on the Ethereal exchange. Clients subscribe to channels over a persistent connection and receive plain JSON payloads with short-form keys, optimized for low latency, minimal overhead, and fast parsing.
wss://ws2.ethereal.trade/v1/stream
Live on Mainnet
Native WebSocket (v2) replaces socketio. Visit Socket.io (deprecated) for socket.io based streams.
Subscription
The subscription gateway offers multiple data streams for real-time and periodic updates. Some channels e.g. OrderUpdate push messages immediately as they occur, while others e.g. L2Book emit messages at fixed intervals. Payload formats and message shapes are documented below.
Connection Behaviour
Connections have a maximum lifetime of approximately 4 hours, after which they are closed with code 1000. Clients are encouraged to implement automatic reconnection to handle this.
Idle connections with no message activity between both parties are closed after 2 minutes. The server sends pings automatically to keep active connections alive to prevent closing idle connections, no client-side heartbeat is required.
There is a per-connection limit on subaccount subscriptions.
Each (subaccountId, streamType) pair counts as one subscription. Market data channels (L2Book, Ticker, TradeFill) are not subject to this limit.
Exceeding the limit returns { ok: false, code: "SUBSCRIPTION_LIMIT_EXCEEDED" }
L2Book
L2Book Provides L2 book depth updates for a specific product.
L2_BOOK events are emitted on a configurable fixed interval (as of writing, this is configured to be once every 200ms).
e- event namet- server timestamp (epoch in milliseconds)data- L2 Book price levels detailss- symbol e.g. BTCUSDt- calculated book timestamp (epoch in milliseconds)pt- previous calculated book timestamp (epoch in milliseconds) - optionalUsing both the
ptanddata.tyou can infer whether or not any events were missed during connection or during consumption
a- asks, array of[price, qty]pairsb- bids, array of[price, qty]pairs
A L2Book message of the current book (up to 100 price levels per side) is emitted back as an initial snapshot on connection. Every subsequent message is a price level diff with absolute quantities. A zero quantity price diff indicates that this level has been removed.
TICKER
TICKERDelivers real-time ticker data feeds for a specified product.
TICKER events are emitted on a configurable fixed interval (currently configured to be once every second).
e- event nameTickert- server timestamp this message was emitted at (epoch in milliseconds)data- Real time ticker datas- symbol e.g. BTCUSDt- calculated best bid / ask book timestampbidPx- best bid priceaskPx- best ask pricebidAmt- total quantity at the best bidaskAmt- total quantity at the best askmarkPx- current mark pricemarkPx24h- 24h mark priceoi- open interestfr1h- projected funding rate at the end of the hourvol24h- past 24 hours volume
In extreme cases, Ticker will skip publishing if both bidPx & askPx are not available. All values are returned as decimals (9 precision).
TRADE_FILL
TRADE_FILLProvides a stream of trades that have occurred filtered by product.
TRADE_FILL events are streamed in real-time as they occur and from the perspective of the taker (i.e. sz, sd).
e- event namet- server timestamp this message was emitted at (epoch in milliseconds)datas- symbol of product tradedt- timestamp trade fills happened (epoch in milliseconds)d- array of fills that occurred on the products- symbol e.g. BTCUSD where the trade fill occurred onid- trade fill identifierpx- execution pricesz- quantity tradedsd- side (0=BUYor1=SELL) from the perspective of the takersids- tuple of the taker subaccount id and the maker subaccount id
SUBACCOUNT_LIQUIDATION
SUBACCOUNT_LIQUIDATIONProvides an update when a subaccount is liquidated.
When a subaccount is liquidated, all positions are transferred to the insurance fund and derisked at a later time. SubaccountLiquidation events are emitted in real-time.
e- event namet- server timestamp this message was emitted at (epoch in milliseconds)data- Liquidation subaccount datasid-idof liquidated sub-accountt- timestamp sub-account was liquidated (epoch in miliseconds)d- An array of positions liquidated (subaccount may have one or many positions at liquidation):price- mark price at the time of liquidationsz- position size at liquidation (positive of long, negative if short)
POSITION_UPDATE
POSITION_UPDATEProvides real-time updates to open positions for a specific subaccount.
POSITION_UPDATE events are emitted in real-time, published per-subaccount whenever a position is opened, increased/reduced, or closed.
e- event namet- server timestamp (epoch in milliseconds)data- position update detailst- update timestamp (epoch in milliseconds)d- array of position updatesid- position ID (UUID)sid- subaccount ID (UUID)s- ticker symbol (e.g. ETHUSD or BTCUSD)sd- position side (BUY or SELL)sz- position sizecost- position value in USD (quantity * average entry price)rpnl- realized PnL in USDfpnl- funding in USD (charged and applied to position, negative if paid)fee- fees accrued in USDlpx- liquidation price (only set if liquidated)
Funding charges do not trigger PositionUpdate events.
ORDER_UPDATE
ORDER_UPDATE Provides updates about order status changes for a specific subaccount.
ORDER_UPDATE events are emitted in real-time, published per-subaccount whenever an order's state changes.
e- event namet- server timestamp (epoch in milliseconds)data- order update detailst- update timestamp (epoch in milliseconds)d- array of order updatesid- order ID (UUID)cloid- client order IDotyp- order typeqty- original quantityaqty- available (remaining) quantityfill- filled amountpx- limit price - optional, omitted for market orderssd- side (BUY=0,SELL=1)s- symbol e.g. BTCUSDsid- subaccount ID (UUID)sn- sender (signer EVM address)Account or linked signer address that originally placed this order
st- order statust- order created timestamp (epoch in milliseconds)ro- reduce only (boolean)cl- close (boolean)tif- time in forceet- expires at (epoch in seconds)po- post onlyspx- stop pricestyp- stop typespxtyp- stop price typetr- triggered stategtyp- group contingency typegid- group ID (UUID)
ORDER_FILL
ORDER_FILLNotifies when orders are filled for a specific subaccount.
ORDER_FILL events are emitted in real-time as they occur, published per-subaccount whenever an order is filled (both maker and taker sides receive their own event).
e- event namet- server timestamp (epoch in milliseconds)data- order fill detailst- fill timestamp (epoch in milliseconds)d- array of order fillsid- fill ID (UUID)oid- order ID (UUID)cloid- client order ID - optionalpx- fill pricesz- filled quantitytyp- order typesd- sides- symbol e.g. BTCUSDsid- subaccount ID (UUID)ro- reduce onlyfee- fee in USDm- is makert- created at timestamp (epoch in milliseconds)
TOKEN_TRANSFER
TOKEN_TRANSFERProvides updates for deposits / withdrawals for a specific subaccount.
TOKEN_TRANSFER events are published per-subaccount when a deposit or withdrawal state changes.
e- event namet- server timestamp this message was emitted at (epoch in milliseconds)data- token transfer detailsid- unique identifier of the transfert- timestamp token transfer event (epoch in miliseconds)sid- subaccount id that owns this transfertName- token nametAddr- token contract addresstyp- transfer type, one of:"DEPOSIT","WITHDRAW"st- transfer status, one of:"SUBMITTED","PENDING","COMPLETED","REJECTED"amt- transfer amountfee- transaction feeiniBk- block number when the transfer was initiated (optional)finBk- block number when the transfer was finalized (optional)iniTx- Transaction hash of the initiation transaction (optional)finTx- Transaction hash of the finalization transaction (optional)lzAddr- LayerZero destination address for cross-chain bridge transfers (optional)lzEid- LayerZero endpoint id identifying the destination chain
Unsubscribing from Channels
To unsubscribe from a channel, send the same payload used to subscribe but with unsubscribe as the event type. Alternatively, disconnecting your entire connection will end all subscriptions. Note that reconnecting will consume rate limits. See System Limits for more details.
Exception Handling
Error responses are returned directly as a reply to the originating event (e.g. subscribe, unsubscribe). They follow a unified shape:
okindicates whether the request succeededcodea machine-readable error code present whenokisfalse
UNKNOWN_PRODUCT
The provided symbol does not match any known product.
VALIDATION_ERROR
The request payload failed validation (e.g. missing or invalid fields).
SUBSCRIPTION_FAILED
The server was unable to subscribe to the requested topic.
UNSUBSCRIBE_FAILED
The server was unable to unsubscribe from the requested topic.
RATE_LIMIT
Too many requests, the client has been rate-limited.
INTERNAL_ERROR
An unexpected server-side error occurred.
SUBSCRIPTION_LIMIT_EXCEEDED
Too many subaccount subscriptions on this connection.
A successful response would simply just return { "ok": true, ... }
Last updated
