Skip to content
Cirrus home
Sign in

Guide

The live stream

Open one WebSocket and get your orders, positions, holdings and funds as they change, without polling.

/v1/stream is a WebSocket. It first sends everything you have (a snapshot), then every change. Needs the read scope.

Connect #

Send the key in the Authorization header when connecting, or as the first message within 5 seconds. Keys are never read from the URL.

const socket = new WebSocket('wss://cirrus.pocketful.in/v1/stream');
socket.onopen = () =>
  socket.send(JSON.stringify({ type: 'auth', token: process.env.CIRRUS_API_KEY }));
socket.onmessage = (event) => {
  const message = JSON.parse(event.data);
  // message.type: hello | snapshot | snapshot_done | order_update | portfolio | error
  console.log(message.seq, message.type, message.account);
};
socket.onclose = (event) => console.log('closed', event.code, event.reason);

What you get #

MessageMeans
helloConnected: your user and accounts.
snapshotThe full state of one account and kind (orders, positions, holdings, trades, margins).
snapshot_doneAll snapshots sent; live changes follow.
order_updateOne order changed: the whole order.
portfolioOne kind of one account changed: the whole list.
activityA new activity-log entry.
errorSomething went wrong; code and message say what.
  • Every message has a seq (1, 2, 3 …). After a gap, send {"type": "resync"} to get fresh snapshots.
  • Changes carry full state, never a diff, so a missed message is fixed by the next one.
  • The server pings every 15 s. A revoked key closes the stream within 10 s.

When it closes #

CodeReasonMeaning
4001unauthorizedBad first message or credential, or revoked.
4002auth timeoutNo auth message within 5 s.
1013slow consumerYou fell too far behind; reconnect.
1001server shutdownRolling deploy; reconnect.
1000idleNothing heard from the client for 45 s.

Reconnect with backoff after any close except 4001; each new connection starts with a fresh snapshot.

In the reference