Realtime

cstar.realtime opens a Server-Sent Events stream and dispatches every event the team's API key can see. Auto-reconnect with exponential backoff, gap replay via Last-Event-ID, and the same wildcards the webhook subscriptions accept.

Subscribe to specific events

subscribe.js
// Specific event
const offCreated = cstar.realtime.on('ticket.created', (event) => {
  console.log('New ticket', event.data.ticket.id);
});

// Wildcard
const offAllTickets = cstar.realtime.on('ticket.*', (event) => {
  console.log(event.type, event.data);
});

// Tear down
offCreated();
offAllTickets();

Subscribe to everything

onany.js
const off = cstar.realtime.onAny((event) => {
  log.event(event.type, event.data);
});

Connection lifecycle

lifecycle.js
cstar.realtime.onConnectionChange((connected) => {
  // Show or hide your "live" indicator
  setLiveIndicator(connected);
});

cstar.realtime.onError((err) => {
  console.warn('SSE error', err);
});

console.log(cstar.realtime.connected); // boolean

// Tear everything down on logout (also cleans up the realtime client)
cstar.destroy();

Revoking the API key ends its streams within about 10 seconds. The server sends an event: revoked frame and closes the stream; the client then stops reconnecting and onError receives one CStarAuthenticationError with code invalid_api_key. Create a new client with a working key to listen again.

Server rendering

The stream uses EventSource, which browsers provide. Where it is missing, as in a server render or plain Node, a subscription throws CStarRealtimeUnavailableError. Subscribe from a client-only path instead: onMount in Svelte, useEffect in React. To subscribe from a runtime without the global, pass a polyfill as realtime.eventSource.

node-stream.js
import { EventSource } from 'eventsource'; // npm install eventsource

const cstar = new CStarClient({
  apiKey: process.env.CSTAR_KEY,
  teamId: process.env.CSTAR_TEAM_ID,
  realtime: { eventSource: EventSource }
});

Server-side filters

Pass realtime.types when constructing the client to scope the stream at the server. The default streams every event. A list of exact event names cuts traffic and handler work.

scoped.js
const cstar = new CStarClient({
  apiKey: process.env.CSTAR_KEY,
  teamId: process.env.CSTAR_TEAM_ID,
  realtime: {
    types: ['ticket.created', 'ticket.updated'], // Exact names, no wildcards
    autoReconnect: true,  // Default
    maxRetries: 10        // Reconnect attempts (default 10)
  }
});

cstar.realtime.on('ticket.created', handler);
cstar.realtime.on('ticket.updated', handler);

Realtime vs. webhooks

Webhooks deliver to a server you host; realtime delivers to a client you've already authenticated. Use webhooks when the receiver is your backend (CRM sync, billing automation). Use realtime when the receiver is your own dashboard or admin app: no public endpoint to expose, no signing secret to store.

Next up