Skip to content

Event streams

Subscribe to the global server event bus (all servers). Requires AppAdmin and Authorization: Bearer ....

You can use WebSocket (GET /api/events/ws) or Server-Sent Events (GET /api/events); both receive the same logical events. S4J exposes the WebSocket feed via getEventStream() only.

Event topics (global bus)

Protocube’s global stream is fed from PublishEvent on each server. Every message uses the wire shape {"Topic":"<name>","Data":{...}} (SSE) or the same object as each WebSocket JSON frame.

Data is always a wrapper with server_id (the affected server) and payload (type depends on the topic). S4J maps these three topics to StatusUpdateEvent, ServerCrashEvent, and ServerDeletedEvent.

Topic (event: name for SSE)When it is emittedpayload
statusServer power/process state changes (SetStatus), including updates from the node (e.g. install finished → offline).A string status such as offline, starting, running, stopping (see server/power.go).
crashThe node reports a process crash (HandleServerCrash).JSON object: reason (string), exit_code (number), timestamp (RFC3339 time).
deletedThe server record is torn down (CleanupForDestroy).null (no extra payload).

Example (status on WebSocket / in SSE data:):

json
{
  "Topic": "status",
  "Data": {
    "server_id": "srv_01HZ...",
    "payload": "running"
  }
}

Example (crash):

json
{
  "Topic": "crash",
  "Data": {
    "server_id": "srv_01HZ...",
    "payload": {
      "reason": "signal: killed",
      "exit_code": 137,
      "timestamp": "2026-04-03T12:00:00Z"
    }
  }
}

If a topic ever includes a : suffix internally, the bus normalizes the listener name to the segment before the first : (events.Publish); the topics above are what Protocube emits today.


GET /api/events/ws — Global event stream (WebSocket)

Same events as SSE, over a WebSocket upgrade.

Handshake — standard WebSocket upgrade with Authorization: Bearer ... (or as your reverse proxy forwards it).

Example

http
GET /api/events/ws HTTP/1.1
Host: protocube.example.com
Authorization: Bearer sls_live_...
Upgrade: websocket
Connection: Upgrade
java
import com.protoxon.S4J.client.entities.ServerEvent;
import com.protoxon.S4J.client.entities.WebSocketEventStream;

WebSocketEventStream stream = client.getEventStream()
    .onServerEvent((ServerEvent ev) -> {
      // handle parsed server-related events
    })
    .onError(Throwable::printStackTrace);

stream.start();
// when done: stream.stop();

Messages — each application message is {"Topic":"...","Data":{...}} as in Event topics above.

The server also sends WebSocket ping frames periodically to keep the connection alive.

Close the socket to unsubscribe.


GET /api/events — Global event stream (SSE)

Long-lived response; skips the default HTTP timeout. Server-Sent Events.

Headers — clients often send:

http
GET /api/events HTTP/1.1
Authorization: Bearer sls_live_...
Accept: text/event-stream
java
// S4J does not expose GET /api/events (SSE) on SLSClient.
// For Java, use client.getEventStream() in the WebSocket section — same global event bus.

Response200 OK, headers include:

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

Each event looks like:

text
event: <topic>
data: {"Topic":"<topic>","Data":...}

The data line is JSON (field names are Topic and Data as emitted by the server). Topic matches the SSE event: name. Data is the payload (object, string, etc.).

Example (illustrative — same JSON as WebSocket, line-oriented for SSE):

text
event: status
data: {"Topic":"status","Data":{"server_id":"srv_01HZ...","payload":"running"}}

Close the HTTP connection to unsubscribe.