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/eventsAuthenticate 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.
