Skip to content

WebSocket

The WebSocket interface provides real-time push notifications for all data changes and system events.

ws://<your-server>:7200/ws?token=<JWT_ACCESS_TOKEN>

The JWT token is passed as a query parameter because the browser WebSocket API does not support custom headers. The server validates the JWT and associates the connection with the user.

If the token is invalid, the server closes the connection with code 4401.

All server events follow this structure:

{
"event": "note.created",
"data": {
"id": "550e8400-...",
"title": "Meeting notes",
"created_at": "2026-02-16T10:30:00Z"
},
"timestamp": "2026-02-16T10:30:00.123Z"
}

The client sends JSON messages with { "action": "...", "data": {...} }:

ActionDescriptionData
chat.sendSend message to AI agent{message, conversation_id, agent?, context?}
subscribeSubscribe to specific events{events: ["note.*", ...]}
unsubscribeUnsubscribe from events{events: ["agent.*"]}
pongHeartbeat response(none)

By default, the client receives all events. To filter:

{
"action": "subscribe",
"events": ["note.*", "event.*", "sync.*"]
}

Patterns:

  • "note.created" — specific event
  • "note.*" — all events for a domain
  • "*" — all events (default)

Subscriptions can be changed at any time during the connection.

The server sends a ping every 30 seconds:

{ "event": "ping", "timestamp": "2026-02-16T10:30:30.000Z" }

The client must respond with { "action": "pong" }. Connections without a pong within 90 seconds are closed.

Emitted when records change via REST API. Pattern: <domain>.<action>.

DomainEventsData
Notesnote.created, updated, deleted, restoredFull record (or {id, permanent} for delete)
Eventsevent.created, updated, deleted, restoredFull record
Contactscontact.created, updated, deleted, restoredFull record
Emailsemail.created, updated, deleted, restoredFull record
Emails (send)email.queued, sent, send_failed, snoozed, unsnoozed, scheduledVaries per event
Email Accountsemail_account.created, updated, deleted, status_changedFull record / status details
Filesfile.created, updated, deleted, restoredFull record
Diarydiary.created, updated, deleted, restoredFull record
Bookmarksbookmark.created, updated, deleted, checkedRecord / {id, is_alive, status_code}
Albumsalbum.created, updated, deleted, restored, photo_added, photo_removedRecord / photo details
Sharesshare.created, deletedShare details
Snapshotssnapshot.created, restored, deleted, purgedSnapshot details
EventWhenData
chat.stream.startAgent starts processing{conversation_id, agent}
chat.stream.tokenPartial response token{conversation_id, token}
chat.stream.doneFull response complete{conversation_id, full_text, model, tokens_used}
EventWhenData
approval.requestedApproval requested{id, action, domain, record_id, level}
approval.resolvedApproval resolved{id, decision, resolved_by}
approval.expiredApproval expired{id, action, expired_at}
EventWhenData
digest.readyDigest compiled{digest_id, alert_level, summary, changes_count, domains}
digest.urgentUrgent digest{digest_id, alert_level: "URGENT", summary}
EventWhenData
voice.session_startedVoice session started{session_id, channel, language}
voice.transcriptionTranscription received{session_id, text, confidence, is_final}
voice.responseVoice response generated{session_id, text, audio_url?}
voice.session_endedVoice session ended{session_id, duration_ms}
EventWhenData
sync.startedConnector started syncing{connector_id, started_at}
sync.progressSync progress update{connector_id, records_processed, total_estimated}
sync.completedSync completed{connector_id, records_created, records_updated, duration_ms}
sync.errorSync error{connector_id, error_message}
EventWhenData
system.health_changedService status changed{service, old_status, new_status}
system.storage_alertDisk full or SMART warning{disk_id, alert_type, message}
settings.updatedConfiguration updated{section, changes}
license.changedTier changed{old_tier, new_tier}
EventWhenData
browser.startedBrowser session started{session_id}
browser.navigatingNavigating to URL{session_id, url}
browser.snapshotScreenshot captured{session_id, base64, url?, screenshot_id?}
browser.completeSession ended{session_id, pages_visited}
EventWhenData
agent.session_startedNew agent session{session_id, agent, model}
agent.session_endedSession ended{session_id, agent, tokens_used, duration_ms}
agent.messageAgent message (streaming){session_id, from_agent, to_agent, message_preview}