Skip to main content

Documentation Index

Fetch the complete documentation index at: https://hypernode-docs.polynode.dev/llms.txt

Use this file to discover all available pages before exploring further.

WebSocket connections drop. Networks fail. Rate limits hit. This guide covers how to build a resilient client.

Reconnection

hypernode WebSocket connections can drop due to server restarts, network issues, or idle timeouts. Your client must handle reconnection.

Basic pattern

import WebSocket from "ws";

const API_KEY = "pn_live_YOUR_KEY";
const URL = `wss://hyper.polynode.dev/ws?key=${API_KEY}`;

let ws: WebSocket;
let reconnectDelay = 1000; // Start at 1 second
const MAX_DELAY = 30000;   // Cap at 30 seconds

function connect() {
  ws = new WebSocket(URL);

  ws.on("open", () => {
    console.log("Connected");
    reconnectDelay = 1000; // Reset on successful connect

    // Re-subscribe after every reconnect
    ws.send(JSON.stringify({
      action: "subscribe",
      filters: { action_types: ["order", "fill"] }
    }));
  });

  ws.on("message", (raw) => {
    const event = JSON.parse(raw.toString());
    handleEvent(event);
  });

  ws.on("close", (code, reason) => {
    console.log(`Disconnected: ${code} ${reason}`);
    scheduleReconnect();
  });

  ws.on("error", (err) => {
    console.error("WebSocket error:", err.message);
    // on("close") will fire after this
  });
}

function scheduleReconnect() {
  const jitter = Math.random() * 1000;
  const delay = Math.min(reconnectDelay + jitter, MAX_DELAY);
  console.log(`Reconnecting in ${Math.round(delay)}ms`);

  setTimeout(() => {
    reconnectDelay = Math.min(reconnectDelay * 2, MAX_DELAY);
    connect();
  }, delay);
}

connect();

Python

import json
import time
import websocket

API_KEY = "pn_live_YOUR_KEY"
URL = f"wss://hyper.polynode.dev/ws?key={API_KEY}"

def on_open(ws):
    print("Connected")
    ws.send(json.dumps({
        "action": "subscribe",
        "filters": {"action_types": ["order", "fill"]}
    }))

def on_message(ws, message):
    event = json.loads(message)
    handle_event(event)

def on_close(ws, close_status_code, close_msg):
    print(f"Disconnected: {close_status_code}")

def on_error(ws, error):
    print(f"Error: {error}")

# websocket-client handles reconnection with run_forever
while True:
    try:
        ws = websocket.WebSocketApp(
            URL,
            on_open=on_open,
            on_message=on_message,
            on_close=on_close,
            on_error=on_error,
        )
        ws.run_forever()
    except Exception as e:
        print(f"Connection failed: {e}")
    time.sleep(5)

Key rules

Re-subscribe on every reconnect

Subscriptions are not persisted across connections. After reconnecting, you must send your subscribe messages again. Keep your subscription configs in a variable so you can replay them.
const MY_SUBSCRIPTIONS = [
  { action: "subscribe", filters: { assets: ["BTC"], action_types: ["order", "fill"] } },
  { action: "subscribe", filters: { addresses: ["0xabc..."] } },
];

ws.on("open", () => {
  for (const sub of MY_SUBSCRIPTIONS) {
    ws.send(JSON.stringify(sub));
  }
});

No replay or gap-fill

hypernode does not replay missed events during a disconnection. If your connection drops for 5 seconds, events during that window are lost. Design your application to tolerate gaps. If you need guaranteed delivery, combine the stream with periodic REST API polling:
// Stream for real-time updates
ws.on("message", handleEvent);

// Poll every 30 seconds as a safety net
setInterval(async () => {
  const response = await fetch("https://hyper.polynode.dev/v2/user/open-orders?address=0x...", {
    headers: { "x-api-key": API_KEY }
  });
  const orders = await response.json();
  reconcileState(orders);
}, 30000);

Exponential backoff with jitter

Don’t reconnect immediately in a tight loop. Use exponential backoff (1s, 2s, 4s, 8s, …) with random jitter to avoid thundering herd problems.

Error responses

HTTP errors during handshake

StatusMeaningAction
401Invalid or missing API keyCheck your key
403Key is disabledContact support
429Connection limit reachedClose other connections or upgrade tier

WebSocket errors after connection

Subscription errors are delivered as JSON messages:
{"error": "subscription limit reached for free tier (max 1)"}
Handle these in your message handler:
ws.on("message", (raw) => {
  const msg = JSON.parse(raw.toString());
  if (msg.error) {
    console.error("Server error:", msg.error);
    return;
  }
  handleEvent(msg);
});

Rate limits

  • Connections per key: determined by your tier (1 for free, 5 for starter, up to 500 for enterprise)
  • Subscriptions per connection: determined by your tier
  • Messages: no rate limit on inbound subscribe/unsubscribe messages
  • Events delivered: no throttling, you get everything matching your filters

Health checks

If you need to verify the service is up before connecting:
curl https://hyper.polynode.dev/health
Returns {"status":"ok"} when the stream service is running.

Browser clients

If running in a browser, handle tab visibility to avoid wasting resources:
document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    ws.close();
  } else {
    connect(); // Reconnect when tab becomes visible
  }
});