OpenReels
API Reference

SSE Events

Server-Sent Events reference for real-time pipeline progress monitoring.

The SSE endpoint GET /api/v1/jobs/:id/events streams real-time progress events as a job moves through the pipeline. The connection uses standard Server-Sent Events format.

Connection Lifecycle

  1. Client opens the SSE stream
  2. Server sends job:snapshot with the current job state (supports reconnection)
  3. If the job is already finished, server sends job:completed or job:failed and closes
  4. Otherwise, server streams stage events as the pipeline executes
  5. On terminal event (job:completed or job:failed), the connection closes
  6. If the client disconnects, server cleans up event listeners

Event Format

Events follow the standard SSE format:

event: <event-type>
data: <json-payload>

Each event has a named type prefixed by its category (job:, stage:).


Job Events

job:snapshot

Sent immediately on connection. Contains the full job metadata as stored in meta.json. This allows clients to reconstruct the current state on reconnection.

event: job:snapshot
data: {"id":"1","topic":"Black holes","status":"running","stages":{"research":{"status":"done","detail":"5 key facts","durationSec":4.2},"director":{"status":"running"},"tts":{"status":"pending"},"visuals":{"status":"pending"},"assembly":{"status":"pending"},"critic":{"status":"pending"}}}

The snapshot contains all accumulated data: researchData, score, costEstimate, musicTrack, and criticReview fields are included once their respective stages complete.

job:completed

Sent when the job finishes successfully. The connection closes after this event.

event: job:completed
data: {}

job:failed

Sent when the job fails. Includes the error message. The connection closes after this event.

event: job:failed
data: {"error":"ANTHROPIC_API_KEY is required"}

Stage Events

Stage events are emitted as the pipeline progresses through its six stages: research, director, tts, visuals, assembly, critic. The event type follows the pattern stage:<stage-name>.

Stage Start

Emitted when a stage begins execution.

event: stage:research
data: {"stage":"research","type":"start"}

Stage Complete

Emitted when a stage finishes successfully. Includes a human-readable detail and duration.

event: stage:research
data: {"stage":"research","type":"complete","detail":"5 key facts","durationSec":4.2}

Stage Skipped

Emitted when a stage is skipped (e.g., critic in dry-run mode).

event: stage:critic
data: {"stage":"critic","type":"skipped","reason":"Dry run mode"}

Stage Error

Emitted when a stage encounters an error. The job may still continue or fail depending on the error.

event: stage:visuals
data: {"stage":"visuals","type":"error","error":"Rate limit exceeded"}

Progress Events

Rich progress events are emitted during stages to provide granular updates. They all use the stage:<stage-name> event type with varying type fields in the data payload.

Research Results

Emitted after the research stage gathers data.

event: stage:research
data: {"stage":"research","type":"results","summary":"...","key_facts":["..."],"mood":"epic_cinematic"}

DirectorScore

Emitted after the director stage produces the video plan.

event: stage:director
data: {"stage":"director","type":"score","score":{"emotional_arc":"...","archetype":"...","music_mood":"epic_cinematic","scenes":[...]}}

Cost Estimate

Emitted after the director stage calculates the estimated cost.

event: stage:director
data: {"stage":"director","type":"cost_estimate","estimate":{"totalCost":0.12,"breakdown":{...}}}

Music Selection

Emitted when a bundled music track is selected.

event: stage:visuals
data: {"stage":"visuals","type":"music","track":"epic-cinematic-01","mood":"epic_cinematic","requestedMood":"epic_cinematic","fallback":false}

Music Resolved

Emitted when music is resolved (generated or selected from bundled library).

event: stage:visuals
data: {"stage":"visuals","type":"music_resolved","provider":"bundled","prompt":"...","metadata":{},"fallback":false}

Music Generated

Emitted when music is generated by an AI provider (e.g., Lyria).

event: stage:visuals
data: {"stage":"visuals","type":"music_generated","provider":"lyria","prompt":"Cinematic orchestral score...","durationSeconds":45}

Asset Generated

Emitted as individual visual assets (images, videos, stock clips) are produced during the visuals stage.

event: stage:visuals
data: {"stage":"visuals","type":"asset","sceneIndex":0,"visualType":"ai_image","path":"scene-001.png"}

Critic Review

Emitted after the critic evaluates the final video.

event: stage:critic
data: {"stage":"critic","type":"review","score":8.5,"strengths":["Engaging narrative arc","Strong visual variety"],"weaknesses":["Scene 3 transition could be smoother"]}

Client Example

JavaScript (EventSource)

const eventSource = new EventSource('/api/v1/jobs/1/events');

eventSource.addEventListener('job:snapshot', (e) => {
  const meta = JSON.parse(e.data);
  console.log('Current state:', meta.status);
});

eventSource.addEventListener('stage:research', (e) => {
  const data = JSON.parse(e.data);
  if (data.type === 'complete') {
    console.log(`Research done in ${data.durationSec}s`);
  }
});

eventSource.addEventListener('job:completed', () => {
  console.log('Job finished!');
  eventSource.close();
});

eventSource.addEventListener('job:failed', (e) => {
  const { error } = JSON.parse(e.data);
  console.error('Job failed:', error);
  eventSource.close();
});

React Hook

The OpenReels web UI uses a useSSE hook pattern. See web/src/hooks/useSSE.ts for the implementation.


Reconnection

SSE connections can drop due to network issues. On reconnection:

  1. Open a new EventSource to the same endpoint
  2. The server sends a fresh job:snapshot with all accumulated state
  3. Stage events resume from the current point in the pipeline

The snapshot includes all rich data (researchData, score, musicTrack, criticReview) so the client can fully reconstruct the UI without replaying events.