SSE streaming

Motioness emits a typed event stream for every asset. Subscribe with EventSource to drive progress UI, tail logs, or wire up CI builds.

Three SSE endpoints

EndpointAuthUse
GET /v1/{projectKey}/events/{assetId}Public (project key)Browser / CLI / build script
GET /api/assets/{id}/eventsSession cookieDashboard, per-asset detail
GET /api/projects/{id}/activitySession cookieDashboard, project-wide activity feed

Subscribe

ts
const es = new EventSource( `https://motioness.com/v1/${PK}/events/${ASSET_ID}`,);es.addEventListener('stage_completed', (e) => { const data = JSON.parse(e.data); console.log(`stage ${data.stage} done in ${data.latency_ms}ms`);});es.addEventListener('ready', () => { console.log('mp4 hot'); es.close();});es.addEventListener('failed', (e) => { console.error(JSON.parse(e.data)); es.close();});

EventSource automatically reconnects and resumes from Last-Event-ID.

Event types

The closed enum mirrors the asset lifecycle:

text
queuedvision_started, vision_completed, vision_failedstage_started, stage_completed, stage_failedretry_scheduledr2_write_completedwebhook_dispatched, webhook_delivered, webhook_failed, webhook_dead_letterreadyfailedcancelled

Each event includes ts, attempt, stage (when applicable), latency_ms (on *_completed), error_code + error_msg (on *_failed), request_id.

Reconnect with Last-Event-ID

The server emits id: <ms> on every event. On reconnect, browsers automatically include Last-Event-ID: <last-ms>; the server replays events newer than the cursor.

For non-browser clients you have to set the header yourself:

ts
const headers = lastSeenId ? { 'Last-Event-ID': String(lastSeenId) } : {};const res = await fetch(url, { headers });

Connection cap

Server caps connections at 5 minutes. Most generations finish in under 60 seconds, so the cap is a safety net. Reconnect with the cursor to continue.

Heartbeats

Server sends : ping (SSE comment) every 15 seconds to keep proxies alive. Standard EventSource ignores them silently.

Auth-gated streams

For dashboard use, send the session cookie:

bash
curl -N -b "better-auth.session_token=…" \ "https://motioness.com/api/projects/$PROJECT_ID/activity"

The auth-gated streams emit the same event shape across all assets in the project — useful for activity feeds.

Webhooks vs SSE

WebhooksSSE
UseServer-side, fire-and-forgetBrowser, real-time UI
PersistenceDurable retries (5 attempts)Best-effort
AuthOutbound (your endpoint receives)Inbound (you connect)
Latency~100ms after event~10ms after event

For dashboards, prefer SSE. For server-side reactions (re-encoding, indexing, etc.), prefer webhooks — they survive your service being briefly down.

Ask a question... ⌘I