WebSocket streams¶
wss://api.klondike-crypto.com/v1/ws?format=json
wss://api.klondike-crypto.com/v1/ws?format=capnp
One connection carries any number of subscriptions (50 at most): the trades of
a symbol, its merged order book, the overview. The API key goes in the
X-API-Key header, or in the api_key query parameter when the client cannot
set headers (browsers). A missing or revoked key is refused before the upgrade
with a 401.
format selects the encoding of the server messages:
format |
Server frames | Client frames |
|---|---|---|
json (default) |
text, one JSON object per frame | text, JSON |
capnp |
binary, one packed Cap'n Proto ServerMessage per frame (schema) |
text, JSON |
The client always sends JSON: subscriptions are rare, the data is what is worth encoding in binary.
Client messages¶
{"op": "subscribe", "channel": "trades", "symbol": "BTC/USDT"}
{"op": "subscribe", "channel": "trades", "symbol": "ETH/USDT:USDT", "venues": ["binanceusdm", "bybit"]}
{"op": "subscribe", "channel": "orderbook", "symbol": "BTC/USDT", "depth": 20}
{"op": "subscribe", "channel": "orderbook", "symbol": "BTC/USDT", "depth": 50, "venues": ["coinbase", "kraken"]}
{"op": "subscribe", "channel": "overview"}
{"op": "unsubscribe", "channel": "trades", "symbol": "BTC/USDT"}
{"op": "ping"}
| Field | ||
|---|---|---|
op |
subscribe, unsubscribe, ping |
|
channel |
trades, orderbook, overview |
|
symbol |
unified CCXT symbol | required except for overview |
venues |
CCXT exchange ids | optional, all venues when absent |
depth |
levels per side, 1 to 200 | orderbook only, default 20 |
Subscribing again to the same channel and symbol replaces its venues and
depth. A symbol no venue streams yet is subscribed anyway: Klondike starts
streaming the pairs its users ask for, and the data follows within a few
seconds when a venue lists the pair.
Server messages¶
Every subscription and unsubscription is acknowledged:
{"type": "subscribed", "channel": "trades", "symbol": "BTC/USDT"}
{"type": "unsubscribed", "channel": "trades", "symbol": "BTC/USDT"}
{"type": "subscribed", "channel": "overview"}
New message types may be added: a client should ignore a type it does not
know (the libraries do).
trades¶
The trades received since the previous message, batched every 100 ms, oldest first. Nothing is sent while the symbol does not trade.
{"type": "trades", "symbol": "BTC/USDT", "trades": [
{"ts": 1793706479654, "venue": "binance", "price": 104250.1, "qty": 0.0125, "side": "buy"},
{"ts": 1793706479702, "venue": "okx", "price": 104249.9, "qty": 0.4, "side": "sell"}
]}
side is the aggressor side: buy, sell or unknown. The fields are those
of GET /v1/trades.
orderbook¶
The merged order book, whole (depth levels per side), when it changes and at
most four times a second; the venues are merged about once a second. The
latest book is sent right after the subscription when the API has one.
{"type": "orderbook", "symbol": "BTC/USDT", "ts": 1793706479000,
"venues": [
{"venue": "binance", "ts": 1793706478950, "bid": 104250.0, "bidQty": 1.2, "ask": 104250.1, "askQty": 0.8},
{"venue": "kraken", "ts": 1793706478890, "bid": 104249.0, "bidQty": 0.5, "ask": null, "askQty": null}
],
"bids": [{"price": 104250.0, "qty": 1.2, "venue": "binance"}, {"price": 104249.0, "qty": 0.5, "venue": "kraken"}],
"asks": [{"price": 104250.1, "qty": 0.8, "venue": "binance"}]}
Same fields as GET /v1/orderbook. venues is not
filtered by the venues of the subscription; bids and asks are.
overview¶
The overview, whole, right after the subscription and then each time it changes (every few seconds).
{"type": "overview", "overview": {"ts": 1793706479654, "feeds": {...}, "pairs": [...], ...}}
overview is the document of GET /v1/overview.
error¶
{"type": "error", "code": "bad_request", "message": "symbol is required", "channel": "trades", "symbol": ""}
code |
|
|---|---|
bad_request |
invalid JSON, unknown op, missing symbol, depth out of range |
unknown_channel |
|
too_many_subscriptions |
more than 50 subscriptions on the connection |
An error does not close the connection. A subscription refused with
bad_request, unknown_channel or too_many_subscriptions does not exist on
the server: the libraries forget it and do not send it again after a
reconnection.
pong¶
{"type": "pong"}, the answer to {"op": "ping"}. The server also sends
WebSocket ping frames every 20 s; WebSocket libraries answer them on their own.
Limits and closing¶
- 5 connections at once per API key; a sixth is refused with a 429.
- A client that does not read fast enough is disconnected (close code
4001, reasonslow consumer) rather than served stale data. - The server closes with
1001when it restarts. The client libraries reconnect with a backoff and subscribe again; a client of your own should do the same.
Cap'n Proto¶
With format=capnp, each binary frame is one ServerMessage of
klondike_api.capnp, packed encoding. The union says the type:
trades, orderbook, overviewJson (the overview document as JSON text),
subscribed, unsubscribed, error, pong. Differences with JSON:
- a missing number is NaN, a missing timestamp 0;
- the
venueof a level is an index intoOrderbook.venues.
The libraries give the same objects whatever the format. Cap'n Proto frames are about three times smaller than JSON on an order book of 50 levels and are decoded without parsing text.