Messages
WebSocket endpoint provides real-time market data streaming which works in Subscribe-Publish communication model. After establishing a WebSocket connection with us, you will need to send a Hello message documented below.
Messages
Trades (IN)
Trade message JSON is structured like this:
{
"type": "trade",
"symbol_id": "BITSTAMP_SPOT_BTC_USD",
"sequence": 2323346,
"time_exchange": "2013-09-28T22:40:50.0000000Z",
"time_coinapi": "2017-03-18T22:42:21.3763342Z",
"uuid": "770C7A3B-7258-4441-8182-83740F3E2457",
"price": 770.000000000,
"size": 0.050000000,
"taker_side": "BUY"
}Trade message is sent for every executed transaction (orderbook match).
Message variables
| Variable | Description |
|---|---|
| type | Message type, always trade |
| symbol_id | Our symbol identifier, format documented here |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| time_exchange | Time of trade reported by exchange |
| time_coinapi | Time when coinapi first received trade from exchange |
| uuid | Our unique trade identifier in form of UUIDv4 |
| price | Price of the transaction |
| size | Base asset amount traded in transaction (if a value is equal to zero, then transaction price just marking a data point eg. in the index time series) |
| taker_side | Aggressor side of the transaction (BUY/SELL/BUY_ESTIMATED/SELL_ESTIMATED/UNKNOWN) |
Possible taker_side values
If exchange has not reported who the aggressor side of the transaction was, then we will classify who it most probably was based on current market view.
taker_side | Description |
|---|---|
BUY | Exchange has reported that transaction aggressor was buying |
SELL | Exchange has reported that transaction aggressor was selling |
BUY_ESTIMATED | Exchange has not reported transaction aggressor, we estimated that more likely it was buying |
SELL_ESTIMATED | Exchange has not reported transaction aggressor, we estimated that more likely it was selling |
UNKNOWN | Exchange has not reported transaction aggressor and we have not estimated who it was |
[!TIP]
To classify who the aggressor of the transaction was, we use a proprietary algorithm that extends the method described in the paper "Inferring trade direction from intraday data (1991) by Lee and Ready"
Trades L4 (Transactions) (IN)
[!NOTE]
The
trade_l4data type is available only on the Hyperliquid L4 WS DS data source.
{
"time_exchange": "2026-06-09T08:40:42.2680000Z",
"time_coinapi": "2026-06-09T08:40:42.4291928Z",
"uuid": "17e8da4f-6541-48d5-b87c-2c10c38c7ab8",
"price": 1677.6,
"size": 0.0275,
"taker_side": "BUY",
"user_taker": "0xea928063cd1b5969c73699355b96103210529bda",
"user_maker": "0xf5d81a135f756ca16544e53c20fc20643ec3ad53",
"symbol_id": "HYPERLIQUIDL4_PERP_ETH_USDC",
"sequence": 1,
"type": "trade_l4"
}A trade_l4 message is sent for every Hyperliquid executed transaction where L4 user attribution is available.
It extends the standard trade message with the taker and maker user addresses reported by Hyperliquid.
Message variables
| Variable | Description |
|---|---|
| time_exchange | Exchange time of the trade execution. |
| time_coinapi | CoinAPI time when the trade was received from the exchange. |
| uuid | Exchange-provided unique identifier for the trade. |
| price | Trade execution price. |
| size | Executed trade size. |
| taker_side | Aggressor side of the trade. Possible values are BUY and SELL. |
| user_taker | User or account identifier associated with the taker side, as provided by the exchange. |
| user_maker | User or account identifier associated with the maker side, as provided by the exchange. |
| symbol_id | Our symbol identifier, format documented here. For this message type, the symbol belongs to the HYPERLIQUIDL4 exchange. |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| type | Message type, always trade_l4 |
Possible taker_side values
taker_side | Description |
|---|---|
BUY | The taker was buying. |
SELL | The taker was selling. |
Quotes (IN)
Quote message JSON is structured like this:
{
"type": "quote",
"symbol_id": "BITSTAMP_SPOT_BTC_USD",
"sequence": 2323346,
"time_exchange": "2013-09-28T22:40:50.0000000Z",
"time_coinapi": "2017-03-18T22:42:21.3763342Z",
"ask_price": 770.000000000,
"ask_size": 3252,
"bid_price": 760,
"bid_size": 124
}Quote message is sent for each update on orderbook first best bid or ask level.
Message variables
| Variable | Description |
|---|---|
| type | Message type, always quote |
| symbol_id | Our symbol identifier, format documented here. |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| time_exchange | Exchange time of orderbook |
| time_coinapi | CoinAPI time when orderbook received from exchange |
| ask_price | Best asking price |
| ask_size | Volume resting on best ask (if a value is equal to zero then size is unknown) |
| bid_price | Best bidding price |
| bid_size | Volume resting on best bid (if a value is equal to zero then size is unknown) |
Orderbook L2 (Full) (IN)
A Book message is sent for each snapshot or update of the order book. After subscription to this data type is initialized, we immediately start delivering updates to the order book and at least one snapshot will be provided as soon as possible with the nearest update of the book. Book message represents total ammount of bids and asks aggregated by price level.
{
"type": "book",
"symbol_id": "BITSTAMP_SPOT_BTC_USD",
"sequence": 2323346,
"time_exchange": "2013-09-28T22:40:50.0000000Z",
"time_coinapi": "2017-03-18T22:42:21.3763342Z",
"is_snapshot": true,
"asks": [
{
"price": 456.35,
"size": 123
},
{
"price": 456.36,
"size": 23
},
... cut ...
],
"bids": [
{
"price": 456.10,
"size": 42
},
{
"price": 456.09,
"size": 5
},
... cut ...
]
}Message variables
| Variable | Description |
|---|---|
| type | Message type, always book |
| symbol_id | Our symbol identifier, format documented here. |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| time_exchange | Exchange time of orderbook |
| time_coinapi | CoinAPI time when orderbook received from exchange |
| is_snapshot | Is message a snapshot? If true then all bid and ask levels are listed, otherwise only changed since the last message. |
| asks | All ask levels for snapshot message, otherwise only changed ask levels since the last message. Data will be in order from the best to the worst price. |
| bids | All bid levels for snapshot message, otherwise only changed bid levels since the last message. Data will be in order from the best to the worst price. |
| price | Price of bid/ask |
| size | Volume resting on bid/ask level in base amount |
Orderbook L2 (max 2x5) (IN)
A Book5 message contain first 5 best bid or ask levels.
[!NOTE]
Updates in this data type are sent as soon as possible if orderbook changed (outside or inside levels covered by the snapshot visibility). To reduce amount of updates please use the
subscribe_update_limit_ms_book_snapshotparameter.
{
"type": "book5",
"symbol_id": "BITSTAMP_SPOT_BTC_USD",
"sequence": 2323346,
"time_exchange": "2013-09-28T22:40:50.0000000Z",
"time_coinapi": "2017-03-18T22:42:21.3763342Z",
"asks": [
{
"price": 456.35,
"size": 123
},
{
"price": 456.36,
"size": 23
},
... cut ...
],
"bids": [
{
"price": 456.10,
"size": 42
},
{
"price": 456.09,
"size": 5
},
... cut ...
]
}Message variables
| Variable | Description |
|---|---|
| type | Message type, always book5 |
| symbol_id | Our symbol identifier, format documented here. |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| time_exchange | Exchange time of orderbook |
| time_coinapi | CoinAPI time when orderbook received from exchange |
| asks | Best 5 ask levels in order from best to worst. |
| bids | Best 5 bid levels in order from best to worst. |
| price | Price of bid/ask |
| size | Volume resting on bid/ask level in base amount |
Orderbook L2 (max 2x20) (IN)
A Book20 message contain first 20 best bid or ask levels.
[!NOTE]
Updates in this data type are sent every 1 second if orderbook changed (outside or inside levels covered by the snapshot visibility). To reduce amount of updates please use the
subscribe_update_limit_ms_book_snapshotparameter.
{
"type": "book20",
"symbol_id": "BITSTAMP_SPOT_BTC_USD",
"sequence": 2323346,
"time_exchange": "2013-09-28T22:40:50.0000000Z",
"time_coinapi": "2017-03-18T22:42:21.3763342Z",
"asks": [
{
"price": 456.35,
"size": 123
},
{
"price": 456.36,
"size": 23
},
... cut ...
],
"bids": [
{
"price": 456.10,
"size": 42
},
{
"price": 456.09,
"size": 5
},
... cut ...
]
}Message variables
| Variable | Description |
|---|---|
| type | Message type, always book20 |
| symbol_id | Our symbol identifier, format documented here. |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| time_exchange | Exchange time of orderbook |
| time_coinapi | CoinAPI time when orderbook received from exchange |
| asks | Best 20 ask levels in order from best to worst. |
| bids | Best 20 bid levels in order from best to worst. |
| price | Price of bid/ask |
| size | Volume resting on bid/ask level in base amount |
Orderbook L2 (max 2x50) (IN)
A Book50 message contain first 50 best bid or ask levels.
[!NOTE]
Updates in this data type are sent every 1 second if orderbook changed (outside or inside levels covered by the snapshot visibility). To reduce amount of updates please use the
subscribe_update_limit_ms_book_snapshotparameter.
{
"type": "book50",
"symbol_id": "BITSTAMP_SPOT_BTC_USD",
"sequence": 2323346,
"time_exchange": "2013-09-28T22:40:50.0000000Z",
"time_coinapi": "2017-03-18T22:42:21.3763342Z",
"asks": [
{
"price": 456.35,
"size": 123
},
{
"price": 456.36,
"size": 23
},
... cut ...
],
"bids": [
{
"price": 456.10,
"size": 42
},
{
"price": 456.09,
"size": 5
},
... cut ...
]
}Message variables
| Variable | Description |
|---|---|
| type | Message type, always book50 |
| symbol_id | Our symbol identifier, format documented here. |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| time_exchange | Exchange time of orderbook |
| time_coinapi | CoinAPI time when orderbook received from exchange |
| asks | Best 50 ask levels in order from best to worst. |
| bids | Best 50 bid levels in order from best to worst. |
| price | Price of bid/ask |
| size | Volume resting on bid/ask level in base amount |
Orderbook L3 (Full) (IN)
A book_l3 message is sent for each snapshot or update of the order book in the level 3 format (order-by-order).
After subscription to this data type is initialized, we immediately start delivering updates to the order book and at least one snapshot will be provided as soon as possible with the nearest update of the book.
Book L3 does not aggregate any data. Every ask and bid corresponds to passive order with information on the price and size of that order. The id can identify any order.
[!NOTE]
If the data source is providing the maximum resoluiont of the order book on level 2 then this data type will fallback to the Level 2, in that case the Order ID's will be null or not provided. You should treat Order without Id as Level 2 aggregated entry in the price queue.
{
"type": "book_l3"
"symbol_id": "COINBASE_SPOT_BCH_USD",
"sequence": 2323346,
"time_exchange": "2020-08-26T12:36:04.3464706Z",
"time_coinapi": "2020-08-26T12:36:04.2807750Z",
"is_snapshot": false,
"asks": [
{
"id": "520269d4-c085-47ed-8825-6d787af90800",
"price": 273.01,
"size": 1.81940502,
"update_type":"ADD"
},
{
"id": "0ac891c7-8360-462c-8d9a-d8b217d3fca2",
"price": 273.02,
"size": 1.0,
"update_type":"DELETE"
},
... cut ...
],
"bids": [
{
"id": "6340ec1e-8be8-404e-b9a4-a14120ec179e",
"price": 272.94,
"size": 1.81940502,
"update_type":"UPDATE"
},
{
"id": "7eaaa899-089f-4308-9fa2-e33737ae36ee",
"price": 272.96,
"size": 1.85989855,
"update_type":"DELETE"
},
... cut ...
]
}Message variables
| Variable | Description |
|---|---|
| type | Message type, always book_l3 |
| symbol_id | Our symbol identifier, format documented here. |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| time_exchange | Exchange time of orderbook |
| time_coinapi | CoinAPI time when orderbook received from exchange |
| is_snapshot | Is message a snapshot? If true then all bid and ask levels are listed, otherwise only changed since the last message |
| asks | All ask levels for snapshot message, otherwise only changed ask levels since the last message. Data will be in order from the best to the worst price. |
| bids | All bid levels for snapshot message, otherwise only changed bid levels since the last message. Data will be in order from the best to the worst price. |
| id | Order identifier |
| price | Price of bid/ask |
| size | Bid/ask base asset amount |
| update_type | Type of update message |
Possible update_type values
The snapshot message represents the initial collection of the orders in the order book. Further updates are modifying this collection.
update_type determines the type of update for the order.
Please note that the snapshot message has no defined update_type.
update_type | Description |
|---|---|
ADD | Add order to the price queue. |
UPDATE | Update the order size in the price queue. |
SUBTRACT | Subtract the order size in the price queue. |
DELETE | Delete the order from the price queue. |
MATCH | Subtract the order size in the price queue (same as SUBTRACT but caused by the match). |
Orderbook L4 (Full) (IN)
[!NOTE]
The
book_l4data type is available only on the Hyperliquid L4 WS DS data source.
A book_l4 message is sent for each snapshot or update of the Hyperliquid order book in the level 4 format.
Book L4 does not aggregate any data. Every ask and bid entry corresponds to a passive order with order id, price, size, update type, and the Hyperliquid user address associated with the order.
{
"is_snapshot": true,
"time_exchange": "2026-06-09T07:12:12.1100930Z",
"time_coinapi": "2026-06-09T07:12:12.1100930Z",
"asks": [
{
"id": "463412109888",
"price": 63301.0,
"size": 0.31228,
"user": "0xa62b923a112d50d03e1e096bbd53422490dac104",
"order_type": "Limit",
"orig_size": 0.31228,
"tif": "Alo",
"reduce_only": false,
"is_child": false
}
],
"bids": [
{
"id": "461970659753",
"price": 64200.0,
"size": 0.03115,
"user": "0x6f2411cef3d22ef3291ef281c84891bfec207222",
"order_type": "Limit",
"orig_size": 0.03115,
"tif": "Gtc",
"reduce_only": false,
"is_child": false,
"children_oids": "461970659754",
"children": [
{
"id": "461970659754",
"price": 70200.0,
"size": 0.03115,
"order_type": "Stop Market",
"is_child": true,
"is_trigger": true,
"trigger_px": 65000.0,
"trigger_condition": "Price above 65000"
}
]
}
],
"symbol_id": "HYPERLIQUIDL4_PERP_BTC_USDC",
"sequence": 2,
"type": "book_l4"
}For incremental updates, is_snapshot is false. Each changed ask or bid entry includes update_type and hl4_status:
{
"is_snapshot": false,
"time_exchange": "2026-06-09T07:12:12.1123484Z",
"time_coinapi": "2026-06-09T07:12:12.1123485Z",
"asks": [
{
"id": "463434662141",
"price": 63120.0,
"size": 0.05294,
"user": "0x154d97e96620b08f22b41e96a77dea29da902d6d",
"cloid": "0x000000000023c91d000006ddede11c7b",
"order_type": "Limit",
"orig_size": 0.05294,
"update_type": "set",
"hl4_status": "open",
"tif": "Alo",
"reduce_only": false
},
{
"id": "463434662163",
"price": 63114.0,
"size": 0.13842,
"user": "0x54e3f54df4b10ff63f7284733ed735e8e1507c20",
"cloid": "0x00000000002f362b0000315f825e1c2d",
"order_type": "Limit",
"orig_size": 0.13842,
"update_type": "rejected",
"hl4_status": "rejected_alo",
"tif": "Alo",
"reduce_only": false
}
],
"bids": [],
"symbol_id": "HYPERLIQUIDL4_PERP_BTC_USDC",
"sequence": 3,
"type": "book_l4"
}Message variables
| Variable | Description |
|---|---|
| is_snapshot | Indicates whether the message represents a full order book snapshot. If false, the message represents an incremental order book update. |
| time_exchange | Exchange time of the order book snapshot or update. |
| time_coinapi | CoinAPI time when the order book snapshot or update was received from the exchange. |
| asks | Array of ask-side order book entries. May be empty when there are no ask-side updates. |
| asks[].id | Exchange-provided order identifier for the ask entry. |
| asks[].price | Ask order price. |
| asks[].size | Ask order size. |
| asks[].user | User or account identifier associated with the ask entry, as provided by the exchange. |
| asks[].cloid | Client order identifier for the ask entry, when provided by the exchange. |
| asks[].order_type | Order type for the ask entry. Examples: Limit, Market, Take Profit Limit, Take Profit Market, Stop Market, Stop Limit. |
| asks[].orig_size | Original ask order size at placement. |
| asks[].update_type | Type of ask-side order book update. Present on incremental updates only. |
| asks[].hl4_status | Hyperliquid L4 status for the ask entry. Present on incremental updates only. See Possible hl4_status values. |
| asks[].tif | Time-in-force value for the ask entry, when provided by the exchange. |
| asks[].reduce_only | Indicates whether the ask entry is reduce-only, when provided by the exchange. |
| asks[].trigger_condition | Human-readable trigger condition for the ask entry. N/A for regular orders. Examples: Price above 32886 or Price below 32886 for stop, take-profit, or stop-loss orders. |
| asks[].is_trigger | Indicates whether the ask entry is a stop, take-profit, or stop-loss order that will activate when trigger_px is reached. false for regular limit orders. |
| asks[].trigger_px | Price at which a trigger ask order activates. 0.0 for non-trigger orders. |
| asks[].is_position_tpsl | Indicates whether the ask entry is a take-profit or stop-loss that applies to an entire position, rather than a specific order. |
| asks[].is_child | Indicates whether the ask entry is a child order in a bracket. Present on snapshot messages only. |
| asks[].children | Array of nested child orders attached to the parent ask order. Present on snapshot messages only. |
| asks[].children[].cloid | Client order identifier for the child ask order, when provided by the exchange. |
| asks[].children[].id | Exchange-provided order identifier for the child ask order. |
| asks[].children[].price | Child ask order price. |
| asks[].children[].size | Child ask order size. |
| asks[].children[].order_type | Order type for the child ask order. |
| asks[].children[].orig_size | Original child ask order size at placement. |
| asks[].children[].reduce_only | Indicates whether the child ask order is reduce-only. |
| asks[].children[].trigger_condition | Human-readable trigger condition for the child ask order. |
| asks[].children[].is_trigger | Indicates whether the child ask order is a trigger order. |
| asks[].children[].trigger_px | Price at which the child ask trigger order activates. |
| asks[].children[].is_position_tpsl | Indicates whether the child ask order is a position-level take-profit or stop-loss. |
| asks[].children[].is_child | Always true for entries in the children array. |
| asks[].children_oids | Comma-separated list of order IDs for bracket child orders attached to the parent ask order. Empty string or null when no children are attached. Present on snapshot messages only. |
| bids | Array of bid-side order book entries. May be empty when there are no bid-side updates. |
| bids[].id | Exchange-provided order identifier for the bid entry. |
| bids[].price | Bid order price. |
| bids[].size | Bid order size. |
| bids[].user | User or account identifier associated with the bid entry, as provided by the exchange. |
| bids[].cloid | Client order identifier for the bid entry, when provided by the exchange. |
| bids[].order_type | Order type for the bid entry. Examples: Limit, Market, Take Profit Limit, Take Profit Market, Stop Market, Stop Limit. |
| bids[].orig_size | Original bid order size at placement. |
| bids[].update_type | Type of bid-side order book update. Present on incremental updates only. |
| bids[].hl4_status | Hyperliquid L4 status for the bid entry. Present on incremental updates only. See Possible hl4_status values. |
| bids[].tif | Time-in-force value for the bid entry, when provided by the exchange. |
| bids[].reduce_only | Indicates whether the bid entry is reduce-only, when provided by the exchange. |
| bids[].trigger_condition | Human-readable trigger condition for the bid entry. N/A for regular orders. Examples: Price above 32886 or Price below 32886 for stop, take-profit, or stop-loss orders. |
| bids[].is_trigger | Indicates whether the bid entry is a stop, take-profit, or stop-loss order that will activate when trigger_px is reached. false for regular limit orders. |
| bids[].trigger_px | Price at which a trigger bid order activates. 0.0 for non-trigger orders. |
| bids[].is_position_tpsl | Indicates whether the bid entry is a take-profit or stop-loss that applies to an entire position, rather than a specific order. |
| bids[].is_child | Indicates whether the bid entry is a child order in a bracket. Present on snapshot messages only. |
| bids[].children | Array of nested child orders attached to the parent bid order. Present on snapshot messages only. |
| bids[].children[].cloid | Client order identifier for the child bid order, when provided by the exchange. |
| bids[].children[].id | Exchange-provided order identifier for the child bid order. |
| bids[].children[].price | Child bid order price. |
| bids[].children[].size | Child bid order size. |
| bids[].children[].order_type | Order type for the child bid order. |
| bids[].children[].orig_size | Original child bid order size at placement. |
| bids[].children[].reduce_only | Indicates whether the child bid order is reduce-only. |
| bids[].children[].trigger_condition | Human-readable trigger condition for the child bid order. |
| bids[].children[].is_trigger | Indicates whether the child bid order is a trigger order. |
| bids[].children[].trigger_px | Price at which the child bid trigger order activates. |
| bids[].children[].is_position_tpsl | Indicates whether the child bid order is a position-level take-profit or stop-loss. |
| bids[].children[].is_child | Always true for entries in the children array. |
| bids[].children_oids | Comma-separated list of order IDs for bracket child orders attached to the parent bid order. Empty string or null when no children are attached. Present on snapshot messages only. |
| symbol_id | Our symbol identifier, format documented here. For this message type, the symbol belongs to the HYPERLIQUIDL4 exchange. |
| sequence | Sequence number per pair (type, symbol_id) which is valid only for the lifespan of the connection. |
| type | Message type, always book_l4 |
Possible update_type values
The snapshot message represents the initial collection of the orders in the order book. Further updates modify this collection.
update_type is present on incremental updates only. Snapshot entries do not include update_type.
update_type | Description |
|---|---|
set | Order accepted and placed in the book. |
rejected | Order rejected. See hl4_status for the rejection reason. |
delete | Order removed from the book. See hl4_status for the removal reason. |
Possible hl4_status values
hl4_status is present on incremental updates only, alongside update_type.
| Value | Name | Description |
|---|---|---|
| 0 | OPEN | Order accepted and placed on the book. |
| 1 | FILLED | Order fully executed. |
| 2 | CANCELED | Order canceled by the user. |
| 3 | TRIGGERED | Stop/TP/SL trigger order was activated and executed. |
| 4 | REDUCE_ONLY_CANCELED | Canceled because it would increase position size (reduce-only constraint). |
| 5 | SELF_TRADE_CANCELED | Canceled to prevent self-trading against own orders. |
| 6 | SIBLING_FILLED_CANCELED | OCO bracket — canceled because its sibling order was filled. |
| 7 | MARGIN_CANCELED | Canceled by the risk engine due to insufficient margin. |
| 8 | VAULT_WITHDRAWAL_CANCELED | Canceled due to a vault withdrawal reducing available balance. |
| 9 | LIQUIDATED_CANCELED | Canceled as part of a liquidation process. |
| 10 | REJECTED_ALO | Rejected — Add Liquidity Only order would have crossed the spread. |
| 11 | REJECTED_MARGIN | Rejected — insufficient perpetual margin. |
| 12 | REJECTED_IOC | Rejected — Immediate-or-Cancel order could not be filled immediately. |
| 13 | REJECTED_BALANCE | Rejected — insufficient spot balance. |
| 14 | REJECTED_REDUCE | Rejected — reduce-only order would not reduce position. |
| 15 | REJECTED_MIN_NTL | Rejected — order size below minimum notional value. |
| 16 | REJECTED_ORACLE | Rejected — oracle price deviation too large. |
| 17 | REJECTED_OI | Rejected — would exceed open interest limit. |
Hyperliquid Oracle Prices (IN)
[!NOTE]
The
hl_oracle_pricesdata type is available only on the Hyperliquid L4 WS DS data source.
{
"type": "hl_oracle_prices",
"time_exchange": "2026-06-17T14:40:42.2680000Z",
"time_coinapi": "2026-06-17T14:40:42.4291928Z",
"coin_id": "BTC",
"update_class": "Deployer",
"mark_px": 66751.12,
"mark_daily_px": 65520.01,
"oracle_px": 66749.87,
"oracle_daily_px": 65490.45,
"external_perp_px": 66750.20,
"external_perp_daily_px": 65502.10,
"spot_px_input": 66748.50,
"mark_px_input": 66751.02,
"external_perp_px_input": 66750.18
}A hl_oracle_prices message is sent for each per-coin oracle update emitted by Hyperliquid L4 oracle streams.
Message variables
| Variable | Description |
|---|---|
| type | Message type, always hl_oracle_prices |
| time_exchange | Exchange time of the oracle update. |
| time_coinapi | CoinAPI time when the oracle update was received from the exchange. |
| coin_id | Hyperliquid coin identifier (for example BTC, ETH). |
| update_class | Oracle update class. |
| mark_px | Mark price. |
| mark_daily_px | Daily mark reference value. |
| oracle_px | Oracle price. |
| oracle_daily_px | Daily oracle reference value. |
| external_perp_px | External perpetual reference price. |
| external_perp_daily_px | Daily external perpetual reference value. |
| spot_px_input | Spot input price used by the oracle process. |
| mark_px_input | Mark input price used by the oracle process. |
| external_perp_px_input | External perpetual input price used by the oracle process. |
Possible update_class values
update_class | Description |
|---|---|
Deployer | Update from the primary deployer path. |
Fallback | Update from the fallback path. |
Hyperliquid TWAP Statuses (IN)
[!NOTE]
The
hl_twap_statusesdata type is available only on the Hyperliquid L4 WS DS data source.
{
"type": "hl_twap_statuses",
"time_exchange": "2026-06-17T14:41:01.0123000Z",
"time_coinapi": "2026-06-17T14:41:01.1543221Z",
"twap_id": 918273645,
"coin": "ETH",
"user": "0xea928063cd1b5969c73699355b96103210529bda",
"side": "B",
"status": "activated",
"sz": 100.0,
"executed_sz": 35.5,
"executed_ntl": 59520.15,
"minutes": 30,
"reduce_only": false,
"randomize": true,
"order_timestamp_ms": 1718635261012
}A hl_twap_statuses message is sent for each TWAP status transition or progress update.
Message variables
| Variable | Description |
|---|---|
| type | Message type, always hl_twap_statuses |
| time_exchange | Exchange time of the TWAP status update. |
| time_coinapi | CoinAPI time when the TWAP status update was received from the exchange. |
| twap_id | Hyperliquid TWAP identifier. |
| coin | Hyperliquid coin identifier (for example BTC, ETH). |
| user | User or account identifier associated with the TWAP. |
| side | TWAP side. |
| status | TWAP status value. |
| sz | Configured total TWAP size. |
| executed_sz | Executed TWAP size. |
| executed_ntl | Executed TWAP notional value. |
| minutes | Configured TWAP duration in minutes. |
| reduce_only | Indicates whether the TWAP is reduce-only. |
| randomize | Indicates whether slice randomization is enabled. |
| order_timestamp_ms | Order timestamp in Unix milliseconds. |
Possible side values
side | Description |
|---|---|
B | Buy side. |
A | Sell side. |
Typical status values
status | Description |
|---|---|
activated | TWAP started and is active. |
finished | TWAP completed successfully. |
terminated | TWAP was terminated before completion. |
error:... | TWAP ended with an exchange-reported error payload. |
Hyperliquid Misc Events (IN)
[!NOTE]
The
hl_misc_eventsdata type is available only on the Hyperliquid L4 WS DS data source.
{
"type": "hl_misc_events",
"time_exchange": "2026-06-17T14:42:10.2000000Z",
"time_coinapi": "2026-06-17T14:42:10.3401200Z",
"exchange_id": "HYPERLIQUIDL4",
"block_number": 32456789,
"event_type": "funding",
"json_payload": "{\"funding\":[{\"coin\":\"BTC\",\"funding_rate\":\"0.0001\"}]}"
}A hl_misc_events message is sent for raw Hyperliquid misc node events with normalized envelope fields.
Message variables
| Variable | Description |
|---|---|
| type | Message type, always hl_misc_events |
| time_exchange | Exchange time of the raw event. |
| time_coinapi | CoinAPI time when the raw event was received from the exchange. |
| exchange_id | Exchange identifier, typically HYPERLIQUIDL4. |
| block_number | Source Hyperliquid block number for the event. |
| event_type | Event type extracted from the raw event payload. |
| json_payload | Raw JSON payload serialized as a string. |
Hyperliquid System Events (IN)
[!NOTE]
The
hl_system_eventsdata type is available only on the Hyperliquid L4 WS DS data source.
{
"type": "hl_system_events",
"time_exchange": "2026-06-17T14:42:40.2000000Z",
"time_coinapi": "2026-06-17T14:42:40.3134500Z",
"exchange_id": "HYPERLIQUIDL4",
"block_number": 32456795,
"event_type": "SystemUsdClassTransferAction",
"json_payload": "{\"type\":\"SystemUsdClassTransferAction\",\"ntl\":7500000,\"toPerp\":true}"
}A hl_system_events message is sent for raw Hyperliquid system action events with normalized envelope fields.
Message variables
| Variable | Description |
|---|---|
| type | Message type, always hl_system_events |
| time_exchange | Exchange time of the raw event. |
| time_coinapi | CoinAPI time when the raw event was received from the exchange. |
| exchange_id | Exchange identifier, typically HYPERLIQUIDL4. |
| block_number | Source Hyperliquid block number for the event. |
| event_type | System action type extracted from the payload (for example SystemSendAssetAction or approveAgent). |
| json_payload | Raw JSON payload serialized as a string. |
High-Frequency Market Changes (IN)
[!NOTE]
Enterprise Feature - This data type is only available in the Enterprise plan. Contact your account manager for access.
The high_frequency_market_changes data type provides real-time detection of market structure changes on supported exchanges. The system continuously monitors exchange APIs at high frequency (multiple checks per second) to detect:
- New trading pairs being listed
- Trading pairs being delisted
- Exchange announcements and notifications
Example subscription for high-frequency market changes on UPBIT exchange:
{
"type": "hello",
"subscribe_data_type": ["high_frequency_market_changes"],
"subscribe_filter_exchange_id": ["UPBIT"]
}Message Types
Periodic Status Update (sent every ~1 second)
{
"exchange_name": "UPBIT",
"timestamp": "2025-10-16T13:11:15.4258344Z",
"elapsed_ms": 1005.7186,
"diag_total_api_checks": 8430,
"diag_calls_in_interval": 75,
"total_symbols_count": 635,
"new_symbols_count": 0,
"new_symbols": [],
"removed_symbols_count": 0,
"removed_symbols": [],
"announcements": [],
"diag_current_checks_per_second": 75,
"diag_failed_checks_in_interval": 0,
"diag_average_response_time_ms": 248.48763100000005,
"diag_average_sampling_interval_ms": 13.333333333333334,
"type": "high_frequency_market_changes"
}New Symbols Detected
{
"exchange_name": "UPBIT",
"timestamp": "2025-10-16T13:10:27.6976792Z",
"elapsed_ms": 578.8284,
"diag_total_api_checks": 4796,
"diag_calls_in_interval": 44,
"total_symbols_count": 635,
"new_symbols_count": 3,
"new_symbols": [
{
"symbol_id": "EXAMPLE-NEW-SYMBOL-1",
"discovered_at": "2025-10-16T13:10:27.6903126Z"
},
{
"symbol_id": "EXAMPLE-NEW-SYMBOL-2",
"discovered_at": "2025-10-16T13:10:27.6903328Z"
},
{
"symbol_id": "EXAMPLE-NEW-SYMBOL-3",
"discovered_at": "2025-10-16T13:10:27.6903348Z"
}
],
"removed_symbols_count": 0,
"removed_symbols": [],
"announcements": [],
"diag_current_checks_per_second": 44,
"diag_failed_checks_in_interval": 0,
"diag_average_response_time_ms": 248.22826800000007,
"diag_average_sampling_interval_ms": 22.727272727272727,
"type": "high_frequency_market_changes"
}Symbols Removed/Delisted
{
"exchange_name": "UPBIT",
"timestamp": "2025-10-16T13:11:27.7477246Z",
"elapsed_ms": 245.5381,
"diag_total_api_checks": 9369,
"diag_calls_in_interval": 19,
"total_symbols_count": 632,
"new_symbols_count": 0,
"new_symbols": [],
"removed_symbols_count": 3,
"removed_symbols": [
{
"symbol_id": "EXAMPLE-NEW-SYMBOL-1",
"removed_at": "2025-10-16T13:11:27.7188035Z",
"existed_for_seconds": 60.0284973
},
{
"symbol_id": "EXAMPLE-NEW-SYMBOL-2",
"removed_at": "2025-10-16T13:11:27.7277049Z",
"existed_for_seconds": 60.0373731
},
{
"symbol_id": "EXAMPLE-NEW-SYMBOL-3",
"removed_at": "2025-10-16T13:11:27.7351630Z",
"existed_for_seconds": 60.0448291
}
],
"announcements": [],
"diag_current_checks_per_second": 19,
"diag_failed_checks_in_interval": 0,
"diag_average_response_time_ms": 248.63812699999977,
"diag_average_sampling_interval_ms": 52.63157894736842,
"type": "high_frequency_market_changes"
}Message variables
| Variable | Type | Description |
|---|---|---|
| type | string | Message type, always high_frequency_market_changes |
| exchange_name | string | Exchange identifier (e.g., "UPBIT", "BINANCE") |
| timestamp | string | ISO 8601 timestamp when this message was generated |
| elapsed_ms | double | Time elapsed since last message in milliseconds |
| total_symbols_count | int | Current total number of trading pairs on the exchange |
| new_symbols_count | int | Number of new symbols detected in this interval |
| new_symbols | array | Array of newly discovered trading pairs |
| removed_symbols_count | int | Number of delisted symbols detected in this interval |
| removed_symbols | array | Array of delisted trading pairs |
| announcements | array | Exchange announcements detected |
| diag_total_api_checks | int | Total API checks performed since service start (diagnostic) |
| diag_calls_in_interval | int | Number of API checks in the current interval (diagnostic) |
| diag_current_checks_per_second | int | Current rate of API checks per second (diagnostic) |
| diag_failed_checks_in_interval | int | Number of failed API checks in current interval (diagnostic) |
| diag_average_response_time_ms | double | Average API response time in milliseconds (diagnostic) |
| diag_average_sampling_interval_ms | double | Average time between consecutive API checks (diagnostic) |
New Symbol Object
| Variable | Type | Description |
|---|---|---|
| symbol_id | string | Trading pair identifier in exchange format |
| discovered_at | string | ISO 8601 timestamp when the symbol was first detected |
Removed Symbol Object
| Variable | Type | Description |
|---|---|---|
| symbol_id | string | Trading pair identifier in exchange format |
| removed_at | string | ISO 8601 timestamp when the symbol was detected as removed |
| existed_for_seconds | double | Duration the symbol existed on the exchange in seconds |
Use Cases
- Trading Bots: Automatically detect and start trading new listing opportunities within milliseconds
- Market Surveillance: Monitor exchange listing/delisting events for compliance and reporting
- Data Collection: Ensure complete historical data capture by detecting new symbols immediately
- Alerting Systems: Set up real-time notifications for market structure changes
Connectivity Status (IN)
Connectivity status message JSON is structured like this:
{
"exchange_id": "COINBASE",
"timestamp": "2026-04-09T16:08:32.7515306Z",
"type": "connectivity_status"
}The connectivity_status message is sent periodically for the connected market data source.
It can be used to confirm that the upstream source is currently reachable and actively monitored on this stream.
Message variables
| Variable | Type | Description |
|---|---|---|
| type | string | Message type, always connectivity_status |
| exchange_id | string | Exchange identifier for the monitored source |
| timestamp | string | ISO 8601 timestamp when the status message was generated |
Reconnect (IN)
Reconnect message is sent by the server to all connected clients when the server will be restarted or shut down at the defined exact time included in the message content. After the period specified in message passes, the client must expect that the underlying WebSocket connection will be closed from the server-side. A new connection will automatically be established to a different server.
The correct way of handling this event depends on the specific requirements of the integration, but we can define standard ways how to handle it:
- Wait for the connection to be closed and reconnect
- Reconnect immediately after receiving the message
- Upon receiving the message, establish a second connection, and subscribe to the same scope of data. When the first connection is disconnected, do not reconnect it and instead transparently switch the data streams between connections. This method requires more implementation as a transparent switch of the data stream must not break the sequence for streams published using the initial snapshot and update messages.
Example JSON reconnect message is structured like this:
{
"type": "reconnect"
"within_seconds": 10,
"before_time": "2020-08-06T19:19:09.7035429Z",
}Message variables
| Variable | Description |
|---|---|
| type | Message type, always reconnect |
| within_seconds | Seconds within which reconnection should be performed. |
| before_time | Time before which reconnection should be performed. |
Heartbeat (IN)
Heartbeat message JSON is structured like this:
{
"type": "hearbeat"
}Heartbeat message is sent to you every time there is one second of silence in communication between us, if you agreed on this feature in Hello message.
[!TIP]
WebSocket working on TCP protocol which doesn't have the feature indicating that the connection is broken without trying exchange data over it. As you will not be actively sending messages to us, with Heartbeat you can distinguish a situation where there are no market data updates for you (Heartbeat is delivered but no market data updates) or connection between us is broken (Heartbeat and market data updates are not delivered).
Hyperliquid L4
HYPERLIQUIDL4-only WebSocket DS feeds for L4 order book, L4 trades, oracle enrichment, TWAP statuses, and raw node events.
Introduction
Financial Information eXchange (FIX) protocol is an electronic communications protocol initiated in 1992 for international real-time exchange of information related to the securities transactions and markets. You can use it to receive real-time market data from us and it's an alternative to WebSocket protocol.