Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Code Examples

Production-ready clients with reconnection, latency tracking, and a test-announcement smoke check on connect.

Keep-alive (PING/PONG) is handled by each WebSocket library — no application-level watchdog needed.

pip install websockets
import asyncio
import json
import time
import websockets

API_KEY = "dsk_your_key_here"
WS_URL  = "wss://cryptolisting.ws"
# Filter exchanges (optional):
# WS_URL = "wss://cryptolisting.ws?cex=binance,upbit"

MAX_RETRIES = 20


def on_announcement(msg: dict):
    now_us = int(time.time() * 1_000_000)
    network_ms = (now_us - msg["dispatchTimestampUs"]) / 1000
    print(f"[{msg['listingType']}] {msg['ticker']} on {msg['publisher']}")
    print(f"  {msg['title']}")
    print(f"  network={network_ms:.2f}ms")


async def run():
    headers = {"X-API-Key": API_KEY}

    for attempt in range(MAX_RETRIES):
        try:
            async with websockets.connect(WS_URL, extra_headers=headers) as ws:
                print("connected")

                async for raw in ws:
                    msg = json.loads(raw)

                    if msg["type"] == "welcome":
                        print(f"welcome: tier={msg['tier']} cex={msg['allowedCex']}")
                        await asyncio.sleep(15)
                        await ws.send(json.dumps({"type": "test"}))

                    elif msg["type"] in ("announcement", "test_announcement"):
                        if msg["type"] == "test_announcement":
                            print("[TEST] ", end="")
                        on_announcement(msg)

        except websockets.ConnectionClosed as e:
            reason = e.rcvd.reason if e.rcvd else ""
            if reason in ("key_expired", "key_invalidated"):
                print(f"key invalid: {reason}"); return
            print(f"closed: {reason}")

        except Exception as e:
            print(f"error: {e}")

        backoff = min(2 ** attempt, 300)
        print(f"reconnecting in {backoff}s")
        await asyncio.sleep(backoff)


if __name__ == "__main__":
    asyncio.run(run())