Skip to content
SHC Docs

SSE streaming API

Server-Sent Events (text/event-stream) for real-time event and operation progress streaming.

Scope note. There is no SSEBroker subsystem and no sse.* config section in the Go daemon — those were Python-era. Streaming is implemented directly in the module routers below. This page documents the routes that actually emit text/event-stream, verified against the chi routers.

MethodPathEmitsModule / source
GET/api/method/shc.events.streamevent stream (docker/audit/error)events
GET/api/method/shc.events.errors.streamerror events onlyevents
GET/api/method/shc.operation.stream/{operation_id}operation progressbackup (+ operation)
GET/api/method/shc.operation.state/{operation_id}one-shot operation state (JSON, not SSE)backup
GET/api/method/shc.mount.subscribe/{session_id}mount-session events (pins the session)backup/mount
GET/api/method/shc.stack.logs.streamchunked log streamlogs
GET/api/method/shc.storage.logs.streamchunked storage-op log streamstorage
POST/internal/eventscross-node event ingest (peer → local bus)events

All SSE responses set:

  • Content-Type: text/event-stream
  • Cache-Control: no-cache
  • Connection: keep-alive
  • X-Accel-Buffering: no

Each frame is:

id: <sequence>
event: <event_type>
data: <json>

id: is emitted only when the sequence is known (locally published events). A heartbeat frame is sent every 30 seconds during idle periods:

event: heartbeat
data: {"ts": "2026-01-24T12:00:00.123456Z"}

Event stream — GET /api/method/shc.events.stream

Section titled “Event stream — GET /api/method/shc.events.stream”

Streams system-wide events. Auth: events:read (tenant-scoped); a non-member is rejected with 403 before any SSE headers are written. The local UDS caller is implicitly all-tenants.

Query parameters

ParameterDescription
typeComma-separated event types to include: docker, audit, error, event. Omit for all.
stack_nameFilter to one stack.
node_idFilter to events originating on one node.
all_tenants1 = all tenants (platform admin only).

Event type classification (from the event code prefix): D…docker, A…audit, E…error; audit/error flags override; anything else → event. Each data payload is the event’s ToDict() envelope plus an event_type key.

GET /api/method/shc.events.errors.stream is the same stream restricted to error events.

Operation progress — GET /api/method/shc.operation.stream/{operation_id}

Section titled “Operation progress — GET /api/method/shc.operation.stream/{operation_id}”

Async operations (shc.backup.create_async, restore_async, recover_async, stack start/stop/restart, install/update, …) return an operation_id in their response body. Subscribe to this route to receive progress frames. Event types seen on this channel include step (progress update), complete, and error; the stream closes after a complete or error frame.

The backup-module handler serves the canonical URL; it tries the async operations store first, then falls back to the operation module’s registry, so operations registered by either land on the same URL.

GET /api/method/shc.operation.state/{operation_id} returns a one-shot JSON snapshot of operation state (used by the CLI to check whether an operation still exists before following it).

  1. The client tracks the last id: received.
  2. On reconnect it sends Last-Event-Id: <seq> (or ?last_event_id=<seq> for clients that can’t set headers, e.g. browser EventSource).
  3. The server replays events after that sequence from events_log (up to a 1000-event window) before resuming the live stream. Beyond the window the client resyncs by re-querying current state.

Cross-node ingest — POST /internal/events

Section titled “Cross-node ingest — POST /internal/events”

Peer nodes forward events to each other over the internal listener. The body is one event in ToDict() shape; code is required and X-SHC-Source-Node must be present. Events whose source equals the receiving node are dropped (204, loop prevention). Received events are persisted locally and delivered to local subscribers but are not re-broadcast (prevents storms).

StatusMeaning
200Delivered + persisted locally.
204Self-broadcast dropped.
400Missing X-SHC-Source-Node / decode error / missing code.
500 (X500007EVTBUS)Event bus not running.