Snaapi supports realtime event streaming via Server-Sent Events (SSE). Connect to the stream endpoint to receive filtered, permission-aware events as they happen.
Server-Sent Events provide a one-way, persistent connection from the server to
the client. Events are streamed over HTTP with automatic reconnection support
built into the browser's EventSource API.
| Header | Value |
|---|---|
Content-Type |
text/event-stream |
Cache-Control |
no-cache |
Connection |
keep-alive |
X-Accel-Buffering |
no |
GET /v1/{resourceName}/stream
Requires authentication. The authenticated user's permissions determine which events and fields are visible.
| Parameter | Type | Default | Description |
|---|---|---|---|
events |
string |
created,updated,deleted |
Comma-separated event types to subscribe to |
fields |
string |
All allowed fields | Comma-separated field names to include |
Subscribe to all events for a resource:
GET /v1/posts/stream
Subscribe to only created and updated events:
GET /v1/posts/stream?events=created,updated
Subscribe with specific fields:
GET /v1/posts/stream?events=created&fields=title,author_id
Use the events query parameter to subscribe to specific event types. Valid
values are created, updated, and deleted.
Use the fields query parameter to limit which fields appear in the event data.
The following rules apply:
- Requested fields are intersected with the user's allowed fields (from permissions)
- System fields (
id,created_at,updated_at) are always included - The
changesarrays in event data are updated to reflect only filtered fields
Events are filtered based on the authenticated user's read permissions:
- Only events matching the user's filter constraints are delivered
- Only fields the user has permission to read are included
- Filter operators applied:
eq,neq,in,nin,gt,gte,lt,lte,is_null,is_not_null,like,ilike,regex,iregex,similar
The client connects with authentication credentials. On success, the server sends an initial message:
retry: 3000
: connected
The retry: 3000 directive tells the client to wait 3 seconds before attempting
to reconnect if the connection drops.
The server sends a heartbeat comment every 30 seconds to keep the connection alive and detect disconnects:
: heartbeat
When a matching event occurs, it is streamed in SSE format:
event: posts.created
data: {"old":null,"new":{"id":"abc-123","title":"Hello"},"changes":{"added":["id","title"],"updated":[],"removed":[]}}
id: event-uuid
retry: 3000
| SSE Field | Description |
|---|---|
event |
Event type (e.g., posts.created) |
data |
JSON-encoded event data (old/new/changes) |
id |
Event UUID (used for reconnection resumption) |
retry |
Reconnection delay in milliseconds |
When the client disconnects (network drop, tab close, explicit close):
- The server detects the disconnection
- The connection is cleaned up automatically
The browser's native EventSource API does not support custom headers like
Authorization. You have two options:
Option A: Pass the token as a query parameter (if your setup supports it):
const eventSource = new EventSource("/v1/posts/stream?token=<your-token>");Option B: Use an EventSource polyfill that supports custom headers, such as
eventsource from npm or @microsoft/fetch-event-source:
import { fetchEventSource } from "@microsoft/fetch-event-source";
let retryCount = 0;
const MAX_RETRIES = 10;
await fetchEventSource("/v1/posts/stream", {
headers: {
Authorization: "Bearer <your-token>",
},
onopen(response) {
if (response.ok) {
retryCount = 0;
console.log("Connected to event stream");
} else {
throw new Error(`Stream connection failed: ${response.status}`);
}
},
onmessage(event) {
const data = JSON.parse(event.data);
switch (event.event) {
case "posts.created":
console.log("New post:", data.new);
break;
case "posts.updated":
console.log("Updated fields:", data.changes.updated);
break;
case "posts.deleted":
console.log("Deleted post:", data.old.id);
break;
}
},
onerror(err) {
retryCount++;
console.error("Stream error:", err);
if (retryCount >= MAX_RETRIES) {
throw err; // stop retrying
}
// returning without throwing lets the library reconnect automatically
},
});Both approaches give you a persistent connection that automatically reconnects if it drops.
