API Reference
SSE (Server-Sent Events) API
Stream real-time events to browsers and HTTP clients using Server-Sent Events with token-based authentication.
The SSE API provides a persistent HTTP streaming connection for receiving real-time events. Clients create a stream token with one or more subscriptions, then connect using the native EventSource API or any HTTP client that supports streaming responses.
Info
SSE is ideal for browser dashboards, monitoring tools, and any client that only needs to receive events. Unlike WebSocket (bidirectional), SSE is server-to-client only but works with standard HTTP — no special proxy configuration required.
Concepts
- Stream Token — A time-limited credential (
sst_*) that grants access to a specific set of event subscriptions. Created via API, used as a query parameter to connect. - Subscription — A filter within a token that defines which events to receive. Supports event type patterns and payload filters.
- Replay Buffer — A per-token event history stored in Redis. When a client reconnects with
Last-Event-ID, missed events are replayed automatically. - Cross-Instance Delivery — Events are delivered to SSE clients regardless of which backend instance they're connected to, using Redis Pub/Sub. No sticky sessions required.
Create a Stream Token
POST /api/sse/tokenCreates a token with one or more event subscriptions.
Request Body:
| Field | Required | Description |
|---|---|---|
ttlMinutes | Yes | Token lifetime in minutes (5–60) |
subscriptions | Yes | Array of subscription objects |
subscriptions[].events | Yes | Event type patterns (e.g. ["session.status", "annotation.*"]) |
subscriptions[].filter | No | Payload filter for this subscription |
bufferSize | No | Replay buffer size (default 1000, max 5000) |
Example:
curl -X POST /api/sse/token \
-H "Content-Type: application/json" \
-H "X-Application-Id: app_abc123" \
-H "X-Environment: production" \
-d '{
"ttlMinutes": 30,
"subscriptions": [
{ "events": ["session.status", "session.closed"], "filter": { "installSid": "AI4b56b78..." } },
{ "events": ["annotation.*"] }
],
"bufferSize": 2000
}'Response (201):
{
"streamToken": "sst_a1b2c3d4e5f6...",
"tokenId": "stk_xyz789",
"expiresAt": "2026-06-27T00:27:00.000Z",
"subscriptions": [
{ "id": "ssub_001", "events": ["session.status", "session.closed"], "filter": { "installSid": "AI4b56b78..." } },
{ "id": "ssub_002", "events": ["annotation.*"] }
],
"bufferSize": 2000
}Connect to Stream
GET /api/sse/stream?token=sst_a1b2c3d4e5f6...Opens a persistent SSE connection. Events matching any of the token's subscriptions are pushed to the client.
Query Parameters:
| Parameter | Required | Description |
|---|---|---|
token | Yes | The stream token from token creation |
lastEventId | No | Resume from this event ID (alternative to Last-Event-ID header) |
Headers:
| Header | Description |
|---|---|
Last-Event-ID | Standard SSE reconnection header — resumes from this ID |
Example (browser):
const stream = new EventSource('/api/sse/stream?token=sst_a1b2c3d4e5f6...');
stream.addEventListener('session.status', (e) => {
const event = JSON.parse(e.data);
console.log('Session status:', event);
// { subscriptionId: "ssub_001", sid: "ES123", status: "Open", ... }
});
stream.addEventListener('annotation.created', (e) => {
const event = JSON.parse(e.data);
console.log('Annotation:', event);
});
// System events
stream.addEventListener('token_expiring', (e) => {
console.warn('Token expiring soon, extend it!');
// Call /api/sse/token/extend
});
stream.addEventListener('token_expired', () => {
stream.close();
});Example (curl):
curl -N "https://api.example.com/api/sse/stream?token=sst_a1b2c3d4e5f6..."SSE Frame Format:
id: evt_abc123
event: session.status
data: {"subscriptionId":"ssub_001","sid":"ES123","status":"Open","installSid":"AI4b56b78..."}System Events:
| Event | When | Data |
|---|---|---|
token_expiring | 30 seconds before token expires | { "expiresAt": "...", "message": "..." } |
token_expired | Token has expired | { "message": "Stream token expired" } |
token_extended | Token TTL was extended | { "expiresAt": "..." } |
token_revoked | Token was explicitly revoked | { "message": "Token has been revoked" } |
server_shutdown | Server is shutting down | { "message": "Server shutting down" } |
Heartbeat: A :heartbeat comment is sent every 15 seconds to keep the connection alive through proxies and load balancers.
Extend a Token
POST /api/sse/token/extendExtends the TTL of an existing token without disconnecting the stream. Can also add or remove subscriptions.
Request Body:
| Field | Required | Description |
|---|---|---|
token | Yes | The raw stream token to extend |
ttlMinutes | Yes | New TTL from now (5–60 minutes) |
addSubscriptions | No | Additional subscriptions to add |
removeSubscriptions | No | Subscription IDs to remove |
Example:
curl -X POST /api/sse/token/extend \
-H "Content-Type: application/json" \
-d '{
"token": "sst_a1b2c3d4e5f6...",
"ttlMinutes": 30,
"addSubscriptions": [
{ "events": ["exam.*"] }
],
"removeSubscriptions": ["ssub_002"]
}'Response (200):
{
"tokenId": "stk_xyz789",
"expiresAt": "2026-06-27T00:57:00.000Z",
"subscriptions": [
{ "id": "ssub_001", "events": ["session.status", "session.closed"], "filter": { "installSid": "AI4b56b78..." } },
{ "id": "ssub_003", "events": ["exam.*"] }
],
"bufferSize": 2000
}Connected clients automatically receive a token_extended event on their stream.
Revoke a Token
DELETE /api/sse/token/:tokenIdImmediately revokes a token. Any connected clients using this token receive a token_revoked event and are disconnected.
Example:
curl -X DELETE /api/sse/token/stk_xyz789List Active Connections
GET /api/sse/connectionsReturns all active SSE connections on this instance.
Response:
{
"connections": [
{
"id": "sse_abc123",
"tokenId": "stk_xyz789",
"connectedAt": 1719446820000,
"eventsDelivered": 42,
"lastEventId": "evt_def456"
}
],
"total": 1
}Event Matching
SSE subscriptions use the same matching logic as webhooks and WebSocket subscriptions:
Event Type Patterns:
| Pattern | Matches |
|---|---|
session.status | Exactly session.status |
session.* | Any event starting with session. |
* | All events |
Payload Filters (AND logic):
{
"filter": {
"installSid": "AI4b56b78...",
"status": "Open"
}
}An event matches only if ALL filter conditions are satisfied.
Replay on Reconnect
When a client reconnects (browser auto-reconnect, network blip), events missed during disconnection are replayed from the Redis-backed buffer:
- Client disconnects
- Events continue flowing into the replay buffer (up to
bufferSizeevents per token) - Client reconnects with
Last-Event-IDheader (sent automatically byEventSource) - Server replays all events after that ID, then continues live streaming
The replay buffer TTL matches the token TTL — once the token expires, the buffer is cleared.
Security
- Token scoping — Each token is scoped to a specific application and environment. Events from other apps/environments are never delivered.
- Token hashing — Tokens are stored as SHA-256 hashes in Redis. The raw token is only returned once on creation.
- TTL enforcement — Tokens automatically expire. The server closes connections for expired tokens and cleans up resources.
- Rate limiting — The
/api/sse/tokenendpoint is subject to the standard API rate limiter.
Horizontal Scaling
SSE works across multiple backend instances without sticky sessions:
- CDC leader dispatches event → publishes to Redis Pub/Sub channel
- All instances receive the event via their Pub/Sub subscription
- Each instance checks its local SSE clients for matching subscriptions
- Matching clients receive the event regardless of which instance they're connected to
This means you can scale horizontally behind a standard round-robin load balancer.