WebSocket API
Two endpoints share the same API-key namespace.
Endpoints
| URL | Region | Coverage | Use it for |
|---|---|---|---|
wss://cryptolisting.ws | AWS Tokyo (ap-northeast-1a, apne1-az4) | Binance + Upbit + Bithumb | Bots in Tokyo / global |
wss://kr.cryptolisting.ws | AWS Seoul (ap-northeast-2c, apne2-az3) | Upbit only | Korea-based bots trading Upbit |
Pick one per bot — the closest to your trading region. The Seoul endpoint removes the Seoul → Tokyo network hop on Upbit detection. Bithumb is currently dispatched only from the Tokyo endpoint. Same key authenticates on both, but rate limits and connection caps are tracked independently.
Frames are binary; payloads are UTF-8 JSON.
Query parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
cex | No | Comma-separated list of exchanges | binance,upbit |
See Exchange Filtering.
Lifecycle
Client Server
| |
|--- WSS handshake + API key -----→ |
|←---- 101 Switching Protocols -----|
| |
|←---- welcome --------------------| (immediate)
|←---- PING (control frame) -------| (every 15 s)
|--- PONG ------------------------→ | (handled by your WS lib)
|←---- heartbeat (JSON) -----------| (every 30 s)
|←---- announcement ---------------| (when detected)
|--- {"type":"test"} -------------→ | (optional)
|←---- test_announcement ---------| (only to you)
|←---- close (1000, key_expired) -| (if key expires)
Handshake
If the key fails validation, the server rejects the upgrade with an HTTP error:
| Code | Cause |
|---|---|
426 | Malformed upgrade request (missing/invalid Sec-WebSocket-Key or Upgrade) |
401 | Missing X-API-Key header |
403 | Invalid, revoked, or expired key |
429 | Rate, per-IP, distinct-IP, or absolute-cap limit hit (or cooldown active) |
See Error Handling for retry strategy.
Welcome
Sent once after a successful handshake. Confirms tier and limits. See welcome.
Keep-alive
The server sends a WebSocket PING control frame every 15 s (with 0–5 s jitter on the first). Your library responds with PONG automatically — Python websockets, Node.js ws, Go gorilla/websocket, Rust tokio-tungstenite all handle it without configuration.
If the server does not receive a PONG within 30 s of the last ping, it closes the connection.
Don’t add an “no-message-for-N-seconds → reconnect” watchdog at the application layer. Listings are sparse; you’ll reconnect in a loop during quiet periods. Use your library’s close/error callbacks instead.
Heartbeat
A JSON heartbeat message every 30 s, every tier. Lets your client confirm the connection is alive without waiting for a rare announcement. See heartbeat.
Announcements
When an event is detected, every subscriber whose filter matches receives an announcement. See announcement.
Disconnection
The server may close the connection with a close frame. The reason field tells you why — see Error Handling.
Client-to-server messages
The only supported client message is the test request:
{"type":"test"}
Returns a fake test_announcement. Limits:
| Limit | Value | Effect on excess |
|---|---|---|
| Message rate | 3 / minute | Connection closed (rate_limit_exceeded) |
| Frame size | 1 KB | Connection closed (frame_too_large) |
| Test rate | 1 / minute | test_rate_limited error response |