Stream the operation event log via Server-Sent Events
Always returns text/event-stream (SSE) on success. The body
is a sequence of three kinds of lines (per RFC W3C SSE), each
terminated by \n\n:
Frame shapes
Normal event frame — one OperationEvent JSON object in
data:, dispatchable via event::
id: <integer event.id>
event: <OperationEventType, e.g. stdout|stderr|spawn|exit>
data: {"id": N, "ts": "...", "spid": ..., "type": "...", "data": {...}}
event: always matches data.type. See OperationEvent and
OperationEventType for the per-type payload shape. Native
EventSource dispatches each frame to the matching
addEventListener("<type>", ...) handler.
Server-side error frame — surfaces handler exceptions to the connected client without tearing the TCP connection down mid-stream. Sent right before the server closes the response:
: stream ended with error, retry since last event id
event: sse_error
data: <one-line exception message>
The leading SSE comment line lets pure-EventSource clients see
the intent (“retry from Last-Event-Id”); the sse_error frame
carries the error text for logging. Clients should treat this
as a non-clean close and reconnect with the standard SSE
Last-Event-Id semantics (see Resuming).
Keepalive comment — periodic : keepalive\n\n lines
emitted while the stream is idle. They keep upstream
proxy_read_timeout / TCP idle timers fresh and have no
application meaning. Spec-compliant; EventSource and any SSE
parser must ignore comment lines (those beginning with :).
follow semantics
The follow parameter controls only whether the stream stays
open after the last currently-known event:
follow=0(default) — the server emits everything currently available and closes the connection.follow=1— same start; if the operation is still running the server keeps the connection open and forwards new events as they appear. For terminal operationsfollow=1is a no-op: there’s nothing more to subscribe to, so the connection closes after the last event just likefollow=0.
Optional filters:
?spid=N— only events whosespid(Spawned Process ID, the routing identity inOperationEvent) matches.?since=N— only events withid > N.
follow=1 requires SPAWN or SPAWN_DISPOSABLE on top of
the baseline LIST — a long-lived subscription reserves
per-operation server state. follow=0 is read-only and
stays under LIST.
Resuming after a drop
Every normal frame carries id: — the canonical event id.
On reconnect send the last successfully received id in the
standard Last-Event-Id request header (or ?since=N on
manual GETs); the server resumes from that point.
Error handling
| Status | Meaning | Client action |
|---|---|---|
| 200 | Stream open | Read frames; reconnect with Last-Event-Id if the stream closes before reaching a terminal event |
| 400 | Malformed query/header (non-integer param) | Fix request |
| 401 | Missing/invalid auth | Refresh credentials |
| 403 | Auth lacks LIST (or SPAWN for follow=1) | Use a token with the right scope |
| 404 | Operation not in this namespace | Wrong UUID |
| 410 | Stream is over but the terminal artifact isn’t ready yet | Retry after Retry-After |
| 425 | Not yet ready (operation is still being prepared) | Retry after Retry-After |
| 502 | Upstream returned an error opening the stream | Retry; if persistent, escalate |
| 504 | Upstream took too long to respond | Retry |
A 200 followed by an event: sse_error frame and immediate
close is the in-band equivalent of “the stream broke after we
already committed to a 200” — handle it the same way as 410:
wait briefly, reconnect with Last-Event-Id.
See OperationEvent for the per-event shape.
Authorizations
IAM bearer token issued by the Nebius IAM service. Sent as
Authorization: Bearer <iam-token>. Must be combined with the
Project header (see IAMProjectHeader).
This is the recommended authentication scheme for new clients.
Nebius project ID associated with the IAM token. Required together
with IAMBearerAuth. Identifies the project context the request is
scoped to.
Headers
Standard SSE resume header sent automatically by
EventSource on reconnect. Treated as ?since=N;
takes precedence over the query param.
x >= 0Path Parameters
The ID of the operation A UUID string
"12345678-9abc-baba-deda-0123456789ab"
Query Parameters
HTTP-flag boolean. Present without a value (?follow)
and ?follow=1 both enable; ?follow=0 and absence
disable. When enabled, the SSE stream stays open after
the currently-known events have been sent — for a
running operation new events are forwarded as they
appear; for a terminal operation it has no effect.
, 0, 1 Only emit events whose spid field matches. Filter is
applied server-side regardless of whether the operation is
still running or already terminal.
x >= 0Only emit events with id > since (event IDs are
monotonically increasing). Overridden by the
Last-Event-Id header when present.
x >= 0Response
OK — text/event-stream body. Normal events,
: keepalive comments, and a terminal event: sse_error
frame may all appear; see endpoint description. With
follow=0 (or any terminal operation) the response ends
after the last available event; with follow=1 on a
still-running operation the connection stays open until the
client disconnects or the operation reaches a terminal
state.
SSE response body for GET /operations/{operationId}/events.
Wire format: a sequence of \n\n-separated frames; each frame
is an OperationEventSSEFrame.
OpenAPI doesn't have first-class SSE support, so this content
is typed as binary at the protocol level — but the per-frame
contract is the linked schema. Clients should parse frame by
frame and either dispatch on the event: line (e.g. via
native EventSource) or JSON-decode the data: payload.