WS wss://api.crius.sh/v1/{chain}/stream
Plan: Free and above, key with the stream scope · Cost: 1 credit per connection
One connection carries many subscriptions. Messages are pushed as soon as a block is decoded, typically well under a second after it was produced.
Connecting
Section titled “Connecting”Authenticate with the x-api-key header, or with ?api_key= where a client can’t set headers (browsers):
const ws = new WebSocket(`wss://api.crius.sh/v1/robinhood/stream?api_key=${key}`);On connect the server sends a greeting with your limits:
{"ch": "hello", "data": {"chain": "robinhood", "heartbeat_s": 15, "max_subscriptions": 10}}Operations
Section titled “Operations”Send JSON messages with an op:
| Op | Message | Reply |
|---|---|---|
| Subscribe | {"op": "subscribe", "channels": ["trades:0x…", "launches:all"]} |
{"ch": "subscribed", "data": {"channels": […], "finality": "latest"}} |
| Unsubscribe | {"op": "unsubscribe", "channels": ["trades:0x…"]} |
{"ch": "unsubscribed", …} |
| Settled data only | {"op": "subscribe", "channels": […], "finality": "safe"} |
events are held until their block is safe |
| Resume after a reconnect | {"op": "resume", "seqs": {"trades:0x…": 90455}} |
missed messages (up to 60 s), then {"ch": "resumed"} |
| Ping | {"op": "ping"} |
{"ch": "pong", "ts": …} |
Channel names are lowercase. Subscribing over your plan’s limit, or to an Enterprise channel, returns {"ch": "error", "data": {"code": "channel_denied", …}} for those channels.
Channels
Section titled “Channels”| Channel | Pushes |
|---|---|
trades:<token> |
Every trade of a token (same shape as the trade tape) |
trades:pool:<pool> |
Every trade in one pool |
price:<token> |
Price updates (usd, eth, liquidity_usd); a snapshot is sent right after subscribing |
candles:<token>:<interval> |
The live candle (t, o, h, l, c, v, n) for 1s … 1d |
token:<token> |
Price and holder count changes |
tax:<token> |
Realized buy/sell tax changes |
lp:<token> |
Liquidity added or removed in the token’s pools |
launches:<launchpad> / launches:all |
New launches (pons, flap, …) |
graduations:<launchpad> / graduations:all |
Graduations, with the new pool |
pools:new |
Every new Uniswap v2 / v3 / v4 pool, with hook permissions |
wallet:<address> |
Trades and transfers of a wallet |
dev:<address> |
New tokens launched by a creator |
firehose:trades |
Every trade on the chain (Enterprise) |
Every message has the same envelope:
{ "ch": "trades:0x0bd7d308f8e1639fab988df18a8011f41eacad73", "seq": 90455, "block": 95503752, "ts": 1792712930000, "data": { "id": "95503752-4-7", "type": "buy", "token": "0x0bd7d308f8e1639fab988df18a8011f41eacad73", "symbol": "WETH", "dex": "uniswap_v4", "trader": "0x2192bc3b4028acc1113f2cd9ac2cba70c36520db", "amount_base": 0.02724675461168212, "amount_quote": 64.939074, "price_usd": 2383.37, "value_usd": 64.9391 }}seq increases by one per channel. Keep the last seq you saw for each channel and send them in a resume op after reconnecting to receive what you missed (60-second replay buffer).
Heartbeats, finality and reorgs
Section titled “Heartbeats, finality and reorgs”{"ch": "heartbeat", "ts": …, "uptime_s": …}arrives every 15 seconds; reconnect if you hear nothing for 45 seconds.{"ch": "finality", "data": {"safe_block": …, "finalized_block": …}}arrives on every connection whenever the safe or finalized block moves.- If blocks are replaced, a
{"ch": "reorg", "data": {"common_ancestor", "removed_blocks", "depth"}}message comes first, then every affected event is re-sent with"removed": true(sameid), then the replacement events. Subscribe with"finality": "safe"if you never want to see reorged events.