Backbone LabDocs
Concepts

Streaming

Orders take seconds to minutes; you should not poll for them in a tight loop. The API pushes lifecycle events two ways: Server-Sent Events on plain HTTP, and a multiplexed WebSocket that the SDKs manage for you.

Server-Sent Events

Three streams, all authenticated with the usual header:

StreamScopeLifetime
GET /v1/orders/:id/eventsOne order: snapshot, progress, terminal state.Closes itself on completed or failed.
GET /v1/batches/:id/eventsOne shoot: per-order completions plus aggregate counts.Closes when every scene has settled.
GET /v1/eventsThe account: everything on your key, including intermediate frames.Infinite — reconnect on drop.

Every stream opens with a snapshot of the current state before the deltas, and sends a ping every 15 seconds to keep intermediaries from closing the connection. Reconnecting is always safe: the fresh snapshot reconciles whatever happened while you were away, so a dropped connection never loses a terminal state.

WebSocket — via the SDKs

The SDKs use a WebSocket instead of SSE, and hide its lifecycle entirely (ticket authentication, reconnection with backoff, snapshot reconciliation). The design rule: one connection per client. order.wait(), batch.wait() and watch() all filter the same multiplexed socket — following fifty orders costs one connection, not fifty.

for await (const ev of bkbn.watch()) {
  if (ev.type === 'order') {
    console.log(ev.data.orderUuid, ev.data.status, ev.data.progressPercent)
  }
}

When a WebSocket cannot connect at all (proxies that strip the Upgrade header), wait() falls back to polling by itself. Mid-stream drops reconnect with backoff, and each reconnection re-delivers a snapshot first.

Event shape

Order events carry the order summary — orderUuid, status (queued, running, completed, failed), progressPercent, progressStage, and outputAssetId once completed. Unknown event types may be added over time; ignore what you don't recognize. The SDKs do this for you with explicit UNKNOWN sentinels.