Platform

Preview — pending review

This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.

Server-Sent Events stream of realtime resource updates

GET
/events

Opens a long-lived Server-Sent Events (text/event-stream) connection scoped to the caller's session. On connect the server first writes the comment line ': connected' (and flushes) so clients can detect liveness, then pushes one frame per resource change as 'data: \n\n' where is a RealtimeEvent envelope: { "type": "resource.updated", "kind": "", "id": "", "patch": { ...changed fields } }. The client looks up the cached entity by (kind, id) and shallow-merges patch over it — patch carries only the fields that changed (e.g. { "status": "RUNNING" }), never the full resource. Comment keep-alive lines (': ping') are sent roughly every 25s so proxies do not idle-close the connection; clients must ignore comment lines and reconnect with backoff when the stream drops. Validation: the session cookie or bearer token must be valid (else 401 ErrUnauthenticated before any frame is written); the Accept header should include text/event-stream. Only events for tenants the caller can read are ever emitted. Async & state: Synchronous read; no state change. This endpoint emits frames but never creates them — operations and resource mutations elsewhere produce the resource.updated frames delivered here. Errors: 401 invalid/expired session (delivered as a JSON ApiError before the stream upgrades); 429 when the per-session concurrent-stream limit is exceeded; 500 internal. Mid-stream failures simply close the connection — clients reconnect. Lifetime & re-authorization: the server re-checks the session and the caller's grants about every 30 s and before delivering an iam.assignment.changed frame; a logged-out session or a caller left with no access gets the stream closed, a removed project's frames stop at once. Every stream also ends cleanly after about 10 minutes (the edge hard-caps it at 15 minutes); clients reconnect with Last-Event-ID and lose nothing. Idempotency/Concurrency: Safe, cacheable; no idempotency key required (read-only stream; responses must not be buffered or cached by intermediaries — Cache-Control no-cache is set). Frames are at-least-once; merging the same patch twice is harmless.

Authorization

bearerToken
headerAuthorizationBearer <token>

An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.

Response Body

SSE stream. The first bytes are the comment ': connected'; thereafter each event is a 'data: ' line followed by a blank line, where is one RealtimeEvent. Periodic ': ping' comment lines keep the connection alive. The schema below describes the JSON payload of each data frame, not the raw byte stream.

text/event-stream
  1. response

Frame pushed on the /events SSE stream (realtime contract v2). The client merges patch (shallow) into the cached entity identified by (kind, id). v2 adds scopeId: the project (scope) the event belongs to. The server only delivers a frame to a subscriber authorized for that scope; scopeId null marks a tenant-level (project-less) event that every tenant-reachable subscriber still receives.

type*"resource.updated"
Value in"resource.updated"
kind*string

Entity kind, e.g. 'instance' | 'volume' | 'loadBalancer' | 'operation'.

id*string

Identifier of the updated resource.

scopeId?|

Project (scope) the event belongs to. The realtime channel filters frames by the subscriber's accessible scope set, so a reader in one resource group never receives another project's frames. null for tenant-level events (no project), which are broadcast to every tenant-reachable subscriber for backward compatibility.

patch*

Only the changed fields; shallow-merged over the cached entity.

curl -X GET "https://example.com/events"
{  "type": "resource.updated",  "kind": "string",  "id": "string",  "scopeId": "string",  "patch": {}}