Events and Real-time Updates
ScaiDrive exposes change events two ways: a persistent per-tenant change log that drives the cursor-based sync protocol, and a WebSocket stream for low-latency notifications. They share the same underlying data — the WebSocket is a tail of the log, the polling API is a seek-and-read.
The change log#
Every mutation on a tenant writes exactly one row to ChangeLog:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Change types: created, updated, deleted, moved, renamed.
Resource types: file, folder, share.
The log is append-only and ordered. It's consumed via GET /api/v1/sync/changes — see Sync Model.
Real-time WebSocket#
Two WebSocket endpoints:
| Endpoint | Purpose |
|---|---|
/api/v1/sync/ws/{device_id}?token=<JWT> |
Per-device sync nudges. For sync clients |
/api/v1/realtime/ws?token=<JWT> |
General real-time updates for the authenticated user. For UIs |
Both authenticate via a token query parameter (the JWT) since browsers can't set custom headers on WebSocket connections.
Sync WebSocket#
Used by clients that replicate content locally. A sync client connects, subscribes to its shares implicitly (based on user access), and receives nudges:
1 2 3 4 | |
Client-to-server messages:
1 2 | |
The nudge tells the client "something happened" — the client still goes through the cursor-based pull to fetch changes. The WebSocket is not the source of truth.
Realtime WebSocket (UI)#
Used by web and mobile UIs. Subscribe explicitly to shares you want updates for:
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 9 10 11 | |
Server-to-client frame types:
| Frame | Payload |
|---|---|
connected |
{user_id, timestamp} |
subscribed |
{share_id} |
unsubscribed |
{share_id} |
file_created |
{share_id, data: file metadata} |
file_updated |
{share_id, data: file metadata} |
file_deleted |
{share_id, data: {file_id}} |
folder_created |
{share_id, data: folder metadata} |
folder_deleted |
{share_id, data: {folder_id}} |
pong |
response to ping |
Client-to-server actions: subscribe, unsubscribe, ping.
Unlike the sync WebSocket, realtime frames carry full resource metadata in data so a UI can update without a re-fetch.
See Real-time WebSocket for reconnection, heartbeats, and back-pressure handling.
ScaiKey webhooks (inbound)#
ScaiDrive receives webhooks from ScaiKey to keep user and group records in sync. These are inbound to the ScaiDrive server; you don't configure them from your application.
1 | |
Events:
user.created,user.updated,user.deletedgroup.created,group.updated,group.deleted
ScaiDrive verifies the signature header set by ScaiKey before processing.
Outbound webhooks#
Outbound webhooks — ScaiDrive calling your endpoint — are not currently available in the core API. For now, use the WebSocket for real-time or GET /api/v1/sync/changes for scheduled polling. If your use case is SIEM integration or compliance, see Enterprise Compliance for the audit-event streaming options.
Audit events#
Distinct from the change log: audit events record who did what, including non-mutating actions (logins, downloads, permission checks). Audit events are exposed through the enterprise audit API and forwarded to SIEM integrations when configured.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
The category field is one of authentication, authorization, file_access, file_modification, sharing, admin, security, compliance. The service_account field carries the RFC 8693 act.client_id from the JWT when the request reached us through a token-exchange flow — null otherwise. See Enterprise Compliance for the full event-type vocabulary and severity escalation rules.
What's next#
- Sync Model — the cursor protocol that consumes the change log.
- Real-time WebSocket — advanced WebSocket usage.
- Enterprise Compliance — audit and SIEM.