> ## 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.

# Record a video

Starts a job that records a scripted demo of `source.url`. Narration (`say`) is synthesized first with `/v1/infer/audio/speech`; the director then places each beat's steps on its narration, plans cursor and camera, records segments in parallel on a virtual clock, composes at the output frame rate and encodes MP4 (H.264, BT.709), GIF, poster and captions. Artifacts appear as they finish (`video.artifact` events, poster first). Bills `render.video_s` per second of output. 

` POST /v1/render/videos `

Record a video

Starts a job that records a scripted demo of `source.url`. Narration (`say`) is synthesized first with
`/v1/infer/audio/speech`; the director then places each beat's steps on its narration, plans cursor and
camera, records segments in parallel on a virtual clock, composes at the output frame rate and encodes MP4
(H.264, BT.709), GIF, poster and captions. Artifacts appear as they finish (`video.artifact` events, poster
first). Bills `render.video_s` per second of output.


## 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

### ` wait ` (query, optional)

Seconds to wait for the job to finish before responding, from 0 to 60. If it finishes in time the response
is `200` with the finished job; otherwise `202` with the job as it is, a `Location` to poll and
`Retry-After`. `0` (the default) returns immediately.


- ` value `: type ` integer `

  - default: ` 0 `

  - minimum: ` 0 `

  - maximum: ` 60 `

### ` Idempotency-Key ` (header, optional)

A unique value (for example a UUID) that makes this request safe to retry. Scoped to your project for 24
hours: a retry with the same key, method, path and body returns the stored response with
`Idempotent-Replayed: true`, and only to the same API key. Reusing the key for a different request returns
`409 idempotency_key_conflict`.


- ` value `: type ` string `

  - minLength: ` 1 `

  - maxLength: ` 255 `

## Request body (required)

Content type: ` application/json `

- ` value `: type ` object `

  - Required fields: ` source `, ` beats `

  - ` source `: type ` object `

    - Required fields: ` url `

    - ` url `: type ` string `; format ` uri ` — Where the recording starts.

      - maxLength: ` 4096 `

    - ` profile `: type ` string ` — A vision profile ID or name to start signed in. Responses show the resolved `prof_` ID.

      - maxLength: ` 100 `

  - ` beats `: type ` array `

    - ` array item `: type ` object ` — One line of narration and the steps performed while it is said.

      - ` id `: type ` string ` — Optional ID; generated as `b1`, `b2`, … when omitted.

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

      - ` title `: type ` string `

        - maxLength: ` 200 `

      - ` say `: type ` string ` — Narration for this beat. Omit for a silent beat.

        - maxLength: ` 2000 `

      - ` do `: type ` array `

        - ` array item `: type ` unknown ` — One browser step of a beat; `kind` selects it. These are the timeline action kinds (`timeline.schema.json#/$defs/action`) without timing, which the director computes from the narration. 

          - ` oneOf alternative 1 `: type ` object `

            - Required fields: ` kind `, ` url `

            - ` kind `: type ` string `

              - enum: ` ["navigate"] `

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

              - maxLength: ` 4096 `

            - ` wait_until `: type ` string `

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

              - default: ` "load" `

            - ` timeout_ms `: type ` integer `

              - default: ` 10000 `

              - minimum: ` 100 `

              - maximum: ` 120000 `

          - ` oneOf alternative 2 `: type ` object `

            - Required fields: ` kind `, ` target `

            - ` kind `: type ` string `

              - enum: ` ["click"] `

            - ` target `: type ` object ` — How an action finds its element (the same rules as render timelines, `timeline.schema.json#/$defs/target`): candidates match `selector` (CSS), `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 set. An element that stays outside the viewport after scrolling it into view fails with `target_not_found`. 

              - example: ` {"role":"button","name":"Continue"} `

              - ` 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 `

            - ` button `: type ` string `

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

              - default: ` "left" `

            - ` count `: type ` integer `

              - default: ` 1 `

              - minimum: ` 1 `

              - maximum: ` 3 `

            - ` modifiers `: type ` array ` — Modifier keys held during the action.

              - ` array item `: type ` string `

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

          - ` oneOf alternative 3 `: type ` object `

            - Required fields: ` kind `, ` target `

            - ` kind `: type ` string `

              - enum: ` ["hover"] `

            - ` target `: type ` object ` — How an action finds its element (the same rules as render timelines, `timeline.schema.json#/$defs/target`): candidates match `selector` (CSS), `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 set. An element that stays outside the viewport after scrolling it into view fails with `target_not_found`. 

              - example: ` {"role":"button","name":"Continue"} `

              - ` 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 `

          - ` oneOf alternative 4 `: type ` object `

            - Required fields: ` kind `, ` text `

            - ` kind `: type ` string `

              - enum: ` ["type"] `

            - ` target `: type ` object ` — How an action finds its element (the same rules as render timelines, `timeline.schema.json#/$defs/target`): candidates match `selector` (CSS), `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 set. An element that stays outside the viewport after scrolling it into view fails with `target_not_found`. 

              - example: ` {"role":"button","name":"Continue"} `

              - ` 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 `

            - ` text `: type ` string `

              - maxLength: ` 10000 `

            - ` interval_ms `: type ` integer ` — Delay between characters on the video's clock.

              - default: ` 80 `

              - minimum: ` 0 `

              - maximum: ` 1000 `

          - ` oneOf alternative 5 `: type ` object `

            - Required fields: ` kind `, ` key `

            - ` kind `: type ` string `

              - enum: ` ["key"] `

            - ` key `: type ` string `

              - minLength: ` 1 `

              - maxLength: ` 32 `

            - ` modifiers `: type ` array ` — Modifier keys held during the action.

              - ` array item `: type ` string `

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

          - ` oneOf alternative 6 `: type ` object ` — Scroll to an offset (`to`), by a delta (`by`), or until `target` is in view.

            - Required fields: ` kind `

            - ` kind `: type ` string `

              - enum: ` ["scroll"] `

            - ` target `: type ` object ` — How an action finds its element (the same rules as render timelines, `timeline.schema.json#/$defs/target`): candidates match `selector` (CSS), `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 set. An element that stays outside the viewport after scrolling it into view fails with `target_not_found`. 

              - example: ` {"role":"button","name":"Continue"} `

              - ` 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 `

            - ` to `: type ` object ` — A position in CSS pixels.

              - Required fields: ` x `, ` y `

              - ` x `: type ` number `

              - ` y `: type ` number `

            - ` by `: type ` object ` — A position in CSS pixels.

              - Required fields: ` x `, ` y `

              - ` x `: type ` number `

              - ` y `: type ` number `

            - ` duration_ms `: type ` integer `

              - default: ` 600 `

              - minimum: ` 0 `

              - maximum: ` 10000 `

          - ` oneOf alternative 7 `: type ` object `

            - Required fields: ` kind `, ` target `, ` value `

            - ` kind `: type ` string `

              - enum: ` ["select"] `

            - ` target `: type ` object ` — How an action finds its element (the same rules as render timelines, `timeline.schema.json#/$defs/target`): candidates match `selector` (CSS), `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 set. An element that stays outside the viewport after scrolling it into view fails with `target_not_found`. 

              - example: ` {"role":"button","name":"Continue"} `

              - ` 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 `

            - ` value `: type ` string `

              - maxLength: ` 1000 `

          - ` oneOf alternative 8 `: type ` object ` — Pause the story (`ms`) or hold the clock until a condition holds (`for`).

            - Required fields: ` kind `

            - ` kind `: type ` string `

              - enum: ` ["wait"] `

            - ` ms `: type ` integer `

              - minimum: ` 1 `

              - maximum: ` 30000 `

            - ` for `: type ` object ` — Exactly one condition to wait for (the same as a timeline `wait` action's `for`).

              - ` selector `: type ` string ` — An element matching this CSS selector is visible.

                - maxLength: ` 1024 `

              - ` text `: type ` string ` — This text is visible.

                - maxLength: ` 500 `

              - ` url `: type ` string ` — The page URL contains this substring.

                - maxLength: ` 4096 `

              - ` network_idle `: type ` boolean ` — The network has been quiet.

                - enum: ` [true] `

            - ` timeout_ms `: type ` integer `

              - default: ` 10000 `

              - minimum: ` 100 `

              - maximum: ` 120000 `

      - ` hold_ms `: type ` integer ` — Extra time to stay on the beat after its narration and steps end.

        - minimum: ` 0 `

        - maximum: ` 10000 `

  - ` voice `: type ` object `

    - Required fields: ` model `, ` voice `

    - ` model `: type ` string ` — A speech model from `GET /v1/infer/models`, such as `kokoro-82m`.

      - maxLength: ` 64 `

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

    - ` voice `: type ` string ` — A voice from `GET /v1/infer/audio/voices`.

      - maxLength: ` 64 `

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

    - ` speed `: type ` number `

      - default: ` 1 `

      - minimum: ` 0.5 `

      - maximum: ` 2 `

  - ` captions `: type ` object `

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

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

      - default: ` "none" `

    - ` sidecars `: type ` array `

      - default: ` ["vtt"] `

      - ` array item `: type ` string `

        - 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 `

  - ` style `: type ` object ` — Style presets plus overrides, the same object as a timeline's `style` (restyle replaces exactly this). Field values inside `overrides` follow the compositor's style type (padding, corner radius, shadow, colors, gradients); strings are escaped before they reach any HTML or CSS. 

    - ` background `: type ` string ` — A preset ID from `GET /v1/render/presets`, such as `midnight`, `browser-dark` or `mac`.

      - maxLength: ` 64 `

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

    - ` frame `: type ` string ` — A preset ID from `GET /v1/render/presets`, such as `midnight`, `browser-dark` or `mac`.

      - maxLength: ` 64 `

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

    - ` cursor `: type ` string ` — A preset ID from `GET /v1/render/presets`, such as `midnight`, `browser-dark` or `mac`.

      - maxLength: ` 64 `

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

    - ` captions `: type ` string ` — A preset ID from `GET /v1/render/presets`, such as `midnight`, `browser-dark` or `mac`.

      - maxLength: ` 64 `

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

    - ` click_effect `: type ` string ` — A preset ID from `GET /v1/render/presets`, such as `midnight`, `browser-dark` or `mac`.

      - maxLength: ` 64 `

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

    - ` overrides `: type ` object ` — Style fields that override the presets.

  - ` camera `: type ` object `

    - ` auto_zoom `: type ` boolean ` — Zoom toward the element each step acts on.

      - default: ` true `

    - ` max_zoom `: type ` number `

      - default: ` 2 `

      - minimum: ` 1 `

      - maximum: ` 3 `

  - ` viewport `: type ` object ` — Browser viewport in CSS pixels.

    - Required fields: ` width `, ` height `

    - ` width `: type ` integer `

      - minimum: ` 320 `

      - maximum: ` 3840 `

    - ` height `: type ` integer `

      - minimum: ` 240 `

      - maximum: ` 2160 `

  - ` output `: type ` object `

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

    - ` width `: type ` integer `

      - minimum: ` 16 `

      - maximum: ` 3840 `

    - ` height `: type ` integer `

      - minimum: ` 16 `

      - maximum: ` 2160 `

    - ` fps `: type ` integer `

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

  - ` formats `: type ` array `

    - default: ` ["mp4","poster"] `

    - ` array item `: type ` string `

      - enum: ` ["mp4","gif","poster"] `

  - ` seed `: type ` integer ` — Seeds the page's randomness so a re-render is identical.

    - minimum: ` 0 `

  - ` start_time `: type ` string `; format ` date-time ` — The page's `Date` at the start of the video; the clock then advances with the video.

  - ` recording `: type ` object ` — Where the page's network traffic comes from. By default every video loads the site live and records that load (its capture segments replay the recording, so they all see the same content). With `reuse: true` the video replays the newest recording another video of this project made of the same source URL, steps, viewport, seed and start time within `max_age_s`, instead of loading the site again: faster, and the content is what the site served then. When no such recording exists the site is loaded and recorded as usual. `result.recording` says which happened. Recordings hold the page's responses; they are deleted 24 hours after they were made, or earlier with the last video that used them. 

    - ` reuse `: type ` boolean `

      - default: ` false `

    - ` max_age_s `: type ` integer ` — The oldest recording `reuse` accepts, in seconds.

      - default: ` 86400 `

      - minimum: ` 60 `

      - maximum: ` 86400 `

  - ` webhook `: type ` object ` — Where to deliver this job's events. Deliveries are `POST`s of a `WebhookEvent` signed with `B3OS-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">` using the endpoint's secret (`POST /v1/webhooks/secret`). Failed deliveries are retried with backoff for 24 hours. Delivery goes through the egress guard, so private and loopback addresses are refused. 

    - Required fields: ` url `

    - ` url `: type ` string `; format ` uri ` — An `https://` URL.

      - example: ` "https://example.com/hooks/b3os" `

      - maxLength: ` 2048 `

    - ` events `: type ` array ` — Event types to deliver. Defaults to the terminal events (`job.succeeded`, `job.failed`, `job.canceled`); `["*"]` delivers every event.

      - example: ` ["job.succeeded","job.failed"] `

      - ` array item `: type ` string `

        - maxLength: ` 64 `

  - ` metadata `: type ` object ` — Up to 16 string key-value pairs you attach to an object for your own use. Keys are 1 to 40 characters of `A-Z a-z 0-9 _ . : -`; values are at most 500 characters. B3OS never interprets them. 

    - example: ` {"customer":"acme","ticket":"ENG-1423"} `

Example:

```json
{
  "source": {
    "url": "https://app.example.com",
    "profile": "acme-staging"
  },
  "beats": [
    {
      "say": "Open the billing page.",
      "do": [
        {
          "kind": "click",
          "target": {
            "role": "link",
            "name": "Billing"
          }
        }
      ]
    },
    {
      "say": "Switch to annual and watch the price update.",
      "do": [
        {
          "kind": "click",
          "target": {
            "text": "Annual",
            "exact": true
          }
        }
      ]
    }
  ],
  "voice": {
    "model": "kokoro-82m",
    "voice": "af_heart"
  },
  "captions": {
    "burn_in": "karaoke",
    "sidecars": [
      "vtt"
    ]
  },
  "style": {
    "background": "midnight",
    "frame": "browser-dark",
    "cursor": "mac"
  },
  "formats": [
    "mp4",
    "gif",
    "poster"
  ]
}
```

## Responses

### ` 200 ` — The video finished within `wait` seconds, or the event stream when `Accept` is `text/event-stream`.

Content type: ` application/json `

- ` value `: type ` object ` — A video job (`vid_…`). `progress` counts phases (voice, plan, capture, compose, encode, upload).

  - Required fields: ` id `, ` object `, ` status `, ` created_at `, ` updated_at `, ` source `, ` restyled_from `

  - ` id `: type ` string `

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

  - ` object `: type ` string `

    - enum: ` ["video"] `

  - ` status `: type ` string ` — `queued` → `running` → one of the terminal statuses `succeeded`, `failed` or `canceled`. A job never leaves a terminal status. 

    - enum: ` ["queued","running","succeeded","failed","canceled"] `

  - ` created_at `: type ` string `; format ` date-time `

  - ` updated_at `: type ` string `; format ` date-time `

  - ` started_at `: type ` string `; nullable; format ` date-time `

  - ` finished_at `: type ` string `; nullable; format ` date-time `

  - ` progress `: type ` object ` — How far a job has got, in the job's own unit (pages, items, steps).

    - Required fields: ` completed `, ` unit `

    - ` completed `: type ` integer ` — Units finished, successfully or not.

      - minimum: ` 0 `

    - ` failed `: type ` integer ` — Units that failed (included in `completed`).

      - minimum: ` 0 `

    - ` total `: type ` integer `; nullable — Units expected, when known.

      - minimum: ` 0 `

    - ` unit `: type ` string ` — What is counted, such as `pages`, `items` or `steps`.

  - ` result `: type ` object `

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

    - ` duration_ms `: type ` integer `

    - ` width `: type ` integer `

    - ` height `: type ` integer `

    - ` fps `: type ` integer `

    - ` artifacts `: type ` array `

      - ` array item `: type ` object `

        - Required fields: ` id `, ` object `, ` kind `, ` content_type `

        - ` id `: type ` string `

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

        - ` object `: type ` string `

          - enum: ` ["artifact"] `

        - ` kind `: type ` string `

          - enum: ` ["image","mp4","gif","poster","vtt","srt"] `

        - ` content_type `: type ` string `

        - ` bytes `: type ` integer `

        - ` width `: type ` integer `

        - ` height `: type ` integer `

        - ` duration_ms `: type ` integer `

        - ` url `: type ` string `; format ` uri ` — Signed URL on `usercontent.b3os.org`, `https://usercontent.b3os.org/a/<id in host-safe form>/<name>?node=&exp=&sig=`: an Ed25519 signature by the node's key over the method, path and expiry (`renderGetArtifactContent`), no cookies. It works as soon as the artifact is reported, while the upload to storage is still finishing. 

        - ` url_expires_at `: type ` string `; format ` date-time `

        - ` created_at `: type ` string `; format ` date-time `

        - ` expires_at `: type ` string `; format ` date-time ` — When the artifact is deleted.

    - ` recording `: type ` object `

      - Required fields: ` reused `

      - ` reused `: type ` boolean ` — True when the video replayed an earlier recording (`recording.reuse`) instead of loading the site.

      - ` recorded_at `: type ` string `; format ` date-time ` — When the replayed or new recording was made.

  - ` error `: 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 `

  - ` timing `: type ` object ` — Server-side phase durations in milliseconds with microsecond resolution: the same phases as the `Server-Timing` header, keyed `<phase>_ms`. `total_ms` is always present. Phase names are product-specific and documented per operation. Example values in this reference are illustrative, not measurements. 

    - example: ` {"claim_ms":1.1,"navigate_ms":31,"extract_ms":4.2,"total_ms":36.6} `

    - Required fields: ` total_ms `

    - ` total_ms `: type ` number `

      - minimum: ` 0 `

  - ` expires_at `: type ` string `; nullable; format ` date-time ` — When the job's results are deleted (retention); `null` while the job is not terminal.

  - ` metadata `: type ` object ` — Up to 16 string key-value pairs you attach to an object for your own use. Keys are 1 to 40 characters of `A-Z a-z 0-9 _ . : -`; values are at most 500 characters. B3OS never interprets them. 

    - example: ` {"customer":"acme","ticket":"ENG-1423"} `

  - ` webhook `: type ` object ` — Where to deliver this job's events. Deliveries are `POST`s of a `WebhookEvent` signed with `B3OS-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">` using the endpoint's secret (`POST /v1/webhooks/secret`). Failed deliveries are retried with backoff for 24 hours. Delivery goes through the egress guard, so private and loopback addresses are refused. 

    - Required fields: ` url `

    - ` url `: type ` string `; format ` uri ` — An `https://` URL.

      - example: ` "https://example.com/hooks/b3os" `

      - maxLength: ` 2048 `

    - ` events `: type ` array ` — Event types to deliver. Defaults to the terminal events (`job.succeeded`, `job.failed`, `job.canceled`); `["*"]` delivers every event.

      - example: ` ["job.succeeded","job.failed"] `

      - ` array item `: type ` string `

        - maxLength: ` 64 `

  - ` source `: type ` object `

    - Required fields: ` url `

    - ` url `: type ` string `; format ` uri ` — Where the recording starts.

      - maxLength: ` 4096 `

    - ` profile `: type ` string ` — A vision profile ID or name to start signed in. Responses show the resolved `prof_` ID.

      - maxLength: ` 100 `

  - ` restyled_from `: type ` string `; nullable — The source video when this video is a restyle.

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 ` Idempotent-Replayed ` — Present with the value `true` when the response is a stored replay of an earlier request with the same `Idempotency-Key`.

- ` value `: type ` string `

  - enum: ` ["true"] `

Example:

```json
{
  "id": "vid_01m5t4c5ep9bdfhtx7nk2k3vq7",
  "object": "video",
  "status": "succeeded",
  "source": {
    "url": "https://app.example.com",
    "profile": "prof_01m5t3v4507bhcb5jqrgzfvfsk"
  },
  "restyled_from": null,
  "created_at": "2026-10-25T18:50:00.000Z",
  "updated_at": "2026-10-25T18:50:06.420Z",
  "started_at": "2026-10-25T18:50:00.010Z",
  "finished_at": "2026-10-25T18:50:06.420Z",
  "progress": {
    "completed": 6,
    "total": 6,
    "unit": "phases"
  },
  "result": {
    "duration_ms": 9480,
    "width": 1920,
    "height": 1080,
    "fps": 60,
    "artifacts": [
      {
        "id": "art_01m5t5mh213we8gzwkr08x6ef9",
        "object": "artifact",
        "kind": "mp4",
        "content_type": "video/mp4",
        "bytes": 2210388,
        "width": 1920,
        "height": 1080,
        "duration_ms": 9480,
        "url": "https://usercontent.b3os.org/a/art-01m5t5mh213we8gzwkr08x6ef9/video.mp4?node=n1&exp=1793040606&sig=TLNvLS_42-1c-rA5z8mLZn7wLwstijGhGIFm3VyqZ-qCNuNOJ9QZ97k1ZGQGRNB_qt3AueFtNg1WeoX0wjVeCA",
        "url_expires_at": "2026-10-26T18:50:06.000Z",
        "created_at": "2026-10-25T18:50:06.400Z",
        "expires_at": "2026-11-01T18:50:06.400Z"
      }
    ]
  },
  "timing": {
    "voice_ms": 210.3,
    "plan_ms": 6.1,
    "capture_ms": 3302.8,
    "compose_ms": 1210.4,
    "encode_ms": 1642,
    "total_ms": 6410.2
  },
  "expires_at": "2026-11-01T18:50:06.420Z",
  "metadata": {}
}
```

### ` 202 ` — The video job was accepted and is still running.

Content type: ` application/json `

- ` value `: type ` object ` — A video job (`vid_…`). `progress` counts phases (voice, plan, capture, compose, encode, upload).

  - Required fields: ` id `, ` object `, ` status `, ` created_at `, ` updated_at `, ` source `, ` restyled_from `

  - ` id `: type ` string `

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

  - ` object `: type ` string `

    - enum: ` ["video"] `

  - ` status `: type ` string ` — `queued` → `running` → one of the terminal statuses `succeeded`, `failed` or `canceled`. A job never leaves a terminal status. 

    - enum: ` ["queued","running","succeeded","failed","canceled"] `

  - ` created_at `: type ` string `; format ` date-time `

  - ` updated_at `: type ` string `; format ` date-time `

  - ` started_at `: type ` string `; nullable; format ` date-time `

  - ` finished_at `: type ` string `; nullable; format ` date-time `

  - ` progress `: type ` object ` — How far a job has got, in the job's own unit (pages, items, steps).

    - Required fields: ` completed `, ` unit `

    - ` completed `: type ` integer ` — Units finished, successfully or not.

      - minimum: ` 0 `

    - ` failed `: type ` integer ` — Units that failed (included in `completed`).

      - minimum: ` 0 `

    - ` total `: type ` integer `; nullable — Units expected, when known.

      - minimum: ` 0 `

    - ` unit `: type ` string ` — What is counted, such as `pages`, `items` or `steps`.

  - ` result `: type ` object `

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

    - ` duration_ms `: type ` integer `

    - ` width `: type ` integer `

    - ` height `: type ` integer `

    - ` fps `: type ` integer `

    - ` artifacts `: type ` array `

      - ` array item `: type ` object `

        - Required fields: ` id `, ` object `, ` kind `, ` content_type `

        - ` id `: type ` string `

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

        - ` object `: type ` string `

          - enum: ` ["artifact"] `

        - ` kind `: type ` string `

          - enum: ` ["image","mp4","gif","poster","vtt","srt"] `

        - ` content_type `: type ` string `

        - ` bytes `: type ` integer `

        - ` width `: type ` integer `

        - ` height `: type ` integer `

        - ` duration_ms `: type ` integer `

        - ` url `: type ` string `; format ` uri ` — Signed URL on `usercontent.b3os.org`, `https://usercontent.b3os.org/a/<id in host-safe form>/<name>?node=&exp=&sig=`: an Ed25519 signature by the node's key over the method, path and expiry (`renderGetArtifactContent`), no cookies. It works as soon as the artifact is reported, while the upload to storage is still finishing. 

        - ` url_expires_at `: type ` string `; format ` date-time `

        - ` created_at `: type ` string `; format ` date-time `

        - ` expires_at `: type ` string `; format ` date-time ` — When the artifact is deleted.

    - ` recording `: type ` object `

      - Required fields: ` reused `

      - ` reused `: type ` boolean ` — True when the video replayed an earlier recording (`recording.reuse`) instead of loading the site.

      - ` recorded_at `: type ` string `; format ` date-time ` — When the replayed or new recording was made.

  - ` error `: 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 `

  - ` timing `: type ` object ` — Server-side phase durations in milliseconds with microsecond resolution: the same phases as the `Server-Timing` header, keyed `<phase>_ms`. `total_ms` is always present. Phase names are product-specific and documented per operation. Example values in this reference are illustrative, not measurements. 

    - example: ` {"claim_ms":1.1,"navigate_ms":31,"extract_ms":4.2,"total_ms":36.6} `

    - Required fields: ` total_ms `

    - ` total_ms `: type ` number `

      - minimum: ` 0 `

  - ` expires_at `: type ` string `; nullable; format ` date-time ` — When the job's results are deleted (retention); `null` while the job is not terminal.

  - ` metadata `: type ` object ` — Up to 16 string key-value pairs you attach to an object for your own use. Keys are 1 to 40 characters of `A-Z a-z 0-9 _ . : -`; values are at most 500 characters. B3OS never interprets them. 

    - example: ` {"customer":"acme","ticket":"ENG-1423"} `

  - ` webhook `: type ` object ` — Where to deliver this job's events. Deliveries are `POST`s of a `WebhookEvent` signed with `B3OS-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">` using the endpoint's secret (`POST /v1/webhooks/secret`). Failed deliveries are retried with backoff for 24 hours. Delivery goes through the egress guard, so private and loopback addresses are refused. 

    - Required fields: ` url `

    - ` url `: type ` string `; format ` uri ` — An `https://` URL.

      - example: ` "https://example.com/hooks/b3os" `

      - maxLength: ` 2048 `

    - ` events `: type ` array ` — Event types to deliver. Defaults to the terminal events (`job.succeeded`, `job.failed`, `job.canceled`); `["*"]` delivers every event.

      - example: ` ["job.succeeded","job.failed"] `

      - ` array item `: type ` string `

        - maxLength: ` 64 `

  - ` source `: type ` object `

    - Required fields: ` url `

    - ` url `: type ` string `; format ` uri ` — Where the recording starts.

      - maxLength: ` 4096 `

    - ` profile `: type ` string ` — A vision profile ID or name to start signed in. Responses show the resolved `prof_` ID.

      - maxLength: ` 100 `

  - ` restyled_from `: type ` string `; nullable — The source video when this video is a restyle.

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 ` Location ` — URL of the created job or object; poll it with `GET`.

- ` value `: type ` string `; format ` uri-reference `

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

- ` value `: type ` integer `

  - minimum: ` 0 `

Response header ` Idempotent-Replayed ` — Present with the value `true` when the response is a stored replay of an earlier request with the same `Idempotency-Key`.

- ` value `: type ` string `

  - enum: ` ["true"] `

Example:

```json
{
  "id": "vid_01m5t4c5ep9bdfhtx7nk2k3vq7",
  "object": "video",
  "status": "running",
  "source": {
    "url": "https://app.example.com",
    "profile": "prof_01m5t3v4507bhcb5jqrgzfvfsk"
  },
  "restyled_from": null,
  "created_at": "2026-10-25T18:50:00.000Z",
  "updated_at": "2026-10-25T18:50:00.220Z",
  "started_at": "2026-10-25T18:50:00.010Z",
  "finished_at": null,
  "progress": {
    "completed": 1,
    "total": 6,
    "unit": "phases"
  },
  "expires_at": null,
  "metadata": {}
}
```

### ` 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"
}
```

### ` 402 ` — The organization has no credits left, or the key reached its spend cap.

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#credits_exhausted",
  "title": "Credits exhausted",
  "status": 402,
  "code": "credits_exhausted",
  "detail": "Organization org_01m5t5hthd29mm5wpza5ndd6mm has no credits left",
  "instance": "req_01m5t4yg394wegr3j4y01qb363"
}
```

### ` 403 ` — The egress guard refused the source URL (`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#egress_denied",
  "title": "Destination not allowed",
  "status": 403,
  "code": "egress_denied",
  "detail": "http://127.0.0.1:3000/ is a loopback address",
  "instance": "req_01m5t4yg394wegr3j4y01qb363",
  "reason": "loopback"
}
```

### ` 409 ` — The object's state does not allow this operation, or the idempotency key conflicts.

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#idempotency_key_conflict",
  "title": "Idempotency key conflict",
  "status": 409,
  "code": "idempotency_key_conflict",
  "detail": "This Idempotency-Key was used with a different request body",
  "instance": "req_01m5t4yg394wegr3j4y01qb363"
}
```

### ` 413 ` — The request body exceeds this operation's limit.

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#payload_too_large",
  "title": "Payload too large",
  "status": 413,
  "code": "payload_too_large",
  "detail": "Request body is 1572864 bytes; this operation accepts at most 1048576",
  "instance": "req_01m5t4yg394wegr3j4y01qb363"
}
```

### ` 415 ` — The Content-Type is not accepted by this operation.

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#unsupported_media_type",
  "title": "Unsupported media type",
  "status": 415,
  "code": "unsupported_media_type",
  "detail": "Expected Content-Type application/json",
  "instance": "req_01m5t4yg394wegr3j4y01qb363"
}
```

### ` 422 ` — The video request failed validation (`script_invalid`, `style_invalid`, `limit_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 `

Example:

```json
{
  "type": "https://docs.beta.b3os.org/errors#script_invalid",
  "title": "Invalid video script",
  "status": 422,
  "code": "script_invalid",
  "detail": "1 step is invalid",
  "instance": "req_01m5t4yg394wegr3j4y01qb363",
  "errors": [
    {
      "pointer": "/beats/1/do/0/target",
      "detail": "give one of selector, text or role"
    }
  ]
}
```

### ` 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"
}
```

### ` 501 ` — `profile` was given but this node cannot load browser profiles into render yet (`not_implemented`): render
reads profiles through vision's profile API, which is not on the node. Capture without `profile`.


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#not_implemented",
  "title": "Not implemented",
  "status": 501,
  "code": "not_implemented",
  "detail": "browser profiles in render need vision's profile API, which this node does not have yet; capture without profile",
  "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 POST 'https://beta-api.b3os.org/v1/render/videos' \
  -H 'Authorization: Bearer YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
  "source": {
    "url": "https://app.example.com",
    "profile": "acme-staging"
  },
  "beats": [
    {
      "say": "Open the billing page.",
      "do": [
        {
          "kind": "click",
          "target": {
            "role": "link",
            "name": "Billing"
          }
        }
      ]
    },
    {
      "say": "Switch to annual and watch the price update.",
      "do": [
        {
          "kind": "click",
          "target": {
            "text": "Annual",
            "exact": true
          }
        }
      ]
    }
  ],
  "voice": {
    "model": "kokoro-82m",
    "voice": "af_heart"
  },
  "captions": {
    "burn_in": "karaoke",
    "sidecars": [
      "vtt"
    ]
  },
  "style": {
    "background": "midnight",
    "frame": "browser-dark",
    "cursor": "mac"
  },
  "formats": [
    "mp4",
    "gif",
    "poster"
  ]
}'
```

### JavaScript

```javascript
const response = await fetch('https://beta-api.b3os.org/v1/render/videos', {
  method: 'POST',
  headers: {
      "Authorization": "Bearer YOUR_API_TOKEN",
      "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "source": {
      "url": "https://app.example.com",
      "profile": "acme-staging"
    },
    "beats": [
      {
        "say": "Open the billing page.",
        "do": [
          {
            "kind": "click",
            "target": {
              "role": "link",
              "name": "Billing"
            }
          }
        ]
      },
      {
        "say": "Switch to annual and watch the price update.",
        "do": [
          {
            "kind": "click",
            "target": {
              "text": "Annual",
              "exact": true
            }
          }
        ]
      }
    ],
    "voice": {
      "model": "kokoro-82m",
      "voice": "af_heart"
    },
    "captions": {
      "burn_in": "karaoke",
      "sidecars": [
        "vtt"
      ]
    },
    "style": {
      "background": "midnight",
      "frame": "browser-dark",
      "cursor": "mac"
    },
    "formats": [
      "mp4",
      "gif",
      "poster"
    ]
  })
});

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

### Python

```python
import requests

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

response = requests.post('https://beta-api.b3os.org/v1/render/videos', headers=headers, json={
  "source": {
    "url": "https://app.example.com",
    "profile": "acme-staging"
  },
  "beats": [
    {
      "say": "Open the billing page.",
      "do": [
        {
          "kind": "click",
          "target": {
            "role": "link",
            "name": "Billing"
          }
        }
      ]
    },
    {
      "say": "Switch to annual and watch the price update.",
      "do": [
        {
          "kind": "click",
          "target": {
            "text": "Annual",
            "exact": true
          }
        }
      ]
    }
  ],
  "voice": {
    "model": "kokoro-82m",
    "voice": "af_heart"
  },
  "captions": {
    "burn_in": "karaoke",
    "sidecars": [
      "vtt"
    ]
  },
  "style": {
    "background": "midnight",
    "frame": "browser-dark",
    "cursor": "mac"
  },
  "formats": [
    "mp4",
    "gif",
    "poster"
  ]
})
print(response.json())
```