SDK
SSE Client
Receive server-pushed events over HTTP using the SDK's SSE client with automatic token management and reconnection.
The SseClient provides a high-level API for receiving events via Server-Sent Events (SSE). Unlike the WebSocket-based RealtimeClient (bidirectional), the SSE client is receive-only — ideal for dashboards, monitoring tools, and any scenario where you only need to consume events without sending messages.
Info
The SSE client handles token creation, stream connection, event parsing, auto-reconnection (via native EventSource), and automatic token extension. It's a standalone class — you don't need a RealtimeClient to use it.
Quick Start
import { SseClient } from '@smarterservices/realtime';
const sse = new SseClient({
url: 'https://api.example.com',
applicationId: 'app_abc123',
environment: 'production',
subscriptions: [
{ events: ['proctoring.session.created', 'proctoring.session.updated'] },
{ events: ['document.*'] },
],
});
// Listen for events
sse.on('event:proctoring.session.updated', (event) => {
console.log('Session updated:', event);
});
sse.on('event', (event) => {
console.log('Any event:', event.type, event);
});
// Connect — creates a token and opens the SSE stream
await sse.connect();Constructor
new SseClient(options: SseClientOptions)SseClientOptions
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
url | string | Yes | — | Backend API base URL (e.g. "https://api.example.com") |
applicationId | string | Yes | — | Application ID for scoping |
environment | string | Yes | — | Environment ("development", "staging", "production") |
subscriptions | SseSubscriptionInput[] | Yes | — | Event subscriptions (at least one required) |
ttlMinutes | number | No | 30 | Token lifetime in minutes (5–60) |
bufferSize | number | No | 1000 | Replay buffer size (max 5000) |
autoExtend | boolean | No | true | Automatically extend the token 60s before expiry |
authHeader | string | No | — | Authorization header value (e.g. "Bearer <jwt>") |
SseSubscriptionInput
| Field | Type | Required | Description |
|---|---|---|---|
events | string[] | Yes | Event type patterns (e.g. ["session.updated", "document.*"]) |
filter | SubscriptionFilter | No | Payload filter — only events matching all key/value pairs are delivered |
const sse = new SseClient({
url: 'https://api.example.com',
applicationId: 'app_abc123',
environment: 'production',
subscriptions: [
{
events: ['proctoring.session.created', 'proctoring.session.updated'],
filter: { installSid: 'AI4b56b78...' },
},
],
ttlMinutes: 60,
bufferSize: 2000,
autoExtend: true,
authHeader: 'Bearer eyJhbGci...',
});Methods
connect()
Creates a stream token via the SSE API and opens the EventSource connection. Resolves when the connection is established.
await sse.connect();disconnect()
Closes the SSE stream and stops auto-extend timers. Does not revoke the token.
sse.disconnect();extendToken(ttlMinutes?, addSubscriptions?, removeSubscriptions?)
Extends the current token's TTL. Can also add or remove subscriptions dynamically.
// Extend by 30 minutes
await sse.extendToken(30);
// Extend and add a new subscription
await sse.extendToken(30, [{ events: ['audit.*'] }]);
// Extend and remove a subscription
await sse.extendToken(30, undefined, ['ssub_002']);revoke()
Revokes the current token and disconnects. Connected streams receive a token_revoked event.
await sse.revoke();destroy()
Disconnects, revokes the token, and removes all event listeners. Call when the client is no longer needed.
await sse.destroy();on(event, handler) / off(event, handler)
Register or remove event listeners.
sse.on('event:session.updated', handler);
sse.off('event:session.updated', handler);Event Names
| Event | Payload | Description |
|---|---|---|
'event' | SseEvent | Fires for every received event |
'event:<type>' | SseEvent | Fires for events matching a specific type (e.g. 'event:session.updated') |
'connection' | { state: SseConnectionState } | Fires on connection state changes |
'token_expiring' | { expiresAt, message } | Fires ~30s before token expiry |
'token_extended' | { expiresAt } | Fires when the token is successfully extended |
'error' | { message: string } | Fires on connection errors, token expiry, or revocation |
Read-Only Properties
| Property | Type | Description |
|---|---|---|
sse.state | SseConnectionState | 'disconnected', 'connecting', 'connected', or 'reconnecting' |
sse.connected | boolean | true if connected |
sse.token | SseTokenInfo | null | Current token metadata |
SseEvent
Events received from the SSE stream have this shape:
interface SseEvent {
type: string; // e.g. "proctoring.session.updated"
subscriptionId?: string; // which subscription matched (e.g. "ssub_001")
[key: string]: unknown; // event payload fields
}The type field is always present — the server includes it in the data payload (self-describing events), so clients can identify the event type regardless of which EventSource listener pattern they use.
Automatic Reconnection
The SSE client uses the browser's native EventSource API, which automatically reconnects when the connection drops. On reconnect, the Last-Event-ID header is sent automatically, and the server replays any missed events from the replay buffer.
sse.on('connection', ({ state }) => {
if (state === 'reconnecting') {
console.log('Connection lost, auto-reconnecting...');
}
if (state === 'connected') {
console.log('Connected — events flowing');
}
});Token Auto-Extension
When autoExtend is true (the default), the client automatically extends the token 60 seconds before it expires. This keeps the stream alive indefinitely without manual intervention.
To handle extension failures:
sse.on('error', ({ message }) => {
if (message.startsWith('Auto-extend failed')) {
// Token extension failed — stream will close when token expires
console.warn(message);
}
});Entity Key Filtering
Use filter in subscriptions to scope events to specific tenants:
const sse = new SseClient({
url: 'https://api.example.com',
applicationId: 'app_abc123',
environment: 'production',
subscriptions: [
{
events: ['proctoring.session.created', 'proctoring.session.updated'],
filter: {
installSid: 'AI4b56b78...',
proctorAccountLocationSid: 'PAL_xyz789',
},
},
],
});Filter rules use AND logic — all key/value pairs must match the event payload for the event to be delivered.
SSE vs WebSocket
| Feature | SseClient | RealtimeClient |
|---|---|---|
| Direction | Server → Client (receive only) | Bidirectional |
| Protocol | HTTP streaming (EventSource) | WebSocket (Socket.IO) |
| Auth | Token-based (per-stream) | JWT (per-connection) |
| Reconnection | Native EventSource auto-reconnect | Socket.IO auto-reconnect |
| Replay | Last-Event-ID replay buffer | No built-in replay |
| Proxy support | Standard HTTP — no special config | May need WebSocket-aware proxy |
| Use case | Dashboards, monitoring, event feeds | Interactive apps, document sync, chat |
Use SseClient when you only need to receive events (dashboards, webhooks-over-HTTP, monitoring). Use RealtimeClient when you need bidirectional communication (document sync, socket messaging, presence).
TypeScript Types
All types are exported from the SDK:
import type {
SseClientOptions,
SseSubscriptionInput,
SseConnectionState,
SseTokenInfo,
SseEvent,
} from '@smarterservices/realtime';
import { SseClient } from '@smarterservices/realtime';