WebSocket Streaming

Real-time orderbook data via WebSocket. Lower latency and bandwidth than REST polling. API key required.

Connection

Connect to /ws/orderbook, then authenticate by sending an auth message within 5 seconds.

WebSocket URL
wss://api.resolvedmarkets.com/ws/orderbook
Authentication (message-based)

Open the connection without any auth, then send { "type": "auth", "apiKey": "rm_..." } as your first message. The server replies with { "type": "auth", "status": "ok" } on success. If you do not authenticate within 5 seconds the connection is closed with code 4001.

Query-string auth (?apiKey=…) is deprecated but still accepted for backward compatibility — the server logs a warning when it is used. New integrations should use message-based auth.

Message Flow

1

Connect

Open a WebSocket to /ws/orderbook.

2

Authenticate

Send { "type": "auth", "apiKey": "rm_..." }. The server replies { "type": "auth", "status": "ok" } and immediately follows with a markets frame.

3

Subscribe to a crypto

Send { "type": "subscribe", "crypto": "BTC" } to start receiving orderbook data for that crypto.

4

Receive orderbook updates

Server pushes { "type": "orderbook", "markets": [...] } every ~2 seconds with live depth data.

Example: JavaScript

Browser / Node.js
const API_KEY = "rm_your_key_here";
const ws = new WebSocket("wss://api.resolvedmarkets.com/ws/orderbook");

ws.onopen = () => {
  // First message must be auth — server closes with 4001 after 5s otherwise.
  ws.send(JSON.stringify({ type: "auth", apiKey: API_KEY }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type === "auth" && msg.status === "ok") {
    // Authenticated — subscribe to BTC orderbooks.
    ws.send(JSON.stringify({ type: "subscribe", crypto: "BTC" }));
    return;
  }

  if (msg.type === "markets") {
    console.log("Available markets:", msg.data);
  }

  if (msg.type === "orderbook") {
    for (const market of msg.markets) {
      console.log(market.crypto, market.timeframe);
      console.log("  UP best bid:", market.up?.bestBid);
      console.log("  DOWN best ask:", market.down?.bestAsk);
    }
  }
};

ws.onclose = (e) => {
  console.log("Disconnected:", e.code, e.reason);
  setTimeout(() => { /* reconnect logic */ }, 3000);
};

Example: Python

Python (websockets)
import asyncio, json, websockets

async def stream():
    API_KEY = "rm_your_key_here"
    async with websockets.connect("wss://api.resolvedmarkets.com/ws/orderbook") as ws:
        # First message must be auth.
        await ws.send(json.dumps({"type": "auth", "apiKey": API_KEY}))
        ack = json.loads(await ws.recv())
        assert ack.get("status") == "ok", ack

        await ws.send(json.dumps({"type": "subscribe", "crypto": "ETH"}))

        async for message in ws:
            data = json.loads(message)
            if data["type"] == "orderbook":
                for m in data["markets"]:
                    print(f"{m['crypto']} {m['timeframe']}: "
                          f"UP bid={m['up']['bestBid']}")

asyncio.run(stream())

Server Messages

TypeFrequencyDescription
authOn successful auth{ "type": "auth", "status": "ok" }
marketsOn auth + on market rotationFull list of active markets with crypto, timeframe, and IDs
orderbookEvery ~2 secondsLive orderbook for subscribed crypto — UP/DOWN books with bids, asks, depth
errorOn auth/tier failureIncludes a numeric code (4001 auth timeout, 4003 tier restriction / connection limit)
pingEvery 30 secondsHeartbeat — respond with pong (handled automatically by browsers)

Client Messages

TypePayloadDescription
auth{ "type": "auth", "apiKey": "rm_..." }Required first message. Must arrive within 5 seconds or the connection is closed with code 4001.
subscribe{ "type": "subscribe", "crypto": "BTC" }Switch subscription to a different crypto (BTC, ETH, SOL, XRP)

Important Notes

Authenticate via message, not URL

Send { "type": "auth", "apiKey": "rm_..." } as the first frame. The legacy ?apiKey=… query param still works but is deprecated and logs a warning server-side.

Tier connection limits

Free tier has no WebSocket access (closes with code 4003). Pro allows 1 concurrent connection, Enterprise allows 10. Exceeding the cap closes new connections with code 4003.

Auto-reconnect recommended

The server evicts clients that don't respond to pings within 30 seconds. Implement reconnection logic in your client.

One subscription at a time

Sending a new subscribe message replaces the previous subscription. To monitor multiple cryptos, open multiple connections (subject to your tier's cap).

WebSocket Streaming — API Docs | Resolved Markets