---
title: "Make a video from a storyboard you approved"
method: POST
path: "/storyboards/{id}/renders"
tags: ["renders"]
---

# Make a video from a storyboard you approved

`POST /storyboards/{id}/renders`

## Request

- Base URL: `https://api.gogoscreen.com/api/v1`
- URL: `https://api.gogoscreen.com/api/v1/storyboards/{id}/renders`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

Turn a finished storyboard into a video: the beats it proved, in order, with the words you approve. Each beat may have its narration rewritten or be hidden altogether; everything else about a beat — what it clicks, where it goes, what it types — is the plan's own and is not accepted from a caller. The render inherits the storyboard's options, so the video matches what was planned. Answers 202 with a `Location`; the cost and the settlement are `renders.create`'s.

## Path parameters

- `id` string, uuid, required

## Headers

- `Idempotency-Key` string, required

## Request body

- object
  - `beats` object[]: The beats to keep and what they say. Absent renders the plan as it stands.
    - `beatId` string, required
    - `hidden` boolean: Leave this beat out of the video.
    - `narration` string, nullable: Replace this beat's line. Null or absent keeps the planned one.
  - `credentials` object: Only needed when the storyboard's own session credential has expired. They replace it: kept encrypted for that storyboard's session and deleted at most two hours after their last use.
    - `additionalLoginOrigins` string[]: Other exact https origins this account's sign-in may pass through, e.g. ["https://login.example.com"] for a single sign-on provider on its own host. At most 5. Nothing else — not a redirect, a link or a sibling subdomain — is ever approved on its own: a sign-in that moves to an origin not listed here stops before the account is typed. Ordinary same-origin sign-ins need none.
    - `loginUrl` string, required: REQUIRED whenever credentials are given: the page this demo account signs in on, e.g. https://app.example.com/login. Any origin — a product commonly signs in on a different host from its marketing site, and this is what tells the run where the app itself lives. Must be https; checked by the same guard as the site address. Its origin is the only place the account is typed unless `additionalLoginOrigins` names others.
    - `password` string, required
    - `username` string, required

## Response `200`

The work was already known — the service recognised this key on its own record and queued nothing new. Answered when the 24-hour idempotency claim has expired but the work has not.

- object
  - `created` boolean, required
  - `credentialSource` string, nullable, required
  - `lengthFit` object, nullable, required: WHAT THIS RENDER DID ABOUT THE LENGTH. The storyboard's own `lengthFit` is about the PLAN; this one is about the video just queued, and the two differ exactly when the chosen length cannot hold every beat the plan proved. Null when the storyboard names no length at all, and null on a replayed request, which measured nothing.
    - `adjusted` boolean, required: Whether this video is shorter than the storyboard's plan. Render at a longer length, or hide beats yourself, to choose what goes.
    - `beatBudget` number, nullable, required: The steps that length can hold.
    - `beatsDropped` number, required: Steps this render leaves out because the length cannot hold them. Taught extras yield their slot first; only then is the walkthrough itself cut, and always off the end.
    - `beatsKept` number, required: Steps the video will actually show.
    - `beatsPlanned` number, required: Steps the storyboard offered this render, after your own hidden beats were taken out and any taught steps put back.
    - `cappedFromSeconds` number, nullable, required: The length asked for, when a shorter one was used instead. Null on this operation.
    - `maxSeconds` number, nullable, required: The ceiling an Auto render is sized against, or null when a fixed length was chosen.
    - `note` string, nullable, required: The sentence to show, e.g. "Plan adjusted to fit 60 seconds: 10 of 13 steps kept." Null when nothing was adjusted.
    - `plannedSeconds` number, nullable, required: What the kept steps are worth in seconds — what the video will run to, before the read is measured.
    - `seconds` number, nullable, required: The length everything below was decided from: the fixed length, or the Auto ceiling.
    - `targetSeconds` number, nullable, required: The fixed length this render holds, or null when the storyboard was planned as Auto.
  - `resource` object, required
    - `artifactsExpired` boolean, required: The work succeeded but its files were deleted at the end of the retention period.
    - `cancellable` boolean, required
    - `cost` object, required
      - `secondsCharged` number, nullable, required
      - `secondsReserved` number, required
      - `watermark` boolean, required
    - `createdAt` string, date-time, nullable, required
    - `error` object, nullable, required
      - `code` string, required
      - `reason` string, nullable, required
      - `retryable` boolean, required
      - `terminal` boolean, required
    - `expiresAt` string, date-time, nullable, required
    - `finishedAt` string, date-time, nullable, required
    - `id` string, required
    - `idempotencyKey` string, nullable, required
    - `internalStatus` string, required: A finer-grained status word. Informational; branch on `state`.
    - `kind` string, required: walkthrough.render | walkthrough.storyboard | marketing.export | marketing.generation | marketing.source_scan | marketing.source_operation
    - `pollAfterMs` number, nullable, required: Wait this long before polling again; null once the state is terminal.
    - `progress` object, nullable, required: HOW FAR THE WORK HAS GOT, as last reported, or null — null while nothing has been recorded yet and null for every terminal state, because a finished job is 100 by definition and a failed one has no bar to draw.
      - `at` string, nullable, required: When it was reported. A reading that has stopped moving means the work has, not that the bar is broken.
      - `percent` number, required: 0 to 100, as last reported for this job. It never goes backwards. Draw exactly this number: nothing here is interpolated and a client that animates between readings is inventing progress.
      - `stage` string, required: A short label for the current step. Show it; do not branch on it.
    - `requestId` string, nullable, required
    - `result` object, nullable, required
      - `artifacts` object[], required
        - `bytes` number, nullable, required
        - `expiresAt` string, date-time, nullable, required
        - `sha256` string, nullable, required
        - `type` string, required
        - `url` string, nullable, required
      - `durationSeconds` number, nullable, required
    - `stage` string, nullable, required
    - `startedAt` string, date-time, nullable, required
    - `state` 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled', required: The five public states. Poll until one of succeeded/failed/cancelled.

## Other responses

- `202`: The work was queued. Poll the resource at `Location`. A retry with the same Idempotency-Key answers this again, with the same body and the same `Location`, plus `Idempotent-Replayed: true`.
- `400`: `validation_failed` — That request is not valid. · `idempotency_key_required` — This operation needs an Idempotency-Key header: a string of up to 128 characters, unique to this request, so a retry cannot do the work twice. · `hint_required` — Say what to show, in a sentence. · `hint_too_long` — That description of what to show is too long. · `url_invalid` — That address is not one this API will fetch. · `url_private` — That address resolves to a private network and will not be fetched. · `url_malformed` — That address could not be read as a URL. · `login_url_invalid` — That login page address is not one this API will fetch. · `login_url_required` — Credentials need the address of the page they sign in on. · `login_origins_invalid` — Additional sign-in addresses must be a short list of https addresses this API will fetch. · `idempotency_key_unscoped` — An idempotency key needs an account to belong to. · `options_invalid` — Those render options are not valid. · `template_unknown` — No such template. The catalogue is at GET /api/v1/catalog/render-options. · `voice_unknown` — No such voice. The catalogue is at GET /api/v1/catalog/voices. · `orientation_unknown` — No such orientation. The catalogue is at GET /api/v1/catalog/render-options. · `capture_unknown` — No such capture shape. The catalogue is at GET /api/v1/catalog/render-options. · `capture_incompatible` — Phone view only makes a portrait video. Pick a portrait orientation or a computer capture. · `avatar_unknown` — No such presenter. The catalogue is at GET /api/v1/catalog/render-options. · `avatar_unavailable` — The presenter circle is not available on this deployment. Make the video without one. · `caption_style_unknown` — No such caption style. The catalogue is at GET /api/v1/catalog/render-options. · `language_unknown` — No such language. The catalogue is at GET /api/v1/catalog/render-options. · `voice_language` — That voice does not speak the chosen language. Pick a voice listed for it. · `background_unknown` — No such background. The catalogue is at GET /api/v1/catalog/render-options. · `length_below_minimum` — That length is shorter than a walkthrough can be. · `site_not_allowed` — This website can't be used: public platforms and sensitive-topic sites aren't allowed. If you think this is a mistake, write to support@gogoscreen.com or use "Talk to a person": support can allow a site by name. · `body_invalid` — Those edits are not valid. · `storyboard_empty` — That storyboard has no beats to render. · `unknown_beat` — One of the beats named is not on that storyboard. · `no_beats` — Every beat is hidden. Keep at least one. · `credentials_required` — That storyboard was planned signed in, so rendering it needs the demo credentials again.
- `401`: `unauthorized` — Authentication is required.
- `402`: `insufficient_seconds` — You do not have enough video time left. Buy more time to keep going.
- `403`: `forbidden_scope` — This credential does not carry the scope this operation needs.
- `404`: `not_found` — No such resource.
- `409`: `idempotency_conflict` — That idempotency key was already used with a different request. · `idempotency_in_progress` — That idempotency key is still being processed. · `conflict` — That request conflicts with the current state. · `too_many_in_flight` — Too many operations are already running on this account. · `not_ready` — That video is not finished yet.
- `410`: `storyboard_expired` — That storyboard has expired. Plan it again; planning is free.
- `413`: `payload_too_large` — That request body is too large.
- `415`: `unsupported_media_type` — That content type is not supported.
- `429`: `rate_limited` — Too many requests. Try again shortly.
- `500`: `internal_error` — Something went wrong. Try again.
- `503`: `queue_unavailable` — That work cannot be queued right now. Try again shortly. · `vault_unavailable` — Credentials cannot be stored right now. Try again shortly. · `wallet_unavailable` — Video time cannot be reserved right now. Try again shortly.

---

[API](https://skmtc.dev/gogoscreen/apis/gogoscreen-api.md) · [All operations](https://skmtc.dev/gogoscreen/apis/gogoscreen-api/llms.txt) · [OpenAPI document](https://skmtc.dev/gogoscreen/apis/gogoscreen-api/revisions/2fd812319d75?raw)
