Streaming
Stream live job progress and the final result over Server-Sent Events.
GET /v1/jobs/{id}/stream
Opens a text/event-stream SSE connection for one job. The stream replays
prior events, then tails live until terminal (completed or failed), then
closes.
curl -N https://api.orakle.xyz/v1/jobs/<job_id>/stream \
-H "X-Orakle-API-Key: $ORAKLE_API_KEY"-N disables curl buffering. Unknown or unowned jobs return 404 job_not_found.
Wire format
Standard SSE frames: event:, id: (monotonic integer), data: JSON, blank
line.
event: stage
id: 3
data: {"event_type":"stage","job_id":"b7c1...","stage":"planning","message":"Planning strategy...","timestamp":"2026-05-15T12:00:03Z"}
See Events for every event type and payload.
Replay with Last-Event-Id
Send Last-Event-Id with the last id you processed. The server replays
only higher sequences then continues live — so a dropped connection resumes
without gaps or duplicates.
curl -N https://api.orakle.xyz/v1/jobs/<job_id>/stream \
-H "X-Orakle-API-Key: $ORAKLE_API_KEY" \
-H "Last-Event-Id: 3"Keepalive
When idle, the server emits SSE comments to hold the connection open. Skip
lines starting with :.
: keepalive
Consuming in Node
const res = await fetch(
`https://api.orakle.xyz/v1/jobs/${jobId}/stream`,
{ headers: { "X-Orakle-API-Key": process.env.ORAKLE_API_KEY! } },
);
const reader = res.body!.getReader();
const decoder = new TextDecoder();
let buf = "";
for (;;) {
const { value, done } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
let i: number;
while ((i = buf.indexOf("\n\n")) !== -1) {
const frame = buf.slice(0, i);
buf = buf.slice(i + 2);
if (frame.startsWith(":")) continue; // keepalive
const lines = frame.split("\n");
const event = lines.find((l) => l.startsWith("event: "))?.slice(7);
const data = lines.find((l) => l.startsWith("data: "))?.slice(6);
if (data) handle(event, JSON.parse(data));
}
}Prefer the SDK
The SDKs handle streaming, reconnection, and
Last-Event-Id replay, resolving a single typed result. Hand-roll SSE only
for raw progress events or non-JS/Python clients.