> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beta.b3os.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Get a video's timeline

Returns the compiled timeline of a video that has finished planning: beats, narration with word timings, the timed action list the recorder replayed, cursor path, camera keyframes, captions and style (`timeline.schema.json`). `frames=1` adds the per-frame compositor state (large; for debugging). 

` GET /v1/render/videos/{video_id}/timeline `

Get a video's timeline

Returns the compiled timeline of a video that has finished planning: beats, narration with word timings,
the timed action list the recorder replayed, cursor path, camera keyframes, captions and style
(`timeline.schema.json`). `frames=1` adds the per-frame compositor state (large; for debugging).


## Servers

- ` https://beta-api.b3os.org ` — API (API keys and CLI tokens)

- ` https://beta.b3os.org ` — Dashboard (session cookie and CSRF header; same paths)

## Authentication

The operation accepts these alternatives. Schemes within one alternative are required together.

### Alternative 1

- ` apiKey `: ` http `

  - HTTP scheme: ` bearer ` (b3os_sk_ API key or b3os_pat_ token)

  - `Authorization: Bearer <credential>`. Two credential kinds are accepted:

- **API keys** `b3os_sk_<32 base32>_<crc32>`, created in the dashboard or with `POST /v1/keys`. A key belongs to
  one project, has scopes, an optional spend cap and expiry, and is shown only once.
- **CLI tokens** `b3os_pat_<32 base32>_<crc32>`, issued by the device login (`b3os login`). They act for one
  user in the organization and project chosen at approval.

Keys are stored as SHA-256 hashes. The edge exchanges them for a 60-second node token before forwarding
a request to a node, so nodes never see your key.


### Alternative 2

- ` session `: ` apiKey `

  - Credential: ` __Host-b3os_session ` in ` cookie `

  - The dashboard session cookie on `beta.b3os.org` (host-only, `Secure`, `HttpOnly`). Requests other than
`GET`/`HEAD` must also send `x-b3os-csrf: <csrf_token>` from `GET /v1/auth/session`; SameSite is not relied
on. The cookie is never sent to `beta-api.b3os.org` or `usercontent.b3os.org`.


## Parameters

### ` video_id ` (path, required)

The video ID (`vid_…`).

- ` value `: type ` string `

  - pattern: ` "^vid_[0-9a-hjkmnp-tv-z]{26}$" `

Example:

```json
"vid_01m5t4c5ep9bdfhtx7nk2k3vq7"
```

### ` frames ` (query, optional)

Include the per-output-frame state.

- ` value `: type ` boolean `

  - default: ` false `

## Responses

### ` 200 ` — The timeline.

Content type: ` application/json `

- ` value `: type ` object ` — Everything a video job needs after planning: beats, narration with word timings, the timed action list the recorder replays, the cursor path, camera keyframes, captions and style references; plus the per-capture-frame plan sent to the recorder ($defs/capture_frame), the metadata the recorder returns per frame ($defs/captured_frame) and the per-output-frame FrameState the compositor consumes ($defs/frame_state). Times are integer microseconds from t = 0 on the virtual clock (_us); wall-clock budgets are _ms. Positions are CSS pixels in viewport space (origin at the viewport's top-left) unless a field says document space (viewport position plus scroll offset) or output space (pixels of the composed frame). Restyle keeps everything except style and re-composes from the archived capture. Owner after freeze: render-compose.

  - Title: B3OS render timeline, format v1

  - Required fields: ` version `, ` duration_us `, ` viewport `, ` capture `, ` output `, ` actions `

  - ` $schema `: type ` string `; format ` uri `

  - ` version `: type ` unknown `

    - enum: ` [1] `

  - ` job `: type ` string `

    - pattern: ` "^vid_[0-9a-hjkmnp-tv-z]{26}$" `

  - ` duration_us `: type ` integer ` — Length of the video. Output frame i exists for every i with round(i * 1e6 / output.fps) < duration_us.

    - minimum: ` 1 `

    - maximum: ` 600000000 `

  - ` viewport `: type ` object ` — Browser viewport in CSS pixels. Capture runs at device pixel ratio 1; sharp zoom comes from clip.scale at capture time (ARCHITECTURE 5.2).

    - Required fields: ` width `, ` height `

    - ` width `: type ` integer `

      - minimum: ` 320 `

      - maximum: ` 3840 `

    - ` height `: type ` integer `

      - minimum: ` 240 `

      - maximum: ` 2160 `

  - ` capture `: type ` object `

    - Required fields: ` fps `

    - ` fps `: type ` integer ` — Page capture rate. Capture frame seq is taken at virtual time t(seq) = round(seq * 1e6 / fps) us.

      - default: ` 30 `

      - minimum: ` 1 `

      - maximum: ` 60 `

    - ` format `: type ` unknown `

      - enum: ` ["jpeg","png"] `

      - default: ` "jpeg" `

    - ` quality `: type ` integer ` — JPEG quality passed to Chrome.

      - default: ` 90 `

      - minimum: ` 1 `

      - maximum: ` 100 `

    - ` backend `: type ` unknown ` — screenshot: Page.captureScreenshot per virtual tick (any OS). beginframe: HeadlessExperimental.beginFrame with screenshot (Linux chrome-headless-shell; reports damage).

      - enum: ` ["screenshot","beginframe"] `

      - default: ` "screenshot" `

    - ` segments `: type ` integer ` — Number of segments captured in parallel; 1 means serial.

      - default: ` 1 `

      - minimum: ` 1 `

      - maximum: ` 32 `

  - ` output `: type ` object ` — Composed video. Output frame index i is presented at t = round(i * 1e6 / fps) us.

    - Required fields: ` width `, ` height `, ` fps `

    - ` width `: type ` integer `

      - minimum: ` 16 `

      - maximum: ` 3840 `

    - ` height `: type ` integer `

      - minimum: ` 16 `

      - maximum: ` 2160 `

    - ` fps `: type ` unknown `

      - enum: ` [24,25,30,50,60] `

  - ` seed `: type ` integer ` — Seeds Math.random and crypto.getRandomValues in the page and every PRNG in the director, so every segment worker sees the same sequence.

    - minimum: ` 0 `

    - maximum: ` 4294967295 `

  - ` start_time `: type ` string `; format ` date-time ` — Value of Date at t = 0; the page clock then advances with virtual time only.

  - ` source `: type ` object `

    - Required fields: ` url `

    - ` url `: type ` string `; format ` uri `

      - maxLength: ` 4096 `

      - pattern: ` "^https?://" `

    - ` profile `: type ` string `

      - pattern: ` "^prof_[0-9a-hjkmnp-tv-z]{26}$" `

  - ` style `: type ` object ` — References to style presets resolved by b3os-compose. Restyle replaces only this object.

    - ` background `: type ` string ` — A preset id known to b3os-compose (GET /v1/render/presets), e.g. midnight, browser-dark, mac, arrow. Ids are unique across kinds; none (any kind) and auto and transparent (background) are values, not presets.

      - maxLength: ` 64 `

      - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

    - ` frame `: type ` string ` — A preset id known to b3os-compose (GET /v1/render/presets), e.g. midnight, browser-dark, mac, arrow. Ids are unique across kinds; none (any kind) and auto and transparent (background) are values, not presets.

      - maxLength: ` 64 `

      - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

    - ` cursor `: type ` string ` — A preset id known to b3os-compose (GET /v1/render/presets), e.g. midnight, browser-dark, mac, arrow. Ids are unique across kinds; none (any kind) and auto and transparent (background) are values, not presets.

      - maxLength: ` 64 `

      - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

    - ` captions `: type ` string ` — A preset id known to b3os-compose (GET /v1/render/presets), e.g. midnight, browser-dark, mac, arrow. Ids are unique across kinds; none (any kind) and auto and transparent (background) are values, not presets.

      - maxLength: ` 64 `

      - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

    - ` click_effect `: type ` string ` — A preset id known to b3os-compose (GET /v1/render/presets), e.g. midnight, browser-dark, mac, arrow. Ids are unique across kinds; none (any kind) and auto and transparent (background) are values, not presets.

      - maxLength: ` 64 `

      - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

    - ` overrides `: type ` object ` — Style fields that override the presets, validated by b3os-compose against its Style type (NOTES/render-compose.md 1.1): padding, corner_radius, shadow, border, background_color, background_gradient, aspect_ratio, canvas, fit, frame_title, frame_url, theme, cursor_size, cursor_zoom, click_color, click_duration_ms, caption_size, caption_color, caption_highlight, caption_background, caption_position, motion_blur, matte. Unknown keys and bad values are refused with 422 style_invalid.

  - ` layout `: type ` object ` — Where the page layer lands in the output frame, computed by b3os-compose from style and output size and recorded for reproducibility.

    - Required fields: ` page `

    - ` page `: type ` unknown ` — Output space.

      - ` allOf constraint 1 `: type ` object `

        - Required fields: ` x `, ` y `, ` width `, ` height `

        - ` x `: type ` number `

        - ` y `: type ` number `

        - ` width `: type ` number `

          - minimum: ` 0 `

        - ` height `: type ` number `

          - minimum: ` 0 `

    - ` corner_radius `: type ` number `

      - minimum: ` 0 `

  - ` beats `: type ` array ` — Narration-sized units of the story: what is said and what happens while it is said.

    - ` array item `: type ` object `

      - Required fields: ` id `, ` start_us `, ` end_us `

      - ` id `: type ` string `

        - minLength: ` 1 `

        - maxLength: ` 64 `

        - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

      - ` title `: type ` string `

        - maxLength: ` 200 `

      - ` start_us `: type ` integer ` — Microseconds on the virtual timeline.

        - minimum: ` 0 `

        - maximum: ` 600000000 `

      - ` end_us `: type ` integer ` — Microseconds on the virtual timeline.

        - minimum: ` 0 `

        - maximum: ` 600000000 `

      - ` narration `: type ` unknown ` — Narration segment spoken during this beat.

        - ` allOf constraint 1 `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 64 `

          - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

      - ` actions `: type ` array `

        - ` array item `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 64 `

          - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

  - ` narration `: type ` object `; nullable — Voice-over. Audio is synthesized before capture so actions can be placed on words (ARCHITECTURE 5.2). Word times are absolute on the timeline: segment.start_us + the voice sidecar's start_ms * 1000.

    - Required fields: ` voice `, ` sample_rate `, ` segments `

    - ` voice `: type ` object `

      - Required fields: ` model `, ` voice `

      - ` model `: type ` string `

        - maxLength: ` 64 `

        - pattern: ` "^[a-z0-9][a-z0-9._-]*$" `

      - ` voice `: type ` string `

        - maxLength: ` 64 `

        - pattern: ` "^[A-Za-z0-9][A-Za-z0-9._-]*$" `

      - ` speed `: type ` number `

        - default: ` 1 `

        - minimum: ` 0.5 `

        - maximum: ` 2 `

    - ` sample_rate `: type ` unknown `

      - enum: ` [16000,22050,24000,44100,48000] `

    - ` gain_db `: type ` number `

      - default: ` 0 `

      - minimum: ` -30 `

      - maximum: ` 12 `

    - ` segments `: type ` array `

      - ` array item `: type ` object `

        - Required fields: ` id `, ` text `, ` start_us `, ` end_us `, ` audio `, ` words `

        - ` id `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 64 `

          - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

        - ` beat `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 64 `

          - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

        - ` text `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 10000 `

        - ` start_us `: type ` integer ` — Microseconds on the virtual timeline.

          - minimum: ` 0 `

          - maximum: ` 600000000 `

        - ` end_us `: type ` integer ` — Microseconds on the virtual timeline.

          - minimum: ` 0 `

          - maximum: ` 600000000 `

        - ` audio `: type ` object ` — Mono PCM s16le at narration.sample_rate, stored by b3os-render (job-relative path or art_ id).

          - Required fields: ` ref `, ` samples `

          - ` ref `: type ` string `

            - maxLength: ` 256 `

            - pattern: ` "^(art_[0-9a-hjkmnp-tv-z]{26}|audio/[A-Za-z0-9._-]+)$" `

          - ` samples `: type ` integer `

            - minimum: ` 1 `

        - ` words `: type ` array `

          - ` array item `: type ` object `

            - Required fields: ` text `, ` start_us `, ` end_us `

            - ` text `: type ` string `

              - minLength: ` 1 `

              - maxLength: ` 200 `

            - ` start_us `: type ` integer ` — Microseconds on the virtual timeline.

              - minimum: ` 0 `

              - maximum: ` 600000000 `

            - ` end_us `: type ` integer ` — Microseconds on the virtual timeline.

              - minimum: ` 0 `

              - maximum: ` 600000000 `

            - ` byte_start `: type ` integer ` — UTF-8 byte offset of the word in its segment text.

              - minimum: ` 0 `

            - ` byte_end `: type ` integer `

              - minimum: ` 0 `

  - ` actions `: type ` array ` — Timed browser actions in at_us order (ties keep array order). The recorder replays exactly this list in the probe pass and in every capture segment. The virtual clock is frozen while navigate and wait actions settle, so their wall time never shows in the video.

    - ` array item `: type ` object `

      - Required fields: ` id `, ` kind `, ` at_us `

      - ` id `: type ` string `

        - minLength: ` 1 `

        - maxLength: ` 64 `

        - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

      - ` kind `: type ` unknown `

        - enum: ` ["navigate","click","hover","type","key","scroll","select","wait"] `

      - ` at_us `: type ` unknown ` — When the action starts.

        - ` allOf constraint 1 `: type ` integer ` — Microseconds on the virtual timeline.

          - minimum: ` 0 `

          - maximum: ` 600000000 `

      - ` beat `: type ` string `

        - minLength: ` 1 `

        - maxLength: ` 64 `

        - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

      - ` target `: type ` object ` — What an action acts on. Resolution (littledemo targeting): candidates matching selector, text (visible text, case-insensitive substring unless exact), or role plus accessible name, limited to within; the best-scored candidate wins, or the nth match when nth is set. A target that is still outside the viewport after scrolling it into view fails the action with target_not_found.

        - ` selector `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 1024 `

        - ` text `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 500 `

        - ` exact `: type ` boolean `

          - default: ` false `

        - ` role `: type ` string `

          - pattern: ` "^[a-z]{2,32}$" `

        - ` name `: type ` string `

          - maxLength: ` 500 `

        - ` within `: type ` string ` — CSS selector of the scope.

          - maxLength: ` 1024 `

        - ` nth `: type ` integer `

          - minimum: ` 0 `

          - maximum: ` 1000 `

        - ` anyOf alternative 1 `: type ` unknown `

          - Required fields: ` selector `

        - ` anyOf alternative 2 `: type ` unknown `

          - Required fields: ` text `

        - ` anyOf alternative 3 `: type ` unknown `

          - Required fields: ` role `

      - ` url `: type ` string `; format ` uri `

        - maxLength: ` 4096 `

        - pattern: ` "^https?://" `

      - ` wait_until `: type ` unknown `

        - enum: ` ["load","domcontentloaded","networkidle"] `

        - default: ` "load" `

      - ` button `: type ` unknown `

        - enum: ` ["left","right","middle"] `

        - default: ` "left" `

      - ` count `: type ` integer `

        - default: ` 1 `

        - minimum: ` 1 `

        - maximum: ` 3 `

      - ` press_us `: type ` integer ` — click: time between mouse down and mouse up.

        - default: ` 60000 `

        - minimum: ` 0 `

        - maximum: ` 2000000 `

      - ` modifiers `: type ` array `

        - ` array item `: type ` unknown `

          - enum: ` ["Alt","Control","Meta","Shift"] `

      - ` text `: type ` string `

        - maxLength: ` 10000 `

      - ` interval_us `: type ` integer ` — type: delay between characters; character i (a Unicode scalar value) is inserted at at_us + i * interval_us.

        - default: ` 80000 `

        - minimum: ` 0 `

        - maximum: ` 1000000 `

      - ` key `: type ` string ` — KeyboardEvent.key, e.g. Enter, Tab, a.

        - minLength: ` 1 `

        - maxLength: ` 32 `

      - ` to `: type ` unknown ` — scroll: document scroll offset to reach.

        - ` allOf constraint 1 `: type ` object `

          - Required fields: ` x `, ` y `

          - ` x `: type ` number `

          - ` y `: type ` number `

      - ` by `: type ` unknown ` — scroll: delta from the current offset.

        - ` allOf constraint 1 `: type ` object `

          - Required fields: ` x `, ` y `

          - ` x `: type ` number `

          - ` y `: type ` number `

      - ` duration_us `: type ` integer ` — scroll: animation length on the virtual clock.

        - default: ` 600000 `

        - minimum: ` 0 `

        - maximum: ` 10000000 `

      - ` easing `: type ` unknown ` — Easing for the segment that ends at this keyframe; u in [0, 1]. linear: u. ease_in_out_cubic: u < 0.5 ? 4u^3 : 1 - (2 - 2u)^3 / 2. ease_out_quart: 1 - (1 - u)^4. smootherstep: 6u^5 - 15u^4 + 10u^3. hold: 0 until u = 1, then 1. cubic_bezier: CSS cubic-bezier(x1, y1, x2, y2). critically_damped: s(u) / s(1) with s(u) = 1 - (1 + w u) e^(-w u). Default ease_in_out_cubic.

        - ` oneOf alternative 1 `: type ` unknown `

          - enum: ` ["linear","ease_in_out_cubic","ease_out_quart","smootherstep","hold"] `

        - ` oneOf alternative 2 `: type ` object `

          - Required fields: ` cubic_bezier `

          - ` cubic_bezier `: type ` array `

        - ` oneOf alternative 3 `: type ` object `

          - Required fields: ` critically_damped `

          - ` critically_damped `: type ` object `

            - Required fields: ` omega `

            - ` omega `: type ` number `

              - minimum: ` 1 `

              - maximum: ` 100 `

      - ` value `: type ` string ` — select: option value.

        - maxLength: ` 1000 `

      - ` for `: type ` object ` — wait: the condition. The virtual clock is frozen until it holds.

        - ` selector `: type ` string `

          - maxLength: ` 1024 `

        - ` text `: type ` string `

          - maxLength: ` 500 `

        - ` url `: type ` string ` — Substring the page URL must contain.

          - maxLength: ` 4096 `

        - ` network_idle `: type ` unknown `

          - enum: ` [true] `

      - ` timeout_ms `: type ` integer ` — navigate and wait: wall-clock budget for settling.

        - default: ` 10000 `

        - minimum: ` 100 `

        - maximum: ` 120000 `

      - ` observed `: type ` object ` — What the probe pass observed when the action ran; filled by the recorder, read by the director to plan cursor and camera. rect and point are viewport space at at_us.

        - Required fields: ` ok `

        - ` ok `: type ` boolean `

        - ` rect `: type ` object `

          - Required fields: ` x `, ` y `, ` width `, ` height `

          - ` x `: type ` number `

          - ` y `: type ` number `

          - ` width `: type ` number `

            - minimum: ` 0 `

          - ` height `: type ` number `

            - minimum: ` 0 `

        - ` point `: type ` object `

          - Required fields: ` x `, ` y `

          - ` x `: type ` number `

          - ` y `: type ` number `

        - ` selector `: type ` string ` — A unique selector for the resolved element.

          - maxLength: ` 2048 `

        - ` url `: type ` string ` — Page URL after the action.

          - maxLength: ` 4096 `

        - ` scroll `: type ` unknown ` — Document scroll offset after the action.

          - ` allOf constraint 1 `: type ` object `

            - Required fields: ` x `, ` y `

            - ` x `: type ` number `

            - ` y `: type ` number `

        - ` settled_us `: type ` unknown ` — Virtual time at which a navigate or wait finished.

          - ` allOf constraint 1 `: type ` integer ` — Microseconds on the virtual timeline.

            - minimum: ` 0 `

            - maximum: ` 600000000 `

        - ` error `: type ` object `

          - Required fields: ` code `

          - ` code `: type ` string `

            - pattern: ` "^[a-z][a-z0-9_]{0,63}$" `

          - ` detail `: type ` string `

            - maxLength: ` 2000 `

  - ` cursor `: type ` object ` — Composited cursor (not drawn in the page). Position is linear between consecutive points; pressed and visible keep their last value until a point changes them. Before the first point and after the last, the nearest point applies.

    - Required fields: ` points `

    - ` points `: type ` array `

      - ` array item `: type ` object `

        - Required fields: ` t_us `, ` x `, ` y `

        - ` t_us `: type ` integer ` — Microseconds on the virtual timeline.

          - minimum: ` 0 `

          - maximum: ` 600000000 `

        - ` x `: type ` number `

        - ` y `: type ` number `

        - ` pressed `: type ` boolean `

        - ` visible `: type ` boolean `

  - ` camera `: type ` object ` — Camera keyframes. For t between keyframes k-1 and k: u = (t - t[k-1]) / (t[k] - t[k-1]), e = easing[k](u), zoom = zoom[k-1] * (zoom[k] / zoom[k-1])^e, center = center[k-1] + (center[k] - center[k-1]) * e. Before the first keyframe and after the last, the nearest keyframe holds. The camera rect is width = viewport.width / zoom, height = viewport.height / zoom, x = clamp(center.x - width / 2, 0, viewport.width - width), y likewise. Absent: zoom 1 centered.

    - Required fields: ` keyframes `

    - ` keyframes `: type ` array `

      - ` array item `: type ` object `

        - Required fields: ` t_us `, ` center `, ` zoom `

        - ` t_us `: type ` integer ` — Microseconds on the virtual timeline.

          - minimum: ` 0 `

          - maximum: ` 600000000 `

        - ` center `: type ` object `

          - Required fields: ` x `, ` y `

          - ` x `: type ` number `

          - ` y `: type ` number `

        - ` zoom `: type ` number `

          - minimum: ` 1 `

          - maximum: ` 8 `

        - ` easing `: type ` unknown ` — Easing for the segment that ends at this keyframe; u in [0, 1]. linear: u. ease_in_out_cubic: u < 0.5 ? 4u^3 : 1 - (2 - 2u)^3 / 2. ease_out_quart: 1 - (1 - u)^4. smootherstep: 6u^5 - 15u^4 + 10u^3. hold: 0 until u = 1, then 1. cubic_bezier: CSS cubic-bezier(x1, y1, x2, y2). critically_damped: s(u) / s(1) with s(u) = 1 - (1 + w u) e^(-w u). Default ease_in_out_cubic.

          - ` oneOf alternative 1 `: type ` unknown `

            - enum: ` ["linear","ease_in_out_cubic","ease_out_quart","smootherstep","hold"] `

          - ` oneOf alternative 2 `: type ` object `

            - Required fields: ` cubic_bezier `

            - ` cubic_bezier `: type ` array `

          - ` oneOf alternative 3 `: type ` object `

            - Required fields: ` critically_damped `

            - ` critically_damped `: type ` object `

              - Required fields: ` omega `

              - ` omega `: type ` number `

                - minimum: ` 1 `

                - maximum: ` 100 `

  - ` captions `: type ` object `

    - Required fields: ` burn_in `, ` cues `

    - ` burn_in `: type ` unknown ` — none: sidecar files only. static: draw each cue. karaoke: draw each cue and highlight the word being spoken.

      - enum: ` ["none","static","karaoke"] `

    - ` sidecars `: type ` array `

      - ` array item `: type ` unknown `

        - enum: ` ["vtt","srt"] `

    - ` max_chars_per_line `: type ` integer `

      - default: ` 42 `

      - minimum: ` 10 `

      - maximum: ` 80 `

    - ` max_lines `: type ` integer `

      - default: ` 2 `

      - minimum: ` 1 `

      - maximum: ` 3 `

    - ` max_chars_per_second `: type ` number `

      - default: ` 20 `

      - minimum: ` 5 `

      - maximum: ` 40 `

    - ` cues `: type ` array `

      - ` array item `: type ` object ` — One caption cue. words place each word on a line for karaoke highlighting; byte offsets index into that line's text.

        - Required fields: ` id `, ` start_us `, ` end_us `, ` lines `

        - ` id `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 64 `

          - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

        - ` start_us `: type ` integer ` — Microseconds on the virtual timeline.

          - minimum: ` 0 `

          - maximum: ` 600000000 `

        - ` end_us `: type ` integer ` — Microseconds on the virtual timeline.

          - minimum: ` 0 `

          - maximum: ` 600000000 `

        - ` lines `: type ` array `

          - ` array item `: type ` string `

            - minLength: ` 1 `

            - maxLength: ` 120 `

        - ` words `: type ` array `

          - ` array item `: type ` object `

            - Required fields: ` text `, ` start_us `, ` end_us `, ` line `, ` byte_start `, ` byte_end `

            - ` text `: type ` string `

              - minLength: ` 1 `

              - maxLength: ` 200 `

            - ` start_us `: type ` integer ` — Microseconds on the virtual timeline.

              - minimum: ` 0 `

              - maximum: ` 600000000 `

            - ` end_us `: type ` integer ` — Microseconds on the virtual timeline.

              - minimum: ` 0 `

              - maximum: ` 600000000 `

            - ` line `: type ` integer `

              - minimum: ` 0 `

              - maximum: ` 2 `

            - ` byte_start `: type ` integer `

              - minimum: ` 0 `

            - ` byte_end `: type ` integer `

              - minimum: ` 0 `

  - ` capture_plan `: type ` array ` — Per capture frame: the viewport region to capture. Sent to the recorder for each segment. Frames not listed are not captured.

    - ` array item `: type ` object ` — Capture plan entry: at t(seq) capture the viewport region camera (viewport space). The recorder adds the scroll offset to get the document-space clip and sets clip.scale = layout page width (output px) / camera.width so the image arrives at page-layer size.

      - Required fields: ` seq `, ` camera `

      - ` seq `: type ` integer `

        - minimum: ` 0 `

        - maximum: ` 1000000 `

      - ` camera `: type ` object `

        - Required fields: ` x `, ` y `, ` width `, ` height `

        - ` x `: type ` number `

        - ` y `: type ` number `

        - ` width `: type ` number `

          - minimum: ` 0 `

        - ` height `: type ` number `

          - minimum: ` 0 `

      - ` scale `: type ` number ` — Explicit clip.scale; default derived as above.

        - minimum: ` 0 `

        - maximum: ` 16 `

  - ` frames `: type ` array ` — Optional FrameState dump (debugging, tests, GET .../timeline?frames=1).

    - ` array item `: type ` object ` — Everything the compositor needs for output frame index, computed upfront from the timeline so frames compose in parallel. page says which captured image to draw and which viewport region it covers; camera is the region wanted at t_us; the compositor applies the residual transform from page.camera to camera (sub-pixel). Viewport-space positions map to output space through camera and layout.page.

      - Required fields: ` index `, ` t_us `, ` page `, ` camera `, ` cursor `, ` effects `, ` caption `, ` opacity `

      - ` index `: type ` integer `

        - minimum: ` 0 `

      - ` t_us `: type ` integer ` — Microseconds on the virtual timeline.

        - minimum: ` 0 `

        - maximum: ` 600000000 `

      - ` page `: type ` object `

        - Required fields: ` segment `, ` seq `, ` camera `

        - ` segment `: type ` integer `

          - minimum: ` 0 `

          - maximum: ` 31 `

        - ` seq `: type ` integer ` — Latest capture frame with t(seq) <= t_us; when it had damage false, the image of the latest earlier frame with damage.

          - minimum: ` 0 `

        - ` camera `: type ` object `

          - Required fields: ` x `, ` y `, ` width `, ` height `

          - ` x `: type ` number `

          - ` y `: type ` number `

          - ` width `: type ` number `

            - minimum: ` 0 `

          - ` height `: type ` number `

            - minimum: ` 0 `

      - ` camera `: type ` object `

        - Required fields: ` x `, ` y `, ` width `, ` height `

        - ` x `: type ` number `

        - ` y `: type ` number `

        - ` width `: type ` number `

          - minimum: ` 0 `

        - ` height `: type ` number `

          - minimum: ` 0 `

      - ` cursor `: type ` object `

        - Required fields: ` x `, ` y `, ` visible `, ` pressed `

        - ` x `: type ` number `

        - ` y `: type ` number `

        - ` visible `: type ` boolean `

        - ` pressed `: type ` boolean `

      - ` effects `: type ` array `

        - ` array item `: type ` object `

          - Required fields: ` kind `, ` x `, ` y `, ` age_us `

          - ` kind `: type ` unknown `

            - enum: ` ["click"] `

          - ` x `: type ` number `

          - ` y `: type ` number `

          - ` age_us `: type ` integer ` — Time since the effect started; the style decides how long it lasts.

            - minimum: ` 0 `

      - ` caption `: type ` object `; nullable

        - Required fields: ` cue `, ` lines `

        - ` cue `: type ` string `

          - minLength: ` 1 `

          - maxLength: ` 64 `

          - pattern: ` "^[a-z0-9][a-z0-9_-]{0,63}$" `

        - ` lines `: type ` array `

          - ` array item `: type ` string `

        - ` highlight `: type ` object `

          - Required fields: ` line `, ` byte_start `, ` byte_end `

          - ` line `: type ` integer `

            - minimum: ` 0 `

            - maximum: ` 2 `

          - ` byte_start `: type ` integer `

            - minimum: ` 0 `

          - ` byte_end `: type ` integer `

            - minimum: ` 0 `

      - ` opacity `: type ` number ` — Opacity of the window layer (page, frame chrome, shadow, border, cursor, click effects) over the background; the background and the caption stay opaque.

        - minimum: ` 0 `

        - maximum: ` 1 `

      - ` motion `: type ` object ` — Change since the previous output frame, for motion blur: camera center delta and log-zoom delta of the keyframe path (before the viewport clamp, so a camera held at an edge still reports its path), cursor delta (viewport space).

        - ` camera_dx `: type ` number `

        - ` camera_dy `: type ` number `

        - ` camera_dlog_zoom `: type ` number `

        - ` cursor_dx `: type ` number `

        - ` cursor_dy `: type ` number `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "version": 1,
  "job": "vid_01m5t4c5ep9bdfhtx7nk2k3vq7",
  "duration_us": 2000000,
  "viewport": {
    "width": 1440,
    "height": 900
  },
  "capture": {
    "fps": 30
  },
  "output": {
    "width": 1920,
    "height": 1080,
    "fps": 60
  },
  "source": {
    "url": "https://app.example.com"
  },
  "actions": [
    {
      "id": "a1",
      "kind": "click",
      "at_us": 600000,
      "target": {
        "role": "link",
        "name": "Billing"
      }
    }
  ]
}
```

### ` 400 ` — The request failed validation (`invalid_request`, `invalid_url`).

Content type: ` application/problem+json `

- ` value `: type ` object ` — An RFC 9457 problem. `code` is stable and listed in the errors catalog; `type` links to its entry. `detail` is human-readable and may change. Extension members appear only for the codes that document them; ignore members you do not recognize. 

  - Required fields: ` type `, ` title `, ` status `, ` code `, ` detail `

  - ` type `: type ` string `; format ` uri ` — `https://docs.beta.b3os.org/errors#<code>`.

    - example: ` "https://docs.beta.b3os.org/errors#invalid_request" `

  - ` title `: type ` string ` — Short summary of the problem type.

  - ` status `: type ` integer ` — The HTTP status code, repeated for convenience.

    - minimum: ` 400 `

    - maximum: ` 599 `

  - ` code `: type ` string ` — Stable machine-readable error code from the errors catalog.

    - pattern: ` "^[a-z][a-z0-9_]*$" `

  - ` detail `: type ` string ` — Explanation of this occurrence. Never contains secrets.

  - ` instance `: type ` string ` — The request ID (`req_…`) of the request that failed. Include it when you contact support.

    - example: ` "req_01m5t4yg394wegr3j4y01qb363" `

  - ` errors `: type ` array ` — Validation problems, one per field (`invalid_request` and the other codes that list `errors`).

    - ` array item `: type ` object ` — One validation problem.

      - Required fields: ` pointer `, ` detail `

      - ` pointer `: type ` string ` — Where the problem is: a JSON pointer into the request body (`/url`, `/steps/0/uses`), or `#query/<name>`, `#path/<name>` or `#header/<name>` for parameters. 

        - example: ` "/url" `

      - ` detail `: type ` string ` — What is wrong there.

        - example: ` "must be an absolute http or https URL" `

  - ` reason `: type ` string ` — Finer-grained cause for codes that document one (`unauthorized`, `forbidden`, `egress_denied`, `upstream_unreachable`, …).

  - ` required_scope `: type ` string ` — The scope that was missing (`forbidden` with `reason: scope`).

  - ` retry_after_s `: type ` integer ` — Same value as the `Retry-After` header, for clients that only read the body.

    - minimum: ` 0 `

  - ` limit `: type ` object ` — The limit an error refers to. IDs and current values are listed by `GET /v1/limits`.

    - Required fields: ` id `, ` limit `, ` unit `

    - ` id `: type ` string ` — Limit ID, such as `vision.scrape.rpm` or `sandboxes.concurrent`.

      - example: ` "vision.scrape.rpm" `

    - ` limit `: type ` number ` — The limit's value.

    - ` unit `: type ` string ` — What the limit counts, such as `requests`, `sandboxes`, `vcpu` or `MiB`.

    - ` window_s `: type ` integer ` — Window length in seconds for rate limits and quotas.

    - ` current `: type ` number ` — Current usage against the limit, when known.

  - ` current_status `: type ` string ` — The object's current status, for state conflicts such as `sandbox_not_running`.

  - ` upstream_status `: type ` integer ` — The HTTP status the upstream returned (`upstream_error`, `action_output_invalid`).

  - ` step `: type ` string ` — The failed step, as a step ID (routines), an index (`act`) or a path such as `beats/2/do/0` (render).

  - ` pack_error `: type ` object ` — The error a pack's error mapping chose (`upstream_error` from pack actions).

    - Required fields: ` code `, ` message `, ` retryable `

    - ` code `: type ` string `

    - ` message `: type ` string `

    - ` retryable `: type ` boolean `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#invalid_request",
  "title": "Invalid request",
  "status": 400,
  "code": "invalid_request",
  "detail": "1 field failed validation",
  "instance": "req_01m5t4yg394wegr3j4y01qb363",
  "errors": [
    {
      "pointer": "/url",
      "detail": "must be an absolute http or https URL"
    }
  ]
}
```

### ` 401 ` — Missing, malformed, expired or revoked credentials (`unauthorized`).

Content type: ` application/problem+json `

- ` value `: type ` object ` — An RFC 9457 problem. `code` is stable and listed in the errors catalog; `type` links to its entry. `detail` is human-readable and may change. Extension members appear only for the codes that document them; ignore members you do not recognize. 

  - Required fields: ` type `, ` title `, ` status `, ` code `, ` detail `

  - ` type `: type ` string `; format ` uri ` — `https://docs.beta.b3os.org/errors#<code>`.

    - example: ` "https://docs.beta.b3os.org/errors#invalid_request" `

  - ` title `: type ` string ` — Short summary of the problem type.

  - ` status `: type ` integer ` — The HTTP status code, repeated for convenience.

    - minimum: ` 400 `

    - maximum: ` 599 `

  - ` code `: type ` string ` — Stable machine-readable error code from the errors catalog.

    - pattern: ` "^[a-z][a-z0-9_]*$" `

  - ` detail `: type ` string ` — Explanation of this occurrence. Never contains secrets.

  - ` instance `: type ` string ` — The request ID (`req_…`) of the request that failed. Include it when you contact support.

    - example: ` "req_01m5t4yg394wegr3j4y01qb363" `

  - ` errors `: type ` array ` — Validation problems, one per field (`invalid_request` and the other codes that list `errors`).

    - ` array item `: type ` object ` — One validation problem.

      - Required fields: ` pointer `, ` detail `

      - ` pointer `: type ` string ` — Where the problem is: a JSON pointer into the request body (`/url`, `/steps/0/uses`), or `#query/<name>`, `#path/<name>` or `#header/<name>` for parameters. 

        - example: ` "/url" `

      - ` detail `: type ` string ` — What is wrong there.

        - example: ` "must be an absolute http or https URL" `

  - ` reason `: type ` string ` — Finer-grained cause for codes that document one (`unauthorized`, `forbidden`, `egress_denied`, `upstream_unreachable`, …).

  - ` required_scope `: type ` string ` — The scope that was missing (`forbidden` with `reason: scope`).

  - ` retry_after_s `: type ` integer ` — Same value as the `Retry-After` header, for clients that only read the body.

    - minimum: ` 0 `

  - ` limit `: type ` object ` — The limit an error refers to. IDs and current values are listed by `GET /v1/limits`.

    - Required fields: ` id `, ` limit `, ` unit `

    - ` id `: type ` string ` — Limit ID, such as `vision.scrape.rpm` or `sandboxes.concurrent`.

      - example: ` "vision.scrape.rpm" `

    - ` limit `: type ` number ` — The limit's value.

    - ` unit `: type ` string ` — What the limit counts, such as `requests`, `sandboxes`, `vcpu` or `MiB`.

    - ` window_s `: type ` integer ` — Window length in seconds for rate limits and quotas.

    - ` current `: type ` number ` — Current usage against the limit, when known.

  - ` current_status `: type ` string ` — The object's current status, for state conflicts such as `sandbox_not_running`.

  - ` upstream_status `: type ` integer ` — The HTTP status the upstream returned (`upstream_error`, `action_output_invalid`).

  - ` step `: type ` string ` — The failed step, as a step ID (routines), an index (`act`) or a path such as `beats/2/do/0` (render).

  - ` pack_error `: type ` object ` — The error a pack's error mapping chose (`upstream_error` from pack actions).

    - Required fields: ` code `, ` message `, ` retryable `

    - ` code `: type ` string `

    - ` message `: type ` string `

    - ` retryable `: type ` boolean `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#unauthorized",
  "title": "Unauthorized",
  "status": 401,
  "code": "unauthorized",
  "detail": "API key checksum does not match; check that the whole key was copied",
  "instance": "req_01m5t4yg394wegr3j4y01qb363",
  "reason": "malformed"
}
```

### ` 403 ` — Authenticated but not allowed (`forbidden`, `egress_denied`).

Content type: ` application/problem+json `

- ` value `: type ` object ` — An RFC 9457 problem. `code` is stable and listed in the errors catalog; `type` links to its entry. `detail` is human-readable and may change. Extension members appear only for the codes that document them; ignore members you do not recognize. 

  - Required fields: ` type `, ` title `, ` status `, ` code `, ` detail `

  - ` type `: type ` string `; format ` uri ` — `https://docs.beta.b3os.org/errors#<code>`.

    - example: ` "https://docs.beta.b3os.org/errors#invalid_request" `

  - ` title `: type ` string ` — Short summary of the problem type.

  - ` status `: type ` integer ` — The HTTP status code, repeated for convenience.

    - minimum: ` 400 `

    - maximum: ` 599 `

  - ` code `: type ` string ` — Stable machine-readable error code from the errors catalog.

    - pattern: ` "^[a-z][a-z0-9_]*$" `

  - ` detail `: type ` string ` — Explanation of this occurrence. Never contains secrets.

  - ` instance `: type ` string ` — The request ID (`req_…`) of the request that failed. Include it when you contact support.

    - example: ` "req_01m5t4yg394wegr3j4y01qb363" `

  - ` errors `: type ` array ` — Validation problems, one per field (`invalid_request` and the other codes that list `errors`).

    - ` array item `: type ` object ` — One validation problem.

      - Required fields: ` pointer `, ` detail `

      - ` pointer `: type ` string ` — Where the problem is: a JSON pointer into the request body (`/url`, `/steps/0/uses`), or `#query/<name>`, `#path/<name>` or `#header/<name>` for parameters. 

        - example: ` "/url" `

      - ` detail `: type ` string ` — What is wrong there.

        - example: ` "must be an absolute http or https URL" `

  - ` reason `: type ` string ` — Finer-grained cause for codes that document one (`unauthorized`, `forbidden`, `egress_denied`, `upstream_unreachable`, …).

  - ` required_scope `: type ` string ` — The scope that was missing (`forbidden` with `reason: scope`).

  - ` retry_after_s `: type ` integer ` — Same value as the `Retry-After` header, for clients that only read the body.

    - minimum: ` 0 `

  - ` limit `: type ` object ` — The limit an error refers to. IDs and current values are listed by `GET /v1/limits`.

    - Required fields: ` id `, ` limit `, ` unit `

    - ` id `: type ` string ` — Limit ID, such as `vision.scrape.rpm` or `sandboxes.concurrent`.

      - example: ` "vision.scrape.rpm" `

    - ` limit `: type ` number ` — The limit's value.

    - ` unit `: type ` string ` — What the limit counts, such as `requests`, `sandboxes`, `vcpu` or `MiB`.

    - ` window_s `: type ` integer ` — Window length in seconds for rate limits and quotas.

    - ` current `: type ` number ` — Current usage against the limit, when known.

  - ` current_status `: type ` string ` — The object's current status, for state conflicts such as `sandbox_not_running`.

  - ` upstream_status `: type ` integer ` — The HTTP status the upstream returned (`upstream_error`, `action_output_invalid`).

  - ` step `: type ` string ` — The failed step, as a step ID (routines), an index (`act`) or a path such as `beats/2/do/0` (render).

  - ` pack_error `: type ` object ` — The error a pack's error mapping chose (`upstream_error` from pack actions).

    - Required fields: ` code `, ` message `, ` retryable `

    - ` code `: type ` string `

    - ` message `: type ` string `

    - ` retryable `: type ` boolean `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#forbidden",
  "title": "Forbidden",
  "status": 403,
  "code": "forbidden",
  "detail": "This key lacks the scope sandboxes:write",
  "instance": "req_01m5t4yg394wegr3j4y01qb363",
  "reason": "scope",
  "required_scope": "sandboxes:write"
}
```

### ` 404 ` — No such video in this project (`video_not_found`).

Content type: ` application/problem+json `

- ` value `: type ` object ` — An RFC 9457 problem. `code` is stable and listed in the errors catalog; `type` links to its entry. `detail` is human-readable and may change. Extension members appear only for the codes that document them; ignore members you do not recognize. 

  - Required fields: ` type `, ` title `, ` status `, ` code `, ` detail `

  - ` type `: type ` string `; format ` uri ` — `https://docs.beta.b3os.org/errors#<code>`.

    - example: ` "https://docs.beta.b3os.org/errors#invalid_request" `

  - ` title `: type ` string ` — Short summary of the problem type.

  - ` status `: type ` integer ` — The HTTP status code, repeated for convenience.

    - minimum: ` 400 `

    - maximum: ` 599 `

  - ` code `: type ` string ` — Stable machine-readable error code from the errors catalog.

    - pattern: ` "^[a-z][a-z0-9_]*$" `

  - ` detail `: type ` string ` — Explanation of this occurrence. Never contains secrets.

  - ` instance `: type ` string ` — The request ID (`req_…`) of the request that failed. Include it when you contact support.

    - example: ` "req_01m5t4yg394wegr3j4y01qb363" `

  - ` errors `: type ` array ` — Validation problems, one per field (`invalid_request` and the other codes that list `errors`).

    - ` array item `: type ` object ` — One validation problem.

      - Required fields: ` pointer `, ` detail `

      - ` pointer `: type ` string ` — Where the problem is: a JSON pointer into the request body (`/url`, `/steps/0/uses`), or `#query/<name>`, `#path/<name>` or `#header/<name>` for parameters. 

        - example: ` "/url" `

      - ` detail `: type ` string ` — What is wrong there.

        - example: ` "must be an absolute http or https URL" `

  - ` reason `: type ` string ` — Finer-grained cause for codes that document one (`unauthorized`, `forbidden`, `egress_denied`, `upstream_unreachable`, …).

  - ` required_scope `: type ` string ` — The scope that was missing (`forbidden` with `reason: scope`).

  - ` retry_after_s `: type ` integer ` — Same value as the `Retry-After` header, for clients that only read the body.

    - minimum: ` 0 `

  - ` limit `: type ` object ` — The limit an error refers to. IDs and current values are listed by `GET /v1/limits`.

    - Required fields: ` id `, ` limit `, ` unit `

    - ` id `: type ` string ` — Limit ID, such as `vision.scrape.rpm` or `sandboxes.concurrent`.

      - example: ` "vision.scrape.rpm" `

    - ` limit `: type ` number ` — The limit's value.

    - ` unit `: type ` string ` — What the limit counts, such as `requests`, `sandboxes`, `vcpu` or `MiB`.

    - ` window_s `: type ` integer ` — Window length in seconds for rate limits and quotas.

    - ` current `: type ` number ` — Current usage against the limit, when known.

  - ` current_status `: type ` string ` — The object's current status, for state conflicts such as `sandbox_not_running`.

  - ` upstream_status `: type ` integer ` — The HTTP status the upstream returned (`upstream_error`, `action_output_invalid`).

  - ` step `: type ` string ` — The failed step, as a step ID (routines), an index (`act`) or a path such as `beats/2/do/0` (render).

  - ` pack_error `: type ` object ` — The error a pack's error mapping chose (`upstream_error` from pack actions).

    - Required fields: ` code `, ` message `, ` retryable `

    - ` code `: type ` string `

    - ` message `: type ` string `

    - ` retryable `: type ` boolean `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#video_not_found",
  "title": "Video not found",
  "status": 404,
  "code": "video_not_found",
  "detail": "No video vid_01m5t4c5ep9bdfhtx7nk2k3vq7 in this project",
  "instance": "req_01m5t4yg394wegr3j4y01qb363"
}
```

### ` 409 ` — The video has not finished planning yet (`conflict`).

Content type: ` application/problem+json `

- ` value `: type ` object ` — An RFC 9457 problem. `code` is stable and listed in the errors catalog; `type` links to its entry. `detail` is human-readable and may change. Extension members appear only for the codes that document them; ignore members you do not recognize. 

  - Required fields: ` type `, ` title `, ` status `, ` code `, ` detail `

  - ` type `: type ` string `; format ` uri ` — `https://docs.beta.b3os.org/errors#<code>`.

    - example: ` "https://docs.beta.b3os.org/errors#invalid_request" `

  - ` title `: type ` string ` — Short summary of the problem type.

  - ` status `: type ` integer ` — The HTTP status code, repeated for convenience.

    - minimum: ` 400 `

    - maximum: ` 599 `

  - ` code `: type ` string ` — Stable machine-readable error code from the errors catalog.

    - pattern: ` "^[a-z][a-z0-9_]*$" `

  - ` detail `: type ` string ` — Explanation of this occurrence. Never contains secrets.

  - ` instance `: type ` string ` — The request ID (`req_…`) of the request that failed. Include it when you contact support.

    - example: ` "req_01m5t4yg394wegr3j4y01qb363" `

  - ` errors `: type ` array ` — Validation problems, one per field (`invalid_request` and the other codes that list `errors`).

    - ` array item `: type ` object ` — One validation problem.

      - Required fields: ` pointer `, ` detail `

      - ` pointer `: type ` string ` — Where the problem is: a JSON pointer into the request body (`/url`, `/steps/0/uses`), or `#query/<name>`, `#path/<name>` or `#header/<name>` for parameters. 

        - example: ` "/url" `

      - ` detail `: type ` string ` — What is wrong there.

        - example: ` "must be an absolute http or https URL" `

  - ` reason `: type ` string ` — Finer-grained cause for codes that document one (`unauthorized`, `forbidden`, `egress_denied`, `upstream_unreachable`, …).

  - ` required_scope `: type ` string ` — The scope that was missing (`forbidden` with `reason: scope`).

  - ` retry_after_s `: type ` integer ` — Same value as the `Retry-After` header, for clients that only read the body.

    - minimum: ` 0 `

  - ` limit `: type ` object ` — The limit an error refers to. IDs and current values are listed by `GET /v1/limits`.

    - Required fields: ` id `, ` limit `, ` unit `

    - ` id `: type ` string ` — Limit ID, such as `vision.scrape.rpm` or `sandboxes.concurrent`.

      - example: ` "vision.scrape.rpm" `

    - ` limit `: type ` number ` — The limit's value.

    - ` unit `: type ` string ` — What the limit counts, such as `requests`, `sandboxes`, `vcpu` or `MiB`.

    - ` window_s `: type ` integer ` — Window length in seconds for rate limits and quotas.

    - ` current `: type ` number ` — Current usage against the limit, when known.

  - ` current_status `: type ` string ` — The object's current status, for state conflicts such as `sandbox_not_running`.

  - ` upstream_status `: type ` integer ` — The HTTP status the upstream returned (`upstream_error`, `action_output_invalid`).

  - ` step `: type ` string ` — The failed step, as a step ID (routines), an index (`act`) or a path such as `beats/2/do/0` (render).

  - ` pack_error `: type ` object ` — The error a pack's error mapping chose (`upstream_error` from pack actions).

    - Required fields: ` code `, ` message `, ` retryable `

    - ` code `: type ` string `

    - ` message `: type ` string `

    - ` retryable `: type ` boolean `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#conflict",
  "title": "Conflict",
  "status": 409,
  "code": "conflict",
  "detail": "The timeline exists once the video passes the plan phase",
  "instance": "req_01m5t4yg394wegr3j4y01qb363",
  "current_status": "queued"
}
```

### ` 429 ` — A rate, concurrency or quota limit applies (`rate_limited`, `concurrency_limited`, `quota_exceeded`).

Content type: ` application/problem+json `

- ` value `: type ` object ` — An RFC 9457 problem. `code` is stable and listed in the errors catalog; `type` links to its entry. `detail` is human-readable and may change. Extension members appear only for the codes that document them; ignore members you do not recognize. 

  - Required fields: ` type `, ` title `, ` status `, ` code `, ` detail `

  - ` type `: type ` string `; format ` uri ` — `https://docs.beta.b3os.org/errors#<code>`.

    - example: ` "https://docs.beta.b3os.org/errors#invalid_request" `

  - ` title `: type ` string ` — Short summary of the problem type.

  - ` status `: type ` integer ` — The HTTP status code, repeated for convenience.

    - minimum: ` 400 `

    - maximum: ` 599 `

  - ` code `: type ` string ` — Stable machine-readable error code from the errors catalog.

    - pattern: ` "^[a-z][a-z0-9_]*$" `

  - ` detail `: type ` string ` — Explanation of this occurrence. Never contains secrets.

  - ` instance `: type ` string ` — The request ID (`req_…`) of the request that failed. Include it when you contact support.

    - example: ` "req_01m5t4yg394wegr3j4y01qb363" `

  - ` errors `: type ` array ` — Validation problems, one per field (`invalid_request` and the other codes that list `errors`).

    - ` array item `: type ` object ` — One validation problem.

      - Required fields: ` pointer `, ` detail `

      - ` pointer `: type ` string ` — Where the problem is: a JSON pointer into the request body (`/url`, `/steps/0/uses`), or `#query/<name>`, `#path/<name>` or `#header/<name>` for parameters. 

        - example: ` "/url" `

      - ` detail `: type ` string ` — What is wrong there.

        - example: ` "must be an absolute http or https URL" `

  - ` reason `: type ` string ` — Finer-grained cause for codes that document one (`unauthorized`, `forbidden`, `egress_denied`, `upstream_unreachable`, …).

  - ` required_scope `: type ` string ` — The scope that was missing (`forbidden` with `reason: scope`).

  - ` retry_after_s `: type ` integer ` — Same value as the `Retry-After` header, for clients that only read the body.

    - minimum: ` 0 `

  - ` limit `: type ` object ` — The limit an error refers to. IDs and current values are listed by `GET /v1/limits`.

    - Required fields: ` id `, ` limit `, ` unit `

    - ` id `: type ` string ` — Limit ID, such as `vision.scrape.rpm` or `sandboxes.concurrent`.

      - example: ` "vision.scrape.rpm" `

    - ` limit `: type ` number ` — The limit's value.

    - ` unit `: type ` string ` — What the limit counts, such as `requests`, `sandboxes`, `vcpu` or `MiB`.

    - ` window_s `: type ` integer ` — Window length in seconds for rate limits and quotas.

    - ` current `: type ` number ` — Current usage against the limit, when known.

  - ` current_status `: type ` string ` — The object's current status, for state conflicts such as `sandbox_not_running`.

  - ` upstream_status `: type ` integer ` — The HTTP status the upstream returned (`upstream_error`, `action_output_invalid`).

  - ` step `: type ` string ` — The failed step, as a step ID (routines), an index (`act`) or a path such as `beats/2/do/0` (render).

  - ` pack_error `: type ` object ` — The error a pack's error mapping chose (`upstream_error` from pack actions).

    - Required fields: ` code `, ` message `, ` retryable `

    - ` code `: type ` string `

    - ` message `: type ` string `

    - ` retryable `: type ` boolean `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Response header ` Retry-After ` — Seconds to wait before retrying or polling again.

- ` value `: type ` integer `

  - minimum: ` 0 `

Response header ` RateLimit-Limit ` — Requests allowed in the current window for the limit that applies to this operation.

- ` value `: type ` integer `

Response header ` RateLimit-Remaining ` — Requests left in the current window.

- ` value `: type ` integer `

Response header ` RateLimit-Reset ` — Seconds until the current window resets.

- ` value `: type ` integer `

Response header ` RateLimit-Policy ` — The applied policy as `<limit>;w=<window seconds>;name="<limit id>"` (limit IDs are listed by `GET /v1/limits`).

- ` value `: type ` string `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#rate_limited",
  "title": "Rate limited",
  "status": 429,
  "code": "rate_limited",
  "detail": "60 scrapes per minute allowed; retry in 12 seconds",
  "instance": "req_01m5t4yg394wegr3j4y01qb363",
  "retry_after_s": 12,
  "limit": {
    "id": "vision.scrape.rpm",
    "limit": 60,
    "unit": "requests",
    "window_s": 60,
    "current": 60
  }
}
```

### ` 500 ` — Something failed inside B3OS (`internal`). Retry with backoff.

Content type: ` application/problem+json `

- ` value `: type ` object ` — An RFC 9457 problem. `code` is stable and listed in the errors catalog; `type` links to its entry. `detail` is human-readable and may change. Extension members appear only for the codes that document them; ignore members you do not recognize. 

  - Required fields: ` type `, ` title `, ` status `, ` code `, ` detail `

  - ` type `: type ` string `; format ` uri ` — `https://docs.beta.b3os.org/errors#<code>`.

    - example: ` "https://docs.beta.b3os.org/errors#invalid_request" `

  - ` title `: type ` string ` — Short summary of the problem type.

  - ` status `: type ` integer ` — The HTTP status code, repeated for convenience.

    - minimum: ` 400 `

    - maximum: ` 599 `

  - ` code `: type ` string ` — Stable machine-readable error code from the errors catalog.

    - pattern: ` "^[a-z][a-z0-9_]*$" `

  - ` detail `: type ` string ` — Explanation of this occurrence. Never contains secrets.

  - ` instance `: type ` string ` — The request ID (`req_…`) of the request that failed. Include it when you contact support.

    - example: ` "req_01m5t4yg394wegr3j4y01qb363" `

  - ` errors `: type ` array ` — Validation problems, one per field (`invalid_request` and the other codes that list `errors`).

    - ` array item `: type ` object ` — One validation problem.

      - Required fields: ` pointer `, ` detail `

      - ` pointer `: type ` string ` — Where the problem is: a JSON pointer into the request body (`/url`, `/steps/0/uses`), or `#query/<name>`, `#path/<name>` or `#header/<name>` for parameters. 

        - example: ` "/url" `

      - ` detail `: type ` string ` — What is wrong there.

        - example: ` "must be an absolute http or https URL" `

  - ` reason `: type ` string ` — Finer-grained cause for codes that document one (`unauthorized`, `forbidden`, `egress_denied`, `upstream_unreachable`, …).

  - ` required_scope `: type ` string ` — The scope that was missing (`forbidden` with `reason: scope`).

  - ` retry_after_s `: type ` integer ` — Same value as the `Retry-After` header, for clients that only read the body.

    - minimum: ` 0 `

  - ` limit `: type ` object ` — The limit an error refers to. IDs and current values are listed by `GET /v1/limits`.

    - Required fields: ` id `, ` limit `, ` unit `

    - ` id `: type ` string ` — Limit ID, such as `vision.scrape.rpm` or `sandboxes.concurrent`.

      - example: ` "vision.scrape.rpm" `

    - ` limit `: type ` number ` — The limit's value.

    - ` unit `: type ` string ` — What the limit counts, such as `requests`, `sandboxes`, `vcpu` or `MiB`.

    - ` window_s `: type ` integer ` — Window length in seconds for rate limits and quotas.

    - ` current `: type ` number ` — Current usage against the limit, when known.

  - ` current_status `: type ` string ` — The object's current status, for state conflicts such as `sandbox_not_running`.

  - ` upstream_status `: type ` integer ` — The HTTP status the upstream returned (`upstream_error`, `action_output_invalid`).

  - ` step `: type ` string ` — The failed step, as a step ID (routines), an index (`act`) or a path such as `beats/2/do/0` (render).

  - ` pack_error `: type ` object ` — The error a pack's error mapping chose (`upstream_error` from pack actions).

    - Required fields: ` code `, ` message `, ` retryable `

    - ` code `: type ` string `

    - ` message `: type ` string `

    - ` retryable `: type ` boolean `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#internal",
  "title": "Internal error",
  "status": 500,
  "code": "internal",
  "detail": "internal error",
  "instance": "req_01m5t4yg394wegr3j4y01qb363"
}
```

### ` 503 ` — The node or the product is not available right now (`node_unavailable`, `product_unavailable`, `capacity_unavailable`).

Content type: ` application/problem+json `

- ` value `: type ` object ` — An RFC 9457 problem. `code` is stable and listed in the errors catalog; `type` links to its entry. `detail` is human-readable and may change. Extension members appear only for the codes that document them; ignore members you do not recognize. 

  - Required fields: ` type `, ` title `, ` status `, ` code `, ` detail `

  - ` type `: type ` string `; format ` uri ` — `https://docs.beta.b3os.org/errors#<code>`.

    - example: ` "https://docs.beta.b3os.org/errors#invalid_request" `

  - ` title `: type ` string ` — Short summary of the problem type.

  - ` status `: type ` integer ` — The HTTP status code, repeated for convenience.

    - minimum: ` 400 `

    - maximum: ` 599 `

  - ` code `: type ` string ` — Stable machine-readable error code from the errors catalog.

    - pattern: ` "^[a-z][a-z0-9_]*$" `

  - ` detail `: type ` string ` — Explanation of this occurrence. Never contains secrets.

  - ` instance `: type ` string ` — The request ID (`req_…`) of the request that failed. Include it when you contact support.

    - example: ` "req_01m5t4yg394wegr3j4y01qb363" `

  - ` errors `: type ` array ` — Validation problems, one per field (`invalid_request` and the other codes that list `errors`).

    - ` array item `: type ` object ` — One validation problem.

      - Required fields: ` pointer `, ` detail `

      - ` pointer `: type ` string ` — Where the problem is: a JSON pointer into the request body (`/url`, `/steps/0/uses`), or `#query/<name>`, `#path/<name>` or `#header/<name>` for parameters. 

        - example: ` "/url" `

      - ` detail `: type ` string ` — What is wrong there.

        - example: ` "must be an absolute http or https URL" `

  - ` reason `: type ` string ` — Finer-grained cause for codes that document one (`unauthorized`, `forbidden`, `egress_denied`, `upstream_unreachable`, …).

  - ` required_scope `: type ` string ` — The scope that was missing (`forbidden` with `reason: scope`).

  - ` retry_after_s `: type ` integer ` — Same value as the `Retry-After` header, for clients that only read the body.

    - minimum: ` 0 `

  - ` limit `: type ` object ` — The limit an error refers to. IDs and current values are listed by `GET /v1/limits`.

    - Required fields: ` id `, ` limit `, ` unit `

    - ` id `: type ` string ` — Limit ID, such as `vision.scrape.rpm` or `sandboxes.concurrent`.

      - example: ` "vision.scrape.rpm" `

    - ` limit `: type ` number ` — The limit's value.

    - ` unit `: type ` string ` — What the limit counts, such as `requests`, `sandboxes`, `vcpu` or `MiB`.

    - ` window_s `: type ` integer ` — Window length in seconds for rate limits and quotas.

    - ` current `: type ` number ` — Current usage against the limit, when known.

  - ` current_status `: type ` string ` — The object's current status, for state conflicts such as `sandbox_not_running`.

  - ` upstream_status `: type ` integer ` — The HTTP status the upstream returned (`upstream_error`, `action_output_invalid`).

  - ` step `: type ` string ` — The failed step, as a step ID (routines), an index (`act`) or a path such as `beats/2/do/0` (render).

  - ` pack_error `: type ` object ` — The error a pack's error mapping chose (`upstream_error` from pack actions).

    - Required fields: ` code `, ` message `, ` retryable `

    - ` code `: type ` string `

    - ` message `: type ` string `

    - ` retryable `: type ` boolean `

Response header ` x-request-id ` — The request ID (`req_…`). It is the `instance` of any problem and the key for `GET /v1/requests/{request_id}`.

- ` value `: type ` string `

  - pattern: ` "^req_[0-9a-hjkmnp-tv-z]{26}$" `

Response header ` Server-Timing ` — Phase durations in milliseconds (W3C Server Timing); the handler's phases break the request down. For a
response whose body size is known, `total` runs from reading the request head to writing the response head.
Streaming responses (event streams, WebSockets, chunked bodies) carry no `total` here: they report their
final phases in the terminal event (`job.succeeded`, `job.failed`, `job.canceled`) or the final job. The
time from the first request byte to the last response byte is recorded in the node's metrics and request
log (`GET /v1/requests/{request_id}`). The edge prepends `edge_auth` and `edge_upstream`.


- ` value `: type ` string `

Response header ` Retry-After ` — Seconds to wait before retrying or polling again.

- ` value `: type ` integer `

  - minimum: ` 0 `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#node_unavailable",
  "title": "Node unavailable",
  "status": 503,
  "code": "node_unavailable",
  "detail": "Node n1 is not reachable; retry in 5 seconds",
  "instance": "req_01m5t4yg394wegr3j4y01qb363",
  "retry_after_s": 5
}
```

## Request examples

### cURL

```curl
curl -X GET 'https://beta-api.b3os.org/v1/render/videos/vid_01m5t4c5ep9bdfhtx7nk2k3vq7/timeline' \
  -H 'Authorization: Bearer YOUR_API_TOKEN'
```

### JavaScript

```javascript
const response = await fetch('https://beta-api.b3os.org/v1/render/videos/vid_01m5t4c5ep9bdfhtx7nk2k3vq7/timeline', {
  method: 'GET',
  headers: {
      "Authorization": "Bearer YOUR_API_TOKEN"
  }
});

const data = await response.json();
console.log(data);
```

### Python

```python
import requests

headers = {
    'Authorization': 'Bearer YOUR_API_TOKEN'
}

response = requests.get('https://beta-api.b3os.org/v1/render/videos/vid_01m5t4c5ep9bdfhtx7nk2k3vq7/timeline', headers=headers)
print(response.json())
```