Airwave

Live events (SSE)

Stream Airwave events in real time over a single connection, for a Tauri app or a live dashboard.

For an always-connected client, a Tauri desktop app or a wall-mounted dashboard, Airwave streams events over Server-Sent Events instead of pushing to a URL. You hold one long-lived connection and receive the same envelopes the webhooks deliver, the moment they happen.

Connect

GET /api/public/v1/events

Authenticate with an API key from Settings → API Keys, as either the X-API-Key header (for a fetch-based client) or, since a browser EventSource can't set headers, the ?api_key= query parameter. Add ?types=session.started,session.ended to receive only certain events.

// browser / webview
const es = new EventSource(
  "http://192.168.1.10:36020/api/public/v1/events?api_key=airwave_your_key",
);
es.addEventListener("session.started", (e) => {
  const { data } = JSON.parse(e.data);
  console.log(`${data.user} started watching ${data.channel.name}`);
});
es.addEventListener("session.ended", (e) => {
  /* … */
});
# curl — watch the raw stream
curl -N -H "X-API-Key: airwave_your_key" \
  "http://192.168.1.10:36020/api/public/v1/events?types=session.started,session.ended"

The stream

Each message is an SSE frame whose event: is the event type and whose data: is the JSON envelope ({ id, type, timestamp, data }, the same shape and the same rich data a webhook carries: deviceId, channel, program, playbackState, delaySeconds, and progress). On connect you get a hello frame, and a keepalive frame arrives periodically so idle proxies don't drop the connection:

event: hello
data: {"product":"airwave","filter":"all"}

event: session.started
data: {"id":"evt_2a9f…","type":"session.started","timestamp":"2026-09-28T18:04:11.000Z","data":{"userId":"clx9user01","deviceId":"tauri-88ac21","user":"James","channel":{"id":"clx9ch01","number":101,"name":"90s Sitcoms","callsign":"SITCOM"},"program":{"ratingKey":"45210","title":"The One with the Blackout","showTitle":"Friends","season":1,"episode":7,"year":1994},"playbackState":"playing","delaySeconds":0,"progress":{"positionSeconds":0,"durationSeconds":1380}}}

event: keepalive
data: {"t":1790000666000}

The same event catalog applies: playback.* events stream for clients that report play/pause state, and channel.tuned streams for clients that keep a session across channel changes.

A browser EventSource reconnects on its own if the connection drops. For a fetch-based client, reconnect on error with a short backoff.

SSE or webhooks?

  • SSE suits a client that stays open and wants events live (a Tauri app, a dashboard). Nothing is stored; if the client is disconnected it simply misses events while away.
  • Webhooks suit a server-side integration (Home Assistant, n8n): Airwave POSTs to your URL with retries, so you don't need to hold a connection.

Both carry the same events and the same payloads.

On this page