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.
wss://api.resolvedmarkets.com/ws/orderbookOpen 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
Connect
Open a WebSocket to /ws/orderbook.
Authenticate
Send { "type": "auth", "apiKey": "rm_..." }. The server replies { "type": "auth", "status": "ok" } and immediately follows with a markets frame.
Subscribe to a crypto
Send { "type": "subscribe", "crypto": "BTC" } to start receiving orderbook data for that crypto.
Receive orderbook updates
Server pushes { "type": "orderbook", "markets": [...] } every ~2 seconds with live depth data.
Example: JavaScript
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
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
| Type | Frequency | Description |
|---|---|---|
auth | On successful auth | { "type": "auth", "status": "ok" } |
markets | On auth + on market rotation | Full list of active markets with crypto, timeframe, and IDs |
orderbook | Every ~2 seconds | Live orderbook for subscribed crypto — UP/DOWN books with bids, asks, depth |
error | On auth/tier failure | Includes a numeric code (4001 auth timeout, 4003 tier restriction / connection limit) |
| ping | Every 30 seconds | Heartbeat — respond with pong (handled automatically by browsers) |
Client Messages
| Type | Payload | Description |
|---|---|---|
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
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.
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.
The server evicts clients that don't respond to pings within 30 seconds. Implement reconnection logic in your client.
Sending a new subscribe message replaces the previous subscription. To monitor multiple cryptos, open multiple connections (subject to your tier's cap).

