Protocol Reference
Every client-to-server message is a JSON text frame with a required method field.
Invalid JSON, missing required fields, or unknown methods may disconnect the client with a structured error.
Client messages
subscribe
Subscribes the client to a coin or stream.
Subscribe to order book diffs for a coin:
{"method":"subscribe","coin":"BTC"}The coin value must be a non-empty string.
Subscribing twice to the same coin is safe and idempotent.
Subscribe to mempool transactions:
{"method":"subscribe","stream":"mempool"}Currently, the only valid stream value is mempool.
If the mempool stream is not enabled on the server, the server replies with a non-disconnecting mempool_unavailable error.
unsubscribe
Unsubscribes from a coin or stream.
{"method":"unsubscribe","coin":"BTC"}{"method":"unsubscribe","stream":"mempool"}esp
Upgrades the connection to binary protocol mode.
{"method":"esp","version":1}The version field must match the server binary protocol version.
Current binary protocol version: 1.
If the version does not match, the client is disconnected with the version_mismatch error.
prime
Enables additional binary streams after esp.
{"method":"prime"}After prime, the client can receive:
- Ping frames
- Timing metrics
- Server error events
prime must be sent after esp.
Calling prime before esp disconnects the client with the not_esp error.
unprime
Disables the additional prime streams.
{"method":"unprime"}Like prime, this must be called after esp.
JSON mode
JSON mode is the default mode before esp is sent.
In this mode, server-to-client frames are text frames containing newline-delimited JSON order book diffs.
A single WebSocket frame may contain multiple JSON lines separated by \n.
Example:
{"coin":"BTC","time":"...","side":"A","px":"72223.0","sz":"0","oid":123,"user":"0x..."}
{"coin":"BTC","time":"...","side":"B","px":"72182.0","sz":"0.3","oid":456,"user":"0x..."}JSON mode is intended for quick testing and inspection.
For production integrations, use binary mode.
Binary mode
After esp, all server-to-client data frames are binary WebSocket frames.
The first byte of every frame is a tag that identifies the frame type.
All multi-byte integers are little-endian.
| Tag | Type | Size | When it is received |
|---|---|---|---|
| 0 | Block | 33 bytes | After every block applied by the node |
| 1 | TinyOrder | Variable | For each order book diff on a subscribed coin |
| 2 | Metric | Variable | After every block, only after prime |
| 3 | Ping | 9 bytes | Roughly every 5 ms, only after prime |
| 4 | MempoolTx | Variable | For each mempool transaction, when subscribed |
Block frame
Tag:
0
Size:
33 bytes
Block frames are emitted after every block applied by the node.
Layout:
offset size field notes
────────────────────────────────────────────────────────────
0 1 tag Always 0
1 8 ts_ms Block timestamp, ms since UNIX epoch
9 8 height Block height
17 8 wall_ts_us Node-local wall clock, µs since epoch
25 8 apply_duration_us Time spent applying the block
Node-side block latency can be calculated as:
wall_ts_us - (ts_ms * 1000)
TinyOrder frame
Tag:
1
Size:
Variable
TinyOrder frames are emitted for order book diffs on subscribed coins.
All strings are length-prefixed with a single u8 byte.
The following fields are encoded as UTF-8 decimal strings and should be parsed as text:
coinpriceqtyuser
Layout:
offset size field
────────────────────────────────────────────────────────────
0 1 tag = 1
1 8 oid, u64 little-endian
9 1 is_buyer, 1 = buy, 0 = sell
10 1 status, 1 = open, 0 = canceled
11 1 + N coin, for example "BTC"
... 1 + N price, for example "72223.0"
... 1 + N qty, for example "0.3"
... 1 + N user, hex address
Both opens and cancels arrive as TinyOrder frames.
A full cancel is represented as:
status = 0
qty = "0"
Partial fills are not surfaced as separate events. Instead, the resting order quantity changes.
MempoolTx frame
Tag:
4
Size:
Variable
MempoolTx frames are emitted for mempool transactions when the client is subscribed to the mempool stream.
These frames can be large because the payload is length-prefixed with a u32.
Layout:
offset size field
────────────────────────────────────────────────────────────
0 1 tag = 4
1 8 receive_ts_us, node first saw the tx, µs since epoch
9 32 tx_hash, raw 32-byte hash
41 4 payload_len, u32 little-endian
45 N payload, signed-action bundle as raw JSON
Error frames
Errors are delivered as JSON text frames.
Example:
{"channel":"errors","code":"<code>","message":"<human readable>"}The code field is a stable contract and can be used programmatically.
The message field is intended for humans and may change.
| Code | Meaning | Disconnects? |
|---|---|---|
invalid_json | Text frame was not valid JSON | Yes |
missing_method | JSON frame had no method field | Yes |
unknown_method | Method value is not recognized | Yes |
missing_param | Required coin, stream, or version field is missing | Yes |
empty_coin | Subscribe was called with an empty coin string | No |
unknown_stream | Stream value is not supported | No |
mempool_unavailable | Mempool stream is not enabled on this server | No |
version_mismatch | esp version does not match the server version | Yes |
not_esp | prime or unprime was called before esp | Yes |
After prime, clients may also receive informational server error events. These do not necessarily indicate a client-side issue.
What's next?
Updated 3 days ago