CRIUS Docs
API status Get API key
Get started

Real-time stream example

A complete reconnecting WebSocket client for the Crius stream in Node.js - subscribe to new launches, trades and prices on Robinhood Chain, resume after disconnects and handle reorgs.

Updated 1 min read

This client subscribes to every new launch and graduation plus the trades of one token, reconnects with backoff, resumes the messages it missed, and undoes reorged events. It runs on Node.js 22+ (built-in WebSocket) with a key that has the stream scope.

// stream.mjs: node stream.mjs
const KEY = process.env.CRIUS_API_KEY;
const TOKEN = "0x7b8892cea949bc60d494681d1bc3ea96071ab0b8";
const CHANNELS = ["launches:all", "graduations:all", `trades:${TOKEN}`, `price:${TOKEN}`];
const lastSeq = {}; // channel -> last seq seen, for resuming
let backoff = 1000;
function connect() {
const ws = new WebSocket(`wss://api.crius.sh/v1/robinhood/stream?api_key=${KEY}`);
let idle;
const touch = () => {
clearTimeout(idle);
idle = setTimeout(() => ws.close(), 45_000); // heartbeats come every 15 s
};
ws.onopen = () => {
backoff = 1000;
touch();
ws.send(JSON.stringify({ op: "subscribe", channels: CHANNELS }));
if (Object.keys(lastSeq).length) ws.send(JSON.stringify({ op: "resume", seqs: lastSeq }));
};
ws.onmessage = (e) => {
touch();
const m = JSON.parse(e.data);
if (m.seq) lastSeq[m.ch] = m.seq;
switch (true) {
case m.ch === "reorg":
console.warn(`reorg: blocks ${m.data.removed_blocks.join(", ")} replaced`);
break;
case m.data?.removed:
console.warn(`undo ${m.ch} ${m.data.id}`); // reverse whatever you did for this event id
break;
case m.ch.startsWith("launches:"):
console.log(`new ${m.data.launchpad} token ${m.data.address} by ${m.data.creator}`);
break;
case m.ch.startsWith("graduations:"):
console.log(`graduated ${m.data.token} → pool ${m.data.pool}`);
break;
case m.ch.startsWith("trades:"):
console.log(`${m.data.type} $${m.data.value_usd} by ${m.data.trader}`);
break;
case m.ch.startsWith("price:"):
console.log(`price $${m.data.usd}`);
break;
case m.ch === "error":
console.error(m.data);
break;
}
};
ws.onclose = () => {
clearTimeout(idle);
setTimeout(connect, backoff + Math.random() * 500);
backoff = Math.min(backoff * 2, 30_000);
};
ws.onerror = () => ws.close();
}
connect();

Browser version

Browsers can’t set headers on WebSockets, so the key would have to go in the URL (?api_key=), where anyone can read it from your page. Connect from your backend instead and forward the events to your page (for example over Server-Sent Events). Keys restricted to browser origins are read-only and can’t open the stream.

Get your free Crius API key

Every example on this page works with a free key: higher rate limits than the anonymous plan, holders, wallets and the WebSocket stream. No card needed.

  • Robinhood Chain (4663) only, from our own archive nodes
  • REST + WebSocket
  • Pay on-chain or by card