/

Streams

One WebSocket delivers trades, prices, wallet activity, launches and graduations about half a second after each checkpoint. Resume after short gaps with a sequence number.

Works onSui

Connect

Subscribe with {"op":"subscribe","topics":[...]}. Send your key as a Bearer header, or as {"op":"auth","key":"..."} in your first message. No key works too, with smaller limits.

WebSocketwss://yolo.casa/api/v1/stream
SSEhttps://yolo.casa/api/v1/stream/sse?topics=launches

Try it

Opens a real connection from your browser.

Connect to watch events arrive. No key needed.

Topics

TopicEventWhat you get
trades:<coinType>tradeEvery trade of one coin.
price:<coinType>priceOne coin's price, at most two ticks a second.
wallet:<address>tradeTrades made by one wallet.
launcheslaunchEvery new launchpad coin.
launches:<launchpad>launchNew coins on one launchpad.
graduationsgraduationCoins that bonded and left their curve.
large_tradestradeTrades of $10,000 or more.
large_trades:<usd>tradeTrades of at least this many dollars, 1000 or more.
firehosetradeEvery trade, launch and graduation. Funded keys only.
pricespriceEvery coin's price ticks. Funded keys only.

Limits

No keyFree keyFunded key
Connections2320
Topics per connection101002,000
Wallets watched325500
Firehose and all pricesNoNo1 credit a minute

Example client

Reconnects on silence and resumes from the last event it saw.

// Node 22+ or any browser. Reconnects and resumes after short gaps.
const topics = ['large_trades:5000', 'launches'];
let epoch = null, seq = 0;

function connect() {
  const ws = new WebSocket('wss://yolo.casa/api/v1/stream');
  let alive = Date.now();
  ws.onopen = () => {
    // Optional: a key raises the limits. Leave it out to stay anonymous.
    if (process.env.YOLO_API_KEY)
      ws.send(JSON.stringify({ op: 'auth', key: process.env.YOLO_API_KEY }));
    ws.send(JSON.stringify({
      op: 'subscribe', topics,
      ...(epoch ? { resume: { epoch, seq } } : {}),
    }));
  };
  ws.onmessage = (e) => {
    alive = Date.now();
    const m = JSON.parse(e.data);
    if (m.type === 'hello') epoch = epoch ?? m.epoch;
    if (m.type === 'resume_failed') { epoch = m.epoch; seq = m.seq; /* refetch over REST */ }
    if (m.type === 'event') { seq = m.seq; console.log(m.channel, m.topics, m.data); }
  };
  // The server pings every 15 s. Silence for 45 s means the link is dead.
  const watch = setInterval(() => { if (Date.now() - alive > 45_000) ws.close(); }, 5_000);
  ws.onclose = () => { clearInterval(watch); setTimeout(connect, 1_000); };
}
connect();

Reconnecting

Every event has a sequence number. The server pings every 15 seconds; reconnect after 45 seconds of silence. On reconnect, pass the last epoch and seq you saw as resume to receive what you missed, for gaps of up to about two minutes. A resume_failed reply means the gap is gone: refetch over REST.

Clients that fall too far behind are closed with code 4008. Other close codes: 4001 invalid key, 4009 key revoked, 4029 connection limit, 4000 server restart. Server-Sent Events resume with Last-Event-ID.