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

# Create Storyboard Preview

> Generate a video storyboard preview to review scenes, visuals, and settings before final rendering

## Overview

The Storyboard Preview API generates a preview of your video project, allowing you to review the storyboard structure, scene breakdown, visual selections, and configuration before committing to the final render. This is an essential step in the video creation workflow that helps you validate your content and make adjustments without incurring full rendering costs.

<Note>
  The storyboard preview creates a project with scene thumbnails and metadata. To generate the final rendered video, use the [Render from Preview API](/api-reference/videos/render-from-preview) after reviewing and approving the preview.
</Note>

<Tip>
  **Recommended Workflow:** Create Preview → Review Scenes → Make Adjustments → Render Final Video
</Tip>

***

## Render Workflow Options

| Workflow                      | API                                                                      | When to Use                                        |
| ----------------------------- | ------------------------------------------------------------------------ | -------------------------------------------------- |
| **Create Preview**            | **This API**                                                             | Generate preview to review scenes before rendering |
| **Render from Preview**       | [Render from Preview](/api-reference/videos/render-from-preview)         | Render preview as-is without modifications         |
| **Render with Modifications** | [Render Video](/api-reference/videos/render-video)                       | Modify preview elements before rendering           |
| **Render Saved Project**      | [Render Project](/api-reference/videos/render-project)                   | Render existing project created in App or via API  |
| **Direct Render**             | [Render Storyboard Video](/api-reference/videos/render-storyboard-video) | Skip preview, render directly from input           |

***

## Preview vs. Final Render

| Aspect       | Storyboard Preview                            | Final Render             |
| ------------ | --------------------------------------------- | ------------------------ |
| **Purpose**  | Review and validate content                   | Produce final video file |
| **Output**   | Scene thumbnails, metadata, project structure | Full HD video file       |
| **Speed**    | Fast                                          | Slower                   |
| **Cost**     | Lower resource usage                          | Full rendering resources |
| **Editable** | Yes, make changes before render               | Video is final           |
| **Use Case** | Content approval, iteration                   | Final delivery           |

***

## Use Cases

<CardGroup cols={2}>
  <Card title="Content Review" icon="eye">
    Preview how your text will be split into scenes before rendering
  </Card>

  <Card title="Visual Validation" icon="images">
    Review AI-selected visuals and backgrounds for each scene
  </Card>

  <Card title="Scene Adjustment" icon="sliders">
    Identify scenes that need text or visual changes
  </Card>

  <Card title="Approval Workflow" icon="check-circle">
    Share previews with stakeholders before final render
  </Card>

  <Card title="Cost Optimization" icon="coins">
    Validate content before using rendering resources
  </Card>

  <Card title="Iterative Creation" icon="arrows-rotate">
    Quickly iterate on content and settings
  </Card>

  <Card title="Template Testing" icon="flask">
    Test templates and brand settings before production
  </Card>

  <Card title="Batch Preparation" icon="layer-group">
    Prepare multiple video projects for batch rendering
  </Card>
</CardGroup>

***

## API Endpoint

```http theme={null}
POST https://api.pictory.ai/pictoryapis/v2/video/storyboard
```

***

## Request Headers

<ParamField header="Authorization" type="string" required>
  API key for authentication

  ```
  Authorization: YOUR_API_KEY
  ```
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`
</ParamField>

***

## Request Body Parameters

<ParamField body="videoName" type="string" required>
  Name for your video project (alphanumeric, spaces, underscores, and hyphens only, max 150 characters)
</ParamField>

<ParamField body="videoWidth" type="integer">
  Width of the generated video in pixels. Must be provided together with `videoHeight`.
</ParamField>

<ParamField body="videoHeight" type="integer">
  Height of the generated video in pixels. Must be provided together with `videoWidth`.
</ParamField>

<ParamField body="aspectRatio" type="string">
  Video aspect ratio. Options: `1:1`, `16:9`, `9:16`, `4:5`
</ParamField>

<ParamField body="language" type="string">
  Language of the text content.

  **Allowed values:** `zh`, `nl`, `en`, `fr`, `de`, `hi`, `it`, `ja`, `ko`, `mr`, `pt`, `ru`, `es`, `ta`

  `zh` Chinese, `nl` Dutch, `en` English, `fr` French, `de` German, `hi` Hindi, `it` Italian, `ja` Japanese, `ko` Korean, `mr` Marathi, `pt` Portuguese, `ru` Russian, `es` Spanish, `ta` Tamil
</ParamField>

<ParamField body="saveProject" type="boolean">
  Whether to save the project in your Pictory account for later editing. Default: `false`
</ParamField>

<ParamField body="webhook" type="string">
  URL where the completed storyboard preview output will be sent via POST request when finished (max 500 characters)
</ParamField>

<ParamField body="webhookInput" type="object">
  Custom data object that will be included in the webhook POST payload when the job completes. Use this to pass through any metadata (e.g., internal IDs, tracking info) that you need in your webhook handler.

  ```json theme={null}
  {
    "webhookInput": {
      "internalId": "abc-123",
      "source": "campaign-builder"
    }
  }
  ```
</ParamField>

<ParamField body="templateId" type="string">
  ID of a template to use. Get from [Get Templates](/api-reference/templates/get-templates) API.
</ParamField>

<ParamField body="variables" type="object">
  Key-value object for template variables. Only applicable when `templateId` is provided.

  ```json theme={null}
  {
    "variables": {
      "headline": "Welcome to Our Product",
      "subheadline": "Discover Amazing Features",
      "ctaText": "Learn More"
    }
  }
  ```
</ParamField>

<ParamField body="brandId" type="string">
  ID of the brand to apply. Get from [Get Video Brands](/api-reference/branding/get-video-brands) API. Cannot be used with `brandName`.
</ParamField>

<ParamField body="brandName" type="string">
  Name of the brand to apply. Cannot be used with `brandId`.
</ParamField>

<ParamField body="smartLayoutName" type="string">
  Name of the smart layout to apply. Get available layouts from [Get Smart Layouts](/api-reference/smartlayouts/get-smart-layouts) API. Cannot be used with `smartLayoutId`.
</ParamField>

<ParamField body="smartLayoutId" type="string">
  ID of the smart layout to apply. Get from [Get Smart Layouts](/api-reference/smartlayouts/get-smart-layouts) API. Cannot be used with `smartLayoutName`.
</ParamField>

<ParamField body="storyboardVersion" type="string">
  <Warning>**Experimental:** This field is currently experimental. In the future, all storyboards will automatically use the latest version, and this field will be ignored. There is no need to remove it from your requests when that happens.</Warning>

  Specifies which storyboard version to use. Set to `v3` to create a latest Pictory storyboard. Omit this field to use the classic storyboard.

  Options:

  * `v3`: Uses the latest Pictory storyboard
  * Omit or any other value: Uses the classic/legacy storyboard
</ParamField>

<ParamField body="subtitleStyleId" type="string">
  ID of a saved text style for subtitles. Get from [Get Text Styles](/api-reference/branding/get-text-styles) API. Cannot be used with `subtitleStyleName`.
</ParamField>

<ParamField body="subtitleStyleName" type="string">
  Name of a saved text style for subtitles. Cannot be used with `subtitleStyleId`.
</ParamField>

<ParamField body="subtitleStyle" type="object">
  Inline subtitle style configuration. See [subtitleStyle Object](#subtitlestyle-object).
</ParamField>

<ParamField body="awsConnectionId" type="string">
  AWS connection ID for accessing private S3 assets. Get from [Get AWS Connections](/api-reference/aws-integration/get-aws-connections) API.
</ParamField>

<ParamField body="vimeoConnectionId" type="string">
  Vimeo connection ID for uploading videos directly to Vimeo. Get from [Get Vimeo Connections](/api-reference/vimeo-integration/get-vimeo-connections) API.
</ParamField>

<ParamField body="destinations" type="array">
  Array of destination configurations for uploading the generated video (max 5). See [destinations Array](#destinations-array).
</ParamField>

<ParamField body="voiceOver" type="object">
  Voice-over configuration for AI narration. See [voiceOver Object](#voiceover-object).
</ParamField>

<ParamField body="backgroundMusic" type="object">
  Background music configuration for the video. See [backgroundMusic Object](#backgroundmusic-object).
</ParamField>

<ParamField body="logo" type="object">
  Logo overlay configuration. See [logo Object](#logo-object).
</ParamField>

<ParamField body="scenes" type="array" required>
  Array of scene objects containing the content to convert into video. Required unless using `templateId`. See [scenes Array](#scenes-array).
</ParamField>

<ParamField body="avatar" type="object">
  AI avatar configuration for presenter-style videos. See [avatar Object](#avatar-object).
</ParamField>

***

## voiceOver Object

Voice-over configuration for AI narration.

```json theme={null}
{
  "voiceOver": {
    "enabled": true,
    "aiVoices": [
      {
        "speaker": "Brian",
        "speed": 100,
        "amplificationLevel": 0
      }
    ]
  }
}
```

<Note>
  The following fields are nested inside the top-level `voiceOver` object. For example, `voiceOver.enabled` means `enabled` is a property of the `voiceOver` object.
</Note>

<ParamField body="voiceOver.enabled" type="boolean" required>
  Enable or disable voice-over.
</ParamField>

<ParamField body="voiceOver.aiVoices" type="array">
  Array of AI voice configurations (max 10). See [aiVoices Array](#aivoices-array).
</ParamField>

<ParamField body="voiceOver.externalVoice" type="object">
  External voice file configuration. See [externalVoice Object](#externalvoice-object). Cannot be used with `aiVoices`.
</ParamField>

### aiVoices Array

<Note>
  The following fields are nested inside each element of the `voiceOver.aiVoices` array. For example, `voiceOver.aiVoices[].speaker` means `speaker` is a property of each item in the `aiVoices` array, which itself is nested inside the `voiceOver` object. The `[]` notation indicates an array element.
</Note>

<ParamField body="voiceOver.aiVoices[].speaker" type="string" required>
  Voice speaker name (e.g., "Brian", "Emma"). Get available voices from [Get Voiceover Tracks](/api-reference/voiceovers/get-voiceover-tracks) API.
</ParamField>

<ParamField body="voiceOver.aiVoices[].speed" type="number">
  Speech speed from 50 to 200. Default: `100`
</ParamField>

<ParamField body="voiceOver.aiVoices[].amplificationLevel" type="number">
  Volume level from -1 to 1. Default: `0`
</ParamField>

<ParamField body="voiceOver.aiVoices[].premiumVoiceSettings" type="object">
  ElevenLabs premium voice settings. See [premiumVoiceSettings Object](#premiumvoicesettings-object).
</ParamField>

### premiumVoiceSettings Object

```json theme={null}
{
  "premiumVoiceSettings": {
    "modelId": "eleven_multilingual_v2",
    "stability": "50%",
    "similarityBoost": "75%",
    "style": "50%",
    "useSpeakerBoost": true
  }
}
```

<Note>
  The following fields are nested inside `premiumVoiceSettings`, which is a property of each `voiceOver.aiVoices[]` element. For example, `voiceOver.aiVoices[].premiumVoiceSettings.modelId` means `modelId` is inside `premiumVoiceSettings`, inside each voice in the `aiVoices` array, inside the `voiceOver` object.
</Note>

<ParamField body="voiceOver.aiVoices[].premiumVoiceSettings.modelId" type="string">
  ElevenLabs model. Options: `eleven_v3`, `eleven_multilingual_v2`, `eleven_flash_v2_5`, `eleven_turbo_v2_5`, `eleven_turbo_v2`, `eleven_flash_v2`, `eleven_multilingual_v1`, `eleven_monolingual_v1`
</ParamField>

<ParamField body="voiceOver.aiVoices[].premiumVoiceSettings.stability" type="string">
  Voice stability as percentage (e.g., "50%")
</ParamField>

<ParamField body="voiceOver.aiVoices[].premiumVoiceSettings.useSpeakerBoost" type="boolean">
  Enable speaker boost enhancement.
</ParamField>

<ParamField body="voiceOver.aiVoices[].premiumVoiceSettings.similarityBoost" type="string">
  Similarity boost as percentage (e.g., "75%")
</ParamField>

<ParamField body="voiceOver.aiVoices[].premiumVoiceSettings.style" type="string">
  Voice style as percentage (e.g., "50%")
</ParamField>

### externalVoice Object

```json theme={null}
{
  "externalVoice": {
    "voiceUrl": "https://example.com/voiceover.mp3",
    "syncVoice": true,
    "amplificationLevel": 0
  }
}
```

<Note>
  The following fields are nested inside the `voiceOver.externalVoice` object. For example, `voiceOver.externalVoice.voiceUrl` means `voiceUrl` is a property of `externalVoice`, which itself is nested inside the `voiceOver` object.
</Note>

<ParamField body="voiceOver.externalVoice.voiceUrl" type="string" required>
  URL to external voice audio file.
</ParamField>

<ParamField body="voiceOver.externalVoice.syncVoice" type="boolean">
  Auto-synchronize voice with video subtitles.
</ParamField>

<ParamField body="voiceOver.externalVoice.amplificationLevel" type="number">
  Audio amplification level from -1 to 1. Default: `0`
</ParamField>

***

## avatar Object

AI avatar configuration for creating presenter-style videos with lifelike avatars that lip-sync to AI narration.

<Note>
  Avatars require voice-over to be enabled. Use the [Get Avatars](/api-reference/avatars/get-avatars) API to retrieve available `avatarId` values.
</Note>

<ParamField body="avatar.avatarId" type="string" required>
  Unique identifier for the avatar look (e.g., "Annie\_expressive12\_public"). Get from [Get Avatars](/api-reference/avatars/get-avatars) API.
</ParamField>

<ParamField body="avatar.position" type="string">
  Preset position for the avatar. Options: `top-left`, `top-center`, `top-right`, `center-left`, `center-center`, `center-right`, `bottom-left`, `bottom-center`, `bottom-right`

  Default: `bottom-right`
</ParamField>

<ParamField body="avatar.width" type="string">
  Avatar width as percentage (e.g., "20%", "25%", "30%"). Must be an integer percentage from 0% to 100%.

  Default: `"20%"`
</ParamField>

<ParamField body="avatar.borderRadius" type="string">
  Corner rounding. Options: `0` (square), `50` (rounded), `100` (circular)
</ParamField>

<ParamField body="avatar.borderColor" type="string">
  Border color in RGBA format (e.g., "rgba(255,255,255,1)", "rgba(0,0,0,1)", "rgba(132,44,254,1)")
</ParamField>

<ParamField body="avatar.borderThickness" type="number">
  Border width in pixels. Minimum: 0
</ParamField>

<ParamField body="avatar.backgroundColor" type="string">
  Background color in RGBA format (e.g., "rgba(255,255,255,1)", "rgba(0,0,0,0.5)")
</ParamField>

<ParamField body="avatar.hide" type="boolean">
  Hide the avatar globally across all scenes. When `true`, the entire avatar pipeline is skipped. Can be overridden per scene.

  Default: `false`
</ParamField>

<Note>
  Avatar settings can be overridden at the scene level. See [scenes\[\].avatar Object](#scenesavatar-object) for scene-specific customization.
</Note>

***

## backgroundMusic Object

Background music configuration for the video.

```json theme={null}
{
  "backgroundMusic": {
    "enabled": true,
    "autoMusic": true,
    "volume": 0.5
  }
}
```

<Note>
  The following fields are nested inside the top-level `backgroundMusic` object. For example, `backgroundMusic.enabled` means `enabled` is a property of the `backgroundMusic` object.
</Note>

<ParamField body="backgroundMusic.enabled" type="boolean" required>
  Enable or disable background music.
</ParamField>

<ParamField body="backgroundMusic.autoMusic" type="boolean">
  Auto-select background music. Cannot be used with `musicUrl`.
</ParamField>

<ParamField body="backgroundMusic.musicUrl" type="string">
  URL to custom background music file. Cannot be used with `autoMusic`.
</ParamField>

<ParamField body="backgroundMusic.volume" type="number">
  Volume level from 0 to 1. Default: `0.5`
</ParamField>

<ParamField body="backgroundMusic.clips" type="array">
  Time clips to use from the music (max 10). Each clip has `start` and `end` numbers in seconds.

  ```json theme={null}
  {
    "clips": [
      { "start": 0, "end": 30 },
      { "start": 60, "end": 90 }
    ]
  }
  ```
</ParamField>

***

## logo Object

Logo overlay configuration.

```json theme={null}
{
  "logo": {
    "url": "https://example.com/logo.png",
    "position": "top-right",
    "width": "15%"
  }
}
```

<Note>
  The following fields are nested inside the top-level `logo` object. For example, `logo.url` means `url` is a property of the `logo` object.
</Note>

<ParamField body="logo.url" type="string" required>
  URL to logo image file.
</ParamField>

<ParamField body="logo.position" type="string">
  Logo position. Options: `top-left`, `top-right`, `top-center`, `center-left`, `center-center`, `center-right`, `bottom-left`, `bottom-center`, `bottom-right`
</ParamField>

<ParamField body="logo.width" type="string">
  Logo width as percentage (e.g., "15%")
</ParamField>

***

## subtitleStyle Object

Inline subtitle style configuration. Can be used at video level or scene level.

```json theme={null}
{
  "subtitleStyle": {
    "fontFamily": "Montserrat",
    "fontSize": 48,
    "color": "rgba(255,255,255,1)",
    "position": "bottom-center",
    "alignment": "center"
  }
}
```

<Note>
  The following fields are nested inside the `subtitleStyle` object. For example, `subtitleStyle.fontFamily` means `fontFamily` is a property of the `subtitleStyle` object. This object can be used at the top level or inside `scenes[]` as `scenes[].subtitleStyle`.
</Note>

<ParamField body="subtitleStyle.fontUrl" type="string">
  URL to custom font file. When provided, `fontFamily` is required.
</ParamField>

<ParamField body="subtitleStyle.fontFamily" type="string">
  Font family name. Required when `fontUrl` is provided. See [Supported Font Families](#supported-font-families).
</ParamField>

<ParamField body="subtitleStyle.fontSize" type="integer">
  Font size in pixels. Minimum: 1
</ParamField>

<ParamField body="subtitleStyle.color" type="string">
  Text color in RGBA format (e.g., "rgba(255,255,255,1)")
</ParamField>

<ParamField body="subtitleStyle.backgroundColor" type="string">
  Background color in RGBA format (e.g., "rgba(0,0,0,0.5)").
</ParamField>

<ParamField body="subtitleStyle.shadowColor" type="string">
  Shadow color.
</ParamField>

<ParamField body="subtitleStyle.shadowWidth" type="string">
  Shadow width as percentage (e.g., "10%")
</ParamField>

<ParamField body="subtitleStyle.keywordColor" type="string">
  Color for highlighted keywords in RGBA format (e.g., "rgba(255,255,0,1)").
</ParamField>

<ParamField body="subtitleStyle.position" type="string">
  Text position. Options: `top-left`, `top-center`, `top-right`, `center-left`, `center-center`, `center-right`, `bottom-left`, `bottom-center`, `bottom-right`
</ParamField>

<ParamField body="subtitleStyle.alignment" type="string">
  Text alignment. Options: `left`, `center`, `right`
</ParamField>

<ParamField body="subtitleStyle.decorations" type="array">
  Text decorations. Options: `bold`, `underline`, `italics`, `linethrough`

  ```json theme={null}
  {
    "decorations": ["bold", "italics"]
  }
  ```
</ParamField>

<ParamField body="subtitleStyle.case" type="string">
  Text case. Options: `uppercase`, `lowercase`, `capitalize`, `smallcapitalize`
</ParamField>

<ParamField body="subtitleStyle.paragraphWidth" type="string">
  Paragraph width as percentage (e.g., "80%")
</ParamField>

<ParamField body="subtitleStyle.animations" type="array">
  Text animations (max 2: one entry, one exit). See [animations Array](#animations-array).

  ```json theme={null}
  {
    "animations": [
      {
        "name": "fade",
        "type": "entry",
        "speed": "fast",
        "futureWords": "hidden"
      },
      {
        "name": "fade",
        "type": "exit",
        "speed": "fast"
      }
    ]
  }
  ```

  See [Text Animations Guide](/guides/captions/text-animations) for all animation types and examples.
</ParamField>

### animations Array

<Note>
  The following fields are nested inside each element of the `subtitleStyle.animations` array. For example, `subtitleStyle.animations[].name` means `name` is a property of each item in the `animations` array, which itself is nested inside the `subtitleStyle` object. The `[]` notation indicates an array element.
</Note>

<ParamField body="subtitleStyle.animations[].name" type="string" required>
  Animation name. Options: `none`, `fade`, `drift`, `wipe`, `text reveal`, `elastic`, `typewriter`, `blur`, `bulletin`
</ParamField>

<ParamField body="subtitleStyle.animations[].type" type="string" required>
  Animation type. Options: `entry`, `exit`
</ParamField>

<ParamField body="subtitleStyle.animations[].speed" type="string" required>
  Animation speed. Options: `slow`, `medium`, `fast`, `custom`
</ParamField>

<ParamField body="subtitleStyle.animations[].customSpeedValue" type="number">
  Custom speed value (min 0.5). Required when speed is `custom`.
</ParamField>

<ParamField body="subtitleStyle.animations[].direction" type="string">
  Animation direction. Options: `up`, `down`, `left`, `right`
</ParamField>

<ParamField body="subtitleStyle.animations[].writingStyle" type="string">
  Writing style for text animations. Options: `character`, `word`, `line`, `paragraph`
</ParamField>

<ParamField body="subtitleStyle.animations[].futureWords" type="string">
  Controls how upcoming words appear on screen. Only available with `fade` and `blur` entry animations. When AI voiceover is enabled, words sync with the spoken audio.

  Options:

  * `"hidden"`: Upcoming words are invisible, words appear only when spoken
  * `"subtle"`: Upcoming words are faintly visible, current word is highlighted
  * `"prominent"`: All text is clearly visible, spoken word is highlighted brighter

  See [Text Animations Guide](/guides/captions/text-animations) for examples.
</ParamField>

### Supported Font Families

`Anton`, `Archivo Narrow`, `Arial`, `Averia Libre`, `Barlow`, `Barlow Black`, `Bebas Neue`, `Calibri`, `Caprasimo`, `Capriola`, `Carter One`, `Caveat`, `Chakra Petch`, `Chewy`, `Comfortaa`, `Courier Prime`, `Dancing Script`, `Dangrek`, `Delius Unicase`, `DM Sans`, `Grandstander`, `Gruppo`, `Heartbeat`, `Helvetica`, `Helvetica Neue Medium`, `JM Modern`, `Josefin Sans`, `Julius Sans One`, `Laisha`, `Lato`, `Lato Extrabold`, `Lexend`, `LT Wave`, `Manrope`, `Merriweather`, `Montserrat`, `Moon dance`, `Mustard`, `Notosans`, `Opensans`, `Optik`, `Party Confetti`, `Patua One`, `Playfair Display`, `Plus Jakarta Sans`, `Poppins`, `Poppins Extrabold`, `Proxima Nova`, `Quicksand`, `Raleway`, `Raleway Black`, `Raleway Thin`, `Roboto`, `Rokkitt`, `Rowdies`, `Russo One`, `Satisfy`, `Sora`, `Source Sans Pro`, `Space Grotesk`, `Space mono`, `Special Elite`, `Strive`, `Titillium Web`, `Titillium Web Black`, `Ubuntu`, `Unbounded`, `Work Sans`, `Noto Sans JP`, `Noto Serif JP`, `Noto Sans Tamil`, `Noto Sans Devanagari`, `Noto Serif Devanagari`

***

## destinations Array

Array of destination configurations for uploading the generated video (max 5).

### Vimeo Destination

```json theme={null}
{
  "destinations": [
    {
      "type": "vimeo",
      "folder_uri": "/users/12345/projects/67890",
      "content_rating": ["safe"],
      "privacy": {
        "view": "unlisted",
        "embed": "public",
        "download": false
      }
    }
  ]
}
```

<Note>
  The following fields are nested inside each element of the top-level `destinations` array. For example, `destinations[].type` means `type` is a property of each item in the `destinations` array. The `[]` notation indicates an array element.
</Note>

<ParamField body="destinations[].type" type="string" required>
  Must be `vimeo`
</ParamField>

<ParamField body="destinations[].folder_uri" type="string">
  Vimeo folder URI.
</ParamField>

<ParamField body="destinations[].content_rating" type="array">
  Content rating. Options: `violence`, `drugs`, `language`, `nudity`, `advertisement`, `safe`, `unrated`

  ```json theme={null}
  {
    "content_rating": ["safe"]
  }
  ```
</ParamField>

<ParamField body="destinations[].privacy" type="object">
  Privacy settings. See [Vimeo Privacy Object](#vimeo-privacy-object).
</ParamField>

### Vimeo Privacy Object

<Note>
  The following fields are nested inside the `privacy` object of each `destinations[]` element. For example, `destinations[].privacy.view` means `view` is a property of `privacy`, which itself is nested inside each item of the `destinations` array.
</Note>

<ParamField body="destinations[].privacy.view" type="string">
  View access. Options: `anybody`, `contacts`, `disable`, `nobody`, `password`, `unlisted`, `users`
</ParamField>

<ParamField body="destinations[].privacy.embed" type="string">
  Embed access. Options: `private`, `public`, `whitelist`
</ParamField>

<ParamField body="destinations[].privacy.comments" type="string">
  Comment access. Options: `anybody`, `contacts`, `nobody`
</ParamField>

<ParamField body="destinations[].privacy.add" type="boolean">
  Allow adding to albums/channels.
</ParamField>

<ParamField body="destinations[].privacy.download" type="boolean">
  Allow downloads.
</ParamField>

***

## scenes Array

Each scene in the `scenes` array can contain various content sources and settings.

```json theme={null}
{
  "scenes": [
    {
      "story": "Welcome to our product showcase. Discover amazing features.",
      "createSceneOnEndOfSentence": true,
      "highlightKeywords": true,
      "sceneTransition": "fade",
      "background": {
        "visualUrl": "https://example.com/background.mp4",
        "type": "video",
        "settings": {
          "mute": true,
          "loop": true
        }
      }
    }
  ]
}
```

<Warning>
  Each scene can only have ONE content source. Choose one of: `story`, `storyCoPilot`, `blogUrl`, `pptUrl`, `audioUrl`, or `videoUrl`.
</Warning>

<Note>
  The following fields are nested inside each element of the top-level `scenes` array. For example, `scenes[].story` means `story` is a property of each item in the `scenes` array. The `[]` notation indicates an array element.
</Note>

<ParamField body="scenes[].story" type="string">
  Text content for creating video from text (max 15000 characters).
</ParamField>

<ParamField body="scenes[].storyCoPilot" type="object">
  AI story generation configuration. See [storyCoPilot Object](#storycopilot-object).
</ParamField>

<ParamField body="scenes[].blogUrl" type="string">
  URL to blog/article content.
</ParamField>

<ParamField body="scenes[].pptUrl" type="string">
  URL to PowerPoint presentation file.
</ParamField>

<ParamField body="scenes[].audioUrl" type="string">
  URL to audio file for audio-to-video conversion. Requires `audioLanguage`.
</ParamField>

<ParamField body="scenes[].videoUrl" type="string">
  URL to video file for video repurposing. Requires `audioLanguage`.
</ParamField>

<ParamField body="scenes[].createSceneOnNewLine" type="boolean">
  Create new scene on each new line. Default: `false`
</ParamField>

<ParamField body="scenes[].createSceneOnEndOfSentence" type="boolean">
  Create new scene at end of each sentence. Default: `false`
</ParamField>

<ParamField body="scenes[].maxSubtitleLines" type="integer">
  Maximum number of caption lines displayed simultaneously. Integer from `1` to `4`. When omitted, all caption lines for the scene are displayed at once.

  * `1`: Single line (ideal for TikTok/Reels)
  * `2`: Two lines (standard for most content)
  * `3`: Three lines (educational/detailed content)
  * `4`: Four lines (information-heavy content)

  Cannot be used with smart layouts (`smartLayoutId` or `smartLayoutName`). When AI voiceover is enabled, caption lines sync with the spoken audio. See [Dynamic Captions Guide](/guides/captions/dynamic-captions).
</ParamField>

<ParamField body="scenes[].highlightKeywords" type="boolean">
  Highlight keywords in subtitles.
</ParamField>

<ParamField body="scenes[].hideSubtitles" type="boolean">
  Hide subtitles for this scene.
</ParamField>

<ParamField body="scenes[].minimumDuration" type="number">
  Minimum duration for the scene in seconds.
</ParamField>

<ParamField body="scenes[].endPauseDuration" type="number">
  Pause duration at the end of the scene in seconds.
</ParamField>

<ParamField body="scenes[].sceneTransition" type="string">
  Transition effect. Options: `none`, `wipeup`, `wipedown`, `wipeleft`, `wiperight`, `smoothleft`, `smoothright`, `radial`, `circlecrop`, `hblur`, `fade`
</ParamField>

<ParamField body="scenes[].audioLanguage" type="string">
  Language of audio content. Required for `audioUrl` and `videoUrl`.

  **Allowed values:** `en-US`, `en-AU`, `en-GB`, `en-IN`, `en-IE`, `en-AB`, `en-WL`, `fr-CA`, `fr-FR`, `de-CH`, `de-DE`, `it-IT`, `es-ES`, `es-US`, `nl-NL`, `pt-BR`, `ja-JP`, `ko-KR`, `ru-RU`, `hi-IN`, `ta-IN`, `mr-IN`

  `en-US` English (US), `en-AU` English (Australia), `en-GB` English (UK), `en-IN` English (India), `en-IE` English (Ireland), `en-AB` English (Arabic accent), `en-WL` English (Wales), `fr-CA` French (Canada), `fr-FR` French (France), `de-CH` German (Switzerland), `de-DE` German (Germany), `it-IT` Italian (Italy), `es-ES` Spanish (Spain), `es-US` Spanish (US), `nl-NL` Dutch (Netherlands), `pt-BR` Portuguese (Brazil), `ja-JP` Japanese (Japan), `ko-KR` Korean (Korea), `ru-RU` Russian (Russia), `hi-IN` Hindi (India), `ta-IN` Tamil (India), `mr-IN` Marathi (India)
</ParamField>

<ParamField body="scenes[].useSpeakerNotes" type="boolean">
  Use speaker notes from PowerPoint. Only valid with `pptUrl`.
</ParamField>

<ParamField body="scenes[].animatePPT" type="boolean">
  Enable AI-generated slide animations for PowerPoint presentations. When `true`, the AI analyzes each slide and generates motion graphics animations (zoom, pan, fade effects) that bring static slides to life. Only valid with `pptUrl`.
</ParamField>

<ParamField body="scenes[].isSSMLStory" type="boolean">
  Whether story text contains SSML markup. Only valid with `story`. Default: `false`
</ParamField>

<ParamField body="scenes[].caption" type="string">
  Separate caption text for the scene (max 3000 characters). Requires `story`.
</ParamField>

<ParamField body="scenes[].captionLanguage" type="string">
  Language of caption text. Only valid with `caption`.

  **Allowed values:** `zh`, `nl`, `en`, `fr`, `de`, `hi`, `it`, `ja`, `ko`, `mr`, `pt`, `ru`, `es`, `ta`

  `zh` Chinese, `nl` Dutch, `en` English, `fr` French, `de` German, `hi` Hindi, `it` Italian, `ja` Japanese, `ko` Korean, `mr` Marathi, `pt` Portuguese, `ru` Russian, `es` Spanish, `ta` Tamil
</ParamField>

<ParamField body="scenes[].subtitleStyleId" type="string">
  ID of a saved text style for this scene's subtitles. Cannot be used with `subtitleStyleName`.
</ParamField>

<ParamField body="scenes[].subtitleStyleName" type="string">
  Name of a saved text style for this scene's subtitles. Cannot be used with `subtitleStyleId`.
</ParamField>

<ParamField body="scenes[].subtitleStyle" type="object">
  Inline subtitle style for this scene. Overrides video-level subtitle style. See [subtitleStyle Object](#subtitlestyle-object).
</ParamField>

<ParamField body="scenes[].voiceOver" type="object">
  Voice-over configuration specific to this scene. Overrides video-level settings. See [scenes\[\].voiceOver Object](#scenesvoiceover-object).
</ParamField>

<ParamField body="scenes[].backgroundMusic" type="object">
  Background music configuration specific to this scene. See [scenes\[\].backgroundMusic Object](#scenesbackgroundmusic-object).
</ParamField>

<ParamField body="scenes[].avatar" type="object">
  Avatar customization specific to this scene. Overrides global avatar settings. See [scenes\[\].avatar Object](#scenesavatar-object).
</ParamField>

<ParamField body="scenes[].background" type="object">
  Background media configuration for this scene. See [background Object](#background-object).
</ParamField>

<ParamField body="scenes[].backgroundBrolls" type="array">
  Array of B-roll background configurations. See [backgroundBrolls Array](#backgroundbrolls-array).
</ParamField>

<ParamField body="scenes[].backgroundCorpus" type="array">
  Array of background images to use as a corpus (max 100). See [backgroundCorpus Array](#backgroundcorpus-array).
</ParamField>

<ParamField body="scenes[].transcript" type="array">
  Transcription of input video or audio. Required when repurposing `audioUrl` or `videoUrl`. See [transcript Array](#transcript-array).
</ParamField>

<ParamField body="scenes[].mediaRepurposeSettings" type="object">
  Settings for repurposing media content. Only valid with `audioUrl` or `videoUrl`. See [mediaRepurposeSettings Object](#mediarepurposesettings-object).
</ParamField>

<ParamField body="scenes[].templateOverride" type="object">
  Configuration for manipulating template scenes. Only available when `templateId` is provided. See [templateOverride Object](#templateoverride-object).
</ParamField>

<ParamField body="scenes[].elements" type="array">
  Overlay elements placed on top of the scene background (max 20 per scene). Each element has a `type` of `shape`, `text`, `video`, or `image`. See [elements Array](#elements-array).
</ParamField>

***

## storyCoPilot Object

AI story generation configuration for creating video scripts automatically.

```json theme={null}
{
  "storyCoPilot": {
    "prompt": "How AI is transforming video creation",
    "videoType": "Explainer",
    "duration": 60,
    "platform": "YouTube",
    "tone": "informative"
  }
}
```

<Note>
  The following fields are nested inside the `storyCoPilot` object, which is a property of each `scenes[]` element. For example, `scenes[].storyCoPilot.prompt` means `prompt` is a property of `storyCoPilot`, which itself is nested inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].storyCoPilot.prompt" type="string" required>
  Topic or description for AI to generate content (1-5000 characters).
</ParamField>

<ParamField body="scenes[].storyCoPilot.videoType" type="string">
  Type of video to generate. Options: `Explainer`, `Marketing`, `Internal Communication`, `Tutorial`, `Product`. Default: `Explainer`
</ParamField>

<ParamField body="scenes[].storyCoPilot.duration" type="integer">
  Target duration in seconds (1-600).
</ParamField>

<ParamField body="scenes[].storyCoPilot.platform" type="string">
  Target platform. Options: `YouTube`, `TikTok`, `Instagram`, `Facebook`, `LinkedIn`, `Twitter`
</ParamField>

<ParamField body="scenes[].storyCoPilot.tone" type="string">
  Tone of the generated content. Options: `professional`, `casual`, `friendly`, `informative`, `persuasive`, `exciting`, `educational`, `humorous`, `serious`, `conversational`
</ParamField>

***

## scenes\[].voiceOver Object

Voice-over configuration specific to a scene. Overrides video-level voice-over settings.

```json theme={null}
{
  "voiceOver": {
    "enabled": true,
    "aiVoices": [{ "speaker": "Emma", "speed": 100 }]
  }
}
```

<Note>
  The following fields are nested inside the `voiceOver` object at the scene level. For example, `scenes[].voiceOver.enabled` means `enabled` is a property of `voiceOver`, which itself is nested inside each item of the `scenes` array. This is separate from the top-level `voiceOver` object.
</Note>

<ParamField body="scenes[].voiceOver.enabled" type="boolean" required>
  Enable or disable voice-over for this scene.
</ParamField>

<ParamField body="scenes[].voiceOver.aiVoices" type="array">
  Array of AI voice configurations (max 10). Same structure as [aiVoices Array](#aivoices-array).
</ParamField>

<ParamField body="scenes[].voiceOver.externalVoice" type="object">
  External voice configuration with `voiceUrl`, `clips` array, and `amplificationLevel`.
</ParamField>

***

## scenes\[].backgroundMusic Object

Background music configuration specific to a scene.

```json theme={null}
{
  "backgroundMusic": {
    "enabled": true
  }
}
```

<Note>
  The following fields are nested inside the `backgroundMusic` object at the scene level. For example, `scenes[].backgroundMusic.enabled` means `enabled` is a property of `backgroundMusic`, which itself is nested inside each item of the `scenes` array. This is separate from the top-level `backgroundMusic` object.
</Note>

<ParamField body="scenes[].backgroundMusic.enabled" type="boolean" required>
  Enable or disable background music for this scene.
</ParamField>

***

## scenes\[].avatar Object

Scene-level avatar customization. Overrides global [avatar Object](#avatar-object) settings for this specific scene.

<Note>
  Scene-level settings override global avatar configuration. Any property not specified at the scene level inherits from the global avatar settings.
</Note>

```json theme={null}
{
  "avatar": {
    "position": "top-left",
    "width": "25%",
    "hide": false
  }
}
```

<ParamField body="scenes[].avatar.position" type="string">
  Preset position for the avatar in this scene. Options: `top-left`, `top-center`, `top-right`, `center-left`, `center-center`, `center-right`, `bottom-left`, `bottom-center`, `bottom-right`
</ParamField>

<ParamField body="scenes[].avatar.top" type="string">
  Distance from top edge as percentage (e.g., "10%", "25%", "50%"). Integer percentages only (0%-100%). Cannot be used with `position`.
</ParamField>

<ParamField body="scenes[].avatar.left" type="string">
  Distance from left edge as percentage (e.g., "5%", "50%", "80%"). Integer percentages only (0%-100%). Cannot be used with `position`.
</ParamField>

<ParamField body="scenes[].avatar.width" type="string">
  Avatar width as percentage for this scene (e.g., "20%", "25%", "30%"). Must be an integer percentage from 0% to 100%.
</ParamField>

<ParamField body="scenes[].avatar.borderRadius" type="string">
  Corner rounding for this scene. Options: `0` (square), `50` (rounded), `100` (circular)
</ParamField>

<ParamField body="scenes[].avatar.borderColor" type="string">
  Border color in RGBA format for this scene (e.g., "rgba(255,255,255,1)", "rgba(0,0,0,1)", "rgba(132,44,254,1)")
</ParamField>

<ParamField body="scenes[].avatar.borderThickness" type="number">
  Border width in pixels for this scene. Minimum: 0
</ParamField>

<ParamField body="scenes[].avatar.backgroundColor" type="string">
  Background color in RGBA format for this scene (e.g., "rgba(255,255,255,1)", "rgba(0,0,0,0.5)")
</ParamField>

<ParamField body="scenes[].avatar.hide" type="boolean">
  Hide avatar for this specific scene (`true` or `false`)
</ParamField>

<Warning>
  **Important:** You cannot change `avatarId` at the scene level. The same avatar must be used throughout the video. You can only override styling and positioning properties.
</Warning>

***

## background Object

Background media configuration for a scene.

```json theme={null}
{
  "background": {
    "visualUrl": "https://example.com/video.mp4",
    "type": "video",
    "settings": {
      "mute": true,
      "loop": true
    }
  }
}
```

<Warning>
  Background can only have ONE of: `visualUrl`, `color`, or `aiVisual` - not multiple.
</Warning>

<Note>
  The following fields are nested inside the `background` object, which is a property of each `scenes[]` element. For example, `scenes[].background.visualUrl` means `visualUrl` is a property of `background`, which itself is nested inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].background.visualUrl" type="string">
  URL to background video or image. Cannot be used with `color` or `aiVisual`.
</ParamField>

<ParamField body="scenes[].background.color" type="string">
  Solid background color in RGB, RGBA, or hex format (e.g., "rgb(0,0,0)", "rgba(0,0,0,1)", "#000000"). Cannot be used with `visualUrl` or `aiVisual`.
</ParamField>

<ParamField body="scenes[].background.aiVisual" type="object">
  AI-generated visual configuration. Cannot be used with `visualUrl` or `color`. See [aiVisual Object](#aivisual-object).
</ParamField>

<ParamField body="scenes[].background.type" type="string">
  Media type. Options: `video`, `image`. **Required** when `aiVisual` is provided. It determines whether an AI image or AI video clip is generated.
</ParamField>

<ParamField body="scenes[].background.searchFilter" type="object">
  Search filter for auto-selecting visuals. See [searchFilter Object](#searchfilter-object).
</ParamField>

<ParamField body="scenes[].background.clips" type="array">
  Time clips to use from background video. Only valid when `type` is `video` and `visualUrl` is provided. Each clip has `start` and `end` numbers in seconds.

  ```json theme={null}
  {
    "clips": [
      { "start": 0, "end": 10 },
      { "start": 20, "end": 35 }
    ]
  }
  ```
</ParamField>

<ParamField body="scenes[].background.settings" type="object">
  Background playback settings. See [background.settings Object](#backgroundsettings-object).
</ParamField>

<ParamField body="scenes[].background.colorOverlay" type="object">
  Semi-transparent color tint rendered on top of the background. Works with every background source, including solid colors. See [colorOverlay Object](#coloroverlay-object) and the [Background Color Overlay guide](/guides/advanced-features/color-overlay).
</ParamField>

### aiVisual Object

AI-generated visual configuration. Use with `background.type` set to `"image"` for AI-generated images or `"video"` for AI-generated video clips.

<Note>
  The following fields are nested inside the `aiVisual` object, which is a property of `scenes[].background`. For example, `scenes[].background.aiVisual.prompt` means `prompt` is a property of `aiVisual`, which itself is nested inside `background`, inside each item of the `scenes` array.
</Note>

<Tabs>
  <Tab title="AI Image Example">
    ```json theme={null}
    {
      "background": {
        "type": "image",
        "aiVisual": {
          "prompt": "A serene mountain landscape at sunset",
          "model": "seedream3.0",
          "mediaStyle": "photorealistic"
        }
      }
    }
    ```
  </Tab>

  <Tab title="AI Video Clip Example">
    ```json theme={null}
    {
      "background": {
        "type": "video",
        "aiVisual": {
          "prompt": "Aerial drone shot slowly flying over a tropical coastline",
          "model": "pixverse5.5",
          "videoDuration": "8s"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Video with First Frame">
    ```json theme={null}
    {
      "background": {
        "type": "video",
        "aiVisual": {
          "prompt": "A car driving through a desert highway at golden hour",
          "model": "pixverse5.5",
          "videoDuration": "8s",
          "firstFrameImageUrl": "https://example.com/car-on-highway.jpg"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Image with Reference">
    ```json theme={null}
    {
      "background": {
        "type": "image",
        "aiVisual": {
          "prompt": "A modern office workspace with natural lighting",
          "model": "seedream3.0",
          "mediaStyle": "photorealistic",
          "referenceImageUrl": "https://example.com/office-reference.jpg"
        }
      }
    }
    ```
  </Tab>

  <Tab title="Visual Continuity">
    ```json theme={null}
    {
      "scenes": [
        {
          "story": "AI is poised to significantly impact educators and course creators on social media. By automating tasks like content generation, visual design, and video editing, AI will save time and enhance consistency. This allows creators to focus on higher-level strategies and ensures a cohesive brand presence.",
          "createSceneOnNewLine": true,
          "createSceneOnEndOfSentence": true
          "background": {
            "type": "video",
            "aiVisual": {
              "model": "pixverse5.5",
              "visualContinuity": true
            }
          }
        }
      ]
    }
    ```
  </Tab>
</Tabs>

<ParamField body="scenes[].background.aiVisual.prompt" type="string">
  Text prompt describing the visual to generate (max 500 characters). If omitted, the system auto-generates a prompt from the scene's story text.

  When a story is split into multiple scenes (using `createSceneOnEndOfSentence` or `createSceneOnNewLine`), this prompt acts as a **creative direction** for the entire video rather than a prompt for a specific scene. The system uses it to guide the auto-generated prompts for each individual scene, ensuring a consistent visual tone. A good creative direction prompt follows this structure: \[Action/Movement] + \[Scene/Environment] + \[Camera Technique] + \[Visual Style]. For example: `"Smooth cinematic tracking shots in modern creative workspaces with warm golden-hour lighting and shallow depth of field"`.
</ParamField>

<ParamField body="scenes[].background.aiVisual.model" type="string" required>
  AI model to use. The valid options depend on `background.type`:

  **Image models** (when `type` is `"image"`): `flux-schnell`, `seedream3.0`, `nanobanana`, `nanobanana-pro`

  **Video models** (when `type` is `"video"`): `pixverse5.5`, `veo3.1_fast`, `veo3.1`
</ParamField>

<ParamField body="scenes[].background.aiVisual.mediaStyle" type="string">
  Visual style for generated images. Only applicable when `type` is `"image"`. Options: `photorealistic`, `artistic`, `cartoon`, `minimalist`, `vintage`, `futuristic`
</ParamField>

<ParamField body="scenes[].background.aiVisual.videoDuration" type="string">
  Duration of the generated video clip. Only applicable when `type` is `"video"`. Valid values depend on the model:

  * `pixverse5.5`: `"5s"`, `"8s"`, `"10s"` (default: `"5s"`)
  * `veo3.1_fast`: `"4s"`, `"6s"`, `"8s"` (default: `"4s"`)
  * `veo3.1`: `"4s"`, `"6s"`, `"8s"` (default: `"4s"`)

  If omitted or invalid, the model's shortest duration is used.
</ParamField>

<ParamField body="scenes[].background.aiVisual.visualContinuity" type="boolean">
  When set to `true`, enables visual continuity between consecutive AI-generated scenes. The system automatically uses the output of the previous scene as a reference for the next scene, creating smooth visual transitions. For video scenes, the last frame of the previous video is used. For image scenes, the generated image of the previous scene is used. This field works with both `"video"` and `"image"` types.

  Visual continuity applies in two scenarios:

  * **Within the same story:** Consecutive scenes that were split from the same original story use the previous scene's output as a reference for the next scene.
  * **Across consecutive stories:** Continuity is also maintained between the last scene of one story and the first scene of the next story, enabling seamless transitions across story boundaries.

  In both cases, `visualContinuity` must be set to `true` for the system to use the previous scene's output as a reference. If `visualContinuity` is not set or is `false`, the following behavior applies for consecutive scenes from the same story:

  * **Image scenes:** All user-provided reference images (such as `referenceImageUrl`) are cleared, and visuals are generated independently.
  * **Video scenes:** Only `firstFrameImageUrl` is cleared if it was provided. However, `referenceImageUrls` are preserved and still used for generation.

  <Note>
    This field has no effect on the first scene in a sequence. When continuity is active and the previous scene's output is unavailable, the system falls back to generating the visual without a reference image.
  </Note>
</ParamField>

<ParamField body="scenes[].background.aiVisual.firstFrameImageUrl" type="string">
  URL of an image to use as the first frame of the generated video clip. The AI model generates a video that begins from this image and transitions into the content described in the prompt. Only applicable when `type` is `"video"`. Cannot be used together with `referenceImageUrls`.
</ParamField>

<ParamField body="scenes[].background.aiVisual.referenceImageUrl" type="string">
  URL of a reference image to guide the style and composition of the generated image. Only applicable when `type` is `"image"`. For video generation, use `firstFrameImageUrl` or `referenceImageUrls` instead.
</ParamField>

<ParamField body="scenes[].background.aiVisual.referenceImageUrls" type="string[]">
  An array of 1–2 reference image URLs to guide the style and composition of the generated video clip. Only applicable when `type` is `"video"`. Cannot be used together with `firstFrameImageUrl`. For image generation, use `referenceImageUrl` instead.

  <Warning>
    When using `referenceImageUrls` (without `firstFrameImageUrl`) with the `veo3.1` or `veo3.1_fast` models, the video duration is automatically set to `"8s"`.
  </Warning>
</ParamField>

#### Reference Image Fields: Quick Reference

| Field                | Applicable Type | Description                                             |
| -------------------- | --------------- | ------------------------------------------------------- |
| `firstFrameImageUrl` | `"video"` only  | Image used as the starting frame of the generated video |
| `referenceImageUrl`  | `"image"` only  | Single reference image for AI image generation          |
| `referenceImageUrls` | `"video"` only  | 1–2 reference images for AI video generation            |

<Warning>
  **Mutual exclusivity rules:**

  * `firstFrameImageUrl` and `referenceImageUrls` cannot be provided together. Use one or the other.
  * `referenceImageUrl` is only for image generation. For video generation, use `firstFrameImageUrl` or `referenceImageUrls`.
  * `firstFrameImageUrl` and `referenceImageUrls` are only for video generation. For image generation, use `referenceImageUrl`.
</Warning>

#### Image Models: AI Credit Cost

| Model            | AI Credits (per image) | Best For                      |
| ---------------- | ---------------------- | ----------------------------- |
| `flux-schnell`   | 0.6                    | Reliable for basic layouts    |
| `seedream3.0`    | 2                      | Reliable for text and numbers |
| `nanobanana`     | 4                      | Excels at details             |
| `nanobanana-pro` | 14                     | Superior cinematic quality    |

#### Video Models: AI Credit Cost

Credits are charged **per second** of video generated.

| Model         | AI Credits (per second) | Best For                    |
| ------------- | ----------------------- | --------------------------- |
| `pixverse5.5` | 1.6                     | Reliable for basic motion   |
| `veo3.1_fast` | 10                      | Efficient cinematic quality |
| `veo3.1`      | 20                      | Superior cinematic quality  |

<Tip>
  For detailed guides on configuring AI-generated visuals, see:

  * [AI-Generated Scene Background Images](/guides/ai-generated-visuals/background-images)
  * [AI-Generated Scene Background Video Clips](/guides/ai-generated-visuals/background-videos)
</Tip>

### searchFilter Object

```json theme={null}
{
  "searchFilter": {
    "category": "Nature/Landscapes",
    "query": "mountain sunset",
    "keywords": ["nature", "mountains", "sunset"],
    "libraries": ["story_blocks", "getty"]
  }
}
```

<Note>
  The following fields are nested inside the `searchFilter` object, which is a property of `scenes[].background`. For example, `scenes[].background.searchFilter.category` means `category` is a property of `searchFilter`, which itself is nested inside `background`, inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].background.searchFilter.category" type="string">
  Category filter for media search. See [Visual Filter Categories](#visual-filter-categories).
</ParamField>

<ParamField body="scenes[].background.searchFilter.query" type="string">
  Custom search query to find relevant visuals for your scene (max 3000 characters). Use descriptive terms to get more accurate background media results (e.g., "business team collaborating in modern office", "aerial view of city skyline at sunset").
</ParamField>

<ParamField body="scenes[].background.searchFilter.keywords" type="array">
  Keywords for search (max 10, each 2-100 characters).

  ```json theme={null}
  {
    "keywords": ["business", "technology", "innovation"]
  }
  ```
</ParamField>

<ParamField body="scenes[].background.searchFilter.libraries" type="array">
  Media libraries to search. Options: `story_blocks`, `getty`

  ```json theme={null}
  {
    "libraries": ["story_blocks", "getty"]
  }
  ```
</ParamField>

### background.settings Object

```json theme={null}
{
  "settings": {
    "mute": true,
    "loop": true,
    "zoomAndPan": false
  }
}
```

<Note>
  The following fields are nested inside the `settings` object, which is a property of `scenes[].background`. For example, `scenes[].background.settings.mute` means `mute` is a property of `settings`, which itself is nested inside `background`, inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].background.settings.mute" type="boolean">
  Mute audio from background media.
</ParamField>

<ParamField body="scenes[].background.settings.loop" type="boolean">
  Loop the background media.
</ParamField>

<ParamField body="scenes[].background.settings.zoomAndPan" type="boolean">
  Apply zoom and pan effects. Cannot be used with `kenBurnsEffect`.
</ParamField>

<ParamField body="scenes[].background.settings.kenBurnsEffect" type="boolean">
  Apply Ken Burns effect (images only). Cannot be used with `zoomAndPan`.
</ParamField>

### colorOverlay Object

A semi-transparent color tint rendered on top of the background, commonly used to keep subtitles readable on busy footage or to apply a brand color across scenes. The underlying media is not modified.

```json theme={null}
{
  "background": {
    "searchFilter": { "keywords": ["city skyline", "night"] },
    "type": "video",
    "colorOverlay": {
      "color": "rgb(26, 26, 46)",
      "opacity": 0.4
    }
  }
}
```

<Note>
  The following fields are nested inside the `colorOverlay` object, which is a property of `scenes[].background`. For example, `scenes[].background.colorOverlay.color` means `color` is a property of `colorOverlay`, which itself is nested inside `background`, inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].background.colorOverlay.color" type="string" required>
  The tint color in RGB, RGBA, or hex format. If an RGBA value is provided, its alpha channel is ignored; transparency is controlled only by `opacity`.
</ParamField>

<ParamField body="scenes[].background.colorOverlay.opacity" type="number" default="0.4">
  Tint strength from `0` (invisible) to `1` (solid). Defaults to `0.4`.
</ParamField>

<Note>
  `colorOverlay` is also supported on each `backgroundBrolls[]` item (a B-roll's own overlay takes precedence while it is on screen) and on `video`/`image` items in the scene [elements Array](#elements-array). Scenes using `colorOverlay` are processed by the v3 storyboard engine automatically.
</Note>

### Visual Filter Categories

<Accordion title="Available Categories">
  **Aerial:** `Aerial`, `Aerial/Coastal_and_Marine`, `Aerial/Infrastructure`, `Aerial/Natural_Landscapes`, `Aerial/Urban_Landscapes`

  **Animals:** `Animals`, `Animals/Farm_Animals`, `Animals/Marine_Life`, `Animals/Pets`, `Animals/Wildlife`

  **Business:** `Business_and_Professions`, `Business_and_Professions/Business_Concepts`, `Business_and_Professions/Office_Work`, `Business_and_Professions/Professions`

  **Effects:** `Effects`, `Effects/Chemical_Reactions`, `Effects/Explosions`, `Effects/Fire_and_Smoke`, `Effects/Glitches`, `Effects/Lighting_Effects`, `Effects/Particles`

  **Food:** `Food_and_Beverage`, `Food_and_Beverage/Beverages`, `Food_and_Beverage/Food_Preparation`, `Food_and_Beverage/Meals`

  **Graphics:** `Graphics`, `Graphics/Backgrounds`, `Graphics/Effects`, `Graphics/Patterns`

  **Historical:** `Historical`, `Historical/Eras`, `Historical/Events`, `Historical/Figures`

  **Holidays:** `Holidays_and_Celebrations`, `Holidays_and_Celebrations/Cultural_Celebrations`, `Holidays_and_Celebrations/Festivals`, `Holidays_and_Celebrations/Life_Events`

  **Lifestyle:** `Lifestyle`, `Lifestyle/Health_and_Fitness`, `Lifestyle/Hobbies`, `Lifestyle/Home_and_Family`

  **Medical:** `Medical`

  **Nature:** `Nature`, `Nature/Landscapes`, `Nature/Plants_and_Trees`, `Nature/Sunrises_and_Sunsets`, `Nature/Waterfalls`, `Nature/Weather`

  **People:** `People`, `People/Activities`, `People/Groups`, `People/Portraits`

  **Places:** `Places_and_Landmarks`, `Places_and_Landmarks/Rural_Areas`, `Places_and_Landmarks/Tourist_Attractions`, `Places_and_Landmarks/Urban_Areas`

  **Sports:** `Sports_and_Recreation`, `Sports_and_Recreation/Individual_Sports`, `Sports_and_Recreation/Outdoor_Activities`, `Sports_and_Recreation/Team_Sports`

  **Technology:** `Technology`, `Technology/Devices`, `Technology/Innovation`
</Accordion>

***

## backgroundBrolls Array

Array of B-roll background configurations for creating dynamic scene transitions.

```json theme={null}
{
  "backgroundBrolls": [
    {
      "visualUrl": "https://example.com/broll.mp4",
      "type": "video",
      "brollClip": { "start": 0, "end": 5 },
      "settings": { "mute": true }
    }
  ]
}
```

Each B-roll item supports all [background Object](#background-object) properties plus:

<Note>
  The following fields are nested inside each element of the `scenes[].backgroundBrolls` array. For example, `scenes[].backgroundBrolls[].brollClip` means `brollClip` is a property of each item in the `backgroundBrolls` array, which itself is nested inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].backgroundBrolls[].brollClip" type="object">
  Time clip configuration for B-roll. Contains `start` (number, required) and `end` (number, required) in seconds.
</ParamField>

***

## backgroundCorpus Array

Array of background images to use as a corpus for the scene (max 100 items).

```json theme={null}
{
  "backgroundCorpus": [
    { "visualUrl": "https://example.com/image1.jpg", "type": "image", "prefer": true },
    { "visualUrl": "https://example.com/image2.jpg", "type": "image" }
  ]
}
```

<Note>
  The following fields are nested inside each element of the `scenes[].backgroundCorpus` array. For example, `scenes[].backgroundCorpus[].visualUrl` means `visualUrl` is a property of each item in the `backgroundCorpus` array, which itself is nested inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].backgroundCorpus[].visualUrl" type="string">
  URL to background image.
</ParamField>

<ParamField body="scenes[].backgroundCorpus[].type" type="string">
  Must be `image`.
</ParamField>

<ParamField body="scenes[].backgroundCorpus[].prefer" type="boolean">
  Mark as preferred image for selection.
</ParamField>

***

## elements Array

Overlay elements placed on top of the scene background (max 20 per scene). Four element types are supported: `shape` and `text` (see the [Scene Elements guide](/guides/advanced-features/scene-elements)) and `video` and `image` (see the [Media Elements guide](/guides/advanced-features/media-elements)).

```json theme={null}
{
  "elements": [
    {
      "type": "shape",
      "name": "badge-3",
      "fill": "rgba(255,87,51,1)",
      "position": "top-left",
      "width": "18%"
    },
    {
      "type": "video",
      "visualUrl": "https://example.com/videos/demo.mp4",
      "position": "bottom-right",
      "width": "30%",
      "settings": { "loop": true, "mute": true }
    },
    {
      "type": "image",
      "searchFilter": { "query": "growth chart on laptop screen" },
      "top": "10%",
      "left": "6%"
    }
  ]
}
```

<Note>
  The following fields are nested inside each item of the `scenes[].elements` array. Fields marked "media only" apply to `video` and `image` elements; fields marked "shape only" or "text only" apply to those types.
</Note>

<ParamField body="scenes[].elements[].type" type="string" required>
  Element type. Options: `shape`, `text`, `video`, `image`.
</ParamField>

<ParamField body="scenes[].elements[].name" type="string">
  Shape only (required). Shape name, e.g. `rectangle`, `circle`, `badge-3`. See the [shape gallery](/guides/advanced-features/scene-elements#shape-gallery).
</ParamField>

<ParamField body="scenes[].elements[].fill" type="string">
  Shape only. Fill color in RGB, RGBA, or hex format. Related shape fields: `stroke`, `strokeWidth`, `borderRadius`.
</ParamField>

<ParamField body="scenes[].elements[].text" type="string">
  Text only (required). The text to display (max 2000 characters). Related text fields: `textVariant` (`heading`, `subheading`, `body`), `style`, `styleId`, `styleName`.
</ParamField>

<ParamField body="scenes[].elements[].visualUrl" type="string">
  Media only. URL of the video or image file to overlay. Exactly one of `visualUrl`, `searchFilter`, or `aiVisual` is required for media elements.
</ParamField>

<ParamField body="scenes[].elements[].searchFilter" type="object">
  Media only. Stock library search. Contains a single required field `query` (string): what to search for, in plain language. If no match is found, the element is skipped and the request still succeeds.
</ParamField>

<ParamField body="scenes[].elements[].aiVisual" type="object">
  Media only. Generate the element with AI. Same fields as [scenes\[\].background.aiVisual](#aivisual-object): `prompt`, `model` (required), `mediaStyle`, `videoDuration`. Consumes AI Credits according to the selected model's rate. If credits are insufficient or generation fails, the element is skipped.
</ParamField>

<ParamField body="scenes[].elements[].settings" type="object">
  Video elements only. Playback settings: `loop` (boolean, default `true`) and `mute` (boolean, default `true`).
</ParamField>

<ParamField body="scenes[].elements[].colorOverlay" type="object">
  Media only. Color tint applied to this element, with the same fields as the background [colorOverlay Object](#coloroverlay-object): `color` (required) and `opacity` (default `0.4`).
</ParamField>

<ParamField body="scenes[].elements[].position" type="string">
  Anchor preset: `top-left`, `top-center`, `top-right`, `center-left`, `center`, `center-right`, `bottom-left`, `bottom-center`, `bottom-right`. Cannot be combined with `top`/`left`.
</ParamField>

<ParamField body="scenes[].elements[].top" type="string">
  Vertical offset as a percentage from the top, e.g. `"10%"`. Cannot be combined with `position`.
</ParamField>

<ParamField body="scenes[].elements[].left" type="string">
  Horizontal offset as a percentage from the left, e.g. `"10%"`. Cannot be combined with `position`.
</ParamField>

<ParamField body="scenes[].elements[].width" type="string">
  Element width as a percentage of the canvas, e.g. `"30%"`. For media elements, omitting `width` enables automatic sizing: the element starts at 30% of the canvas and shrinks so it stays fully on screen given its position and aspect ratio.
</ParamField>

***

## transcript Array

Transcription of input video or audio content.

```json theme={null}
{
  "transcript": [
    {
      "speakerId": 1,
      "words": [
        { "word": "Hello", "start_time": 0.0, "end_time": 0.5, "is_pause": false, "is_filler": false }
      ]
    }
  ]
}
```

<Note>
  The following fields are nested inside the `scenes[].transcript` array. For example, `scenes[].transcript[].speakerId` means `speakerId` is a property of each item in the `transcript` array, which itself is nested inside each item of the `scenes` array. Fields like `scenes[].transcript[].words[].word` go one level deeper: `word` is inside each item of the `words` array, which is inside each `transcript` element.
</Note>

<ParamField body="scenes[].transcript[].speakerId" type="integer">
  Speaker identifier.
</ParamField>

<ParamField body="scenes[].transcript[].words" type="array" required>
  Array of word objects.
</ParamField>

<ParamField body="scenes[].transcript[].words[].word" type="string" required>
  The word text.
</ParamField>

<ParamField body="scenes[].transcript[].words[].start_time" type="number" required>
  Start time in seconds (min 0).
</ParamField>

<ParamField body="scenes[].transcript[].words[].end_time" type="number" required>
  End time in seconds (must be >= start\_time).
</ParamField>

<ParamField body="scenes[].transcript[].words[].is_pause" type="boolean">
  Whether this is a pause.
</ParamField>

<ParamField body="scenes[].transcript[].words[].is_filler" type="boolean">
  Whether this is a filler word.
</ParamField>

<ParamField body="scenes[].transcript[].words[].speakerId" type="integer">
  Speaker identifier for this word.
</ParamField>

***

## mediaRepurposeSettings Object

Settings for repurposing audio or video content.

```json theme={null}
{
  "mediaRepurposeSettings": {
    "highlightLength": 60,
    "removeFillerWords": true,
    "removeSilences": true,
    "silenceThresholdSeconds": 2
  }
}
```

<Note>
  The following fields are nested inside the `mediaRepurposeSettings` object, which is a property of each `scenes[]` element. For example, `scenes[].mediaRepurposeSettings.highlightLength` means `highlightLength` is a property of `mediaRepurposeSettings`, which itself is nested inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].mediaRepurposeSettings.highlightLength" type="number">
  Length of highlight in seconds (5-180).
</ParamField>

<ParamField body="scenes[].mediaRepurposeSettings.removeFillerWords" type="boolean">
  Remove filler words from the content.
</ParamField>

<ParamField body="scenes[].mediaRepurposeSettings.removeSilences" type="boolean">
  Remove silences from the content.
</ParamField>

<ParamField body="scenes[].mediaRepurposeSettings.silenceThresholdSeconds" type="number">
  Silence threshold in seconds (0-10).
</ParamField>

***

## templateOverride Object

Configuration for manipulating template scenes. Only available when `templateId` is provided.

```json theme={null}
{
  "templateOverride": {
    "sceneId": "scene-123",
    "subtitles": [
      { "text": "Updated subtitle text", "minimumDuration": 3 }
    ],
    "layers": [
      [
        { "layerId": "text-layer-1", "type": "text", "text": "Updated text content" }
      ]
    ]
  }
}
```

<Note>
  The following fields are nested inside the `templateOverride` object, which is a property of each `scenes[]` element. For example, `scenes[].templateOverride.sceneId` means `sceneId` is a property of `templateOverride`, which itself is nested inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].templateOverride.sceneId" type="string">
  ID of the existing scene to modify. Cannot be used with `scenePosition`.
</ParamField>

<ParamField body="scenes[].templateOverride.scenePosition" type="number">
  Position of the existing scene to modify (1-based). Cannot be used with `sceneId`.
</ParamField>

<ParamField body="scenes[].templateOverride.newScenePosition" type="number">
  New position for a newly inserted scene (1-based). Only for new scenes.
</ParamField>

<ParamField body="scenes[].templateOverride.insertAfterSceneId" type="string">
  Insert new scene after this scene ID. Only for new scenes. Cannot be used with `newScenePosition`.
</ParamField>

<ParamField body="scenes[].templateOverride.insertBeforeSceneId" type="string">
  Insert new scene before this scene ID. Only for new scenes. Cannot be used with `newScenePosition` or `insertAfterSceneId`.
</ParamField>

<ParamField body="scenes[].templateOverride.replaceSceneId" type="string">
  Replace the scene with this ID. Only for new scenes. Cannot be used with `newScenePosition`.
</ParamField>

<ParamField body="scenes[].templateOverride.replaceScenePosition" type="number">
  Replace the scene at this position (1-based). Only for new scenes. Cannot be used with `newScenePosition` or `replaceSceneId`.
</ParamField>

<ParamField body="scenes[].templateOverride.baseSceneId" type="string">
  Base scene ID to copy settings from. Only for new scenes.
</ParamField>

<ParamField body="scenes[].templateOverride.baseScenePosition" type="number">
  Base scene position to copy settings from (1-based). Only for new scenes. Cannot be used with `baseSceneId`.
</ParamField>

<ParamField body="scenes[].templateOverride.deleteScene" type="boolean">
  Delete this scene. Only for existing scenes.
</ParamField>

<ParamField body="scenes[].templateOverride.copyScene" type="boolean">
  Copy this scene. Only for existing scenes.
</ParamField>

<ParamField body="scenes[].templateOverride.subtitles" type="array">
  Array of subtitle configurations (max 500). Only for existing scenes. See [templateOverride.subtitles Array](#templateoverridesubtitles-array).
</ParamField>

<ParamField body="scenes[].templateOverride.layers" type="array">
  Array of layer configurations (max 500). Only for existing scenes. See [templateOverride.layers Array](#templateoverridelayers-array).
</ParamField>

<Warning>
  **Template Override Rules:**

  * `templateOverride` is only available when `templateId` is provided
  * Use `sceneId` OR `scenePosition` to identify existing scenes, not both
  * Properties like `newScenePosition`, `insertAfterSceneId`, `insertBeforeSceneId`, `replaceSceneId`, `baseSceneId` are only for new scenes
  * Properties like `deleteScene`, `copyScene`, `subtitles`, `layers` are only for existing scenes
</Warning>

### templateOverride.subtitles Array

```json theme={null}
{
  "subtitles": [
    {
      "text": "Your subtitle text here",
      "minimumDuration": 3,
      "styleId": "style-123"
    }
  ]
}
```

<Note>
  The following fields are nested inside each element of the `scenes[].templateOverride.subtitles` array. For example, `scenes[].templateOverride.subtitles[].text` means `text` is a property of each item in the `subtitles` array, which itself is nested inside `templateOverride`, inside each item of the `scenes` array.
</Note>

<ParamField body="scenes[].templateOverride.subtitles[].text" type="string" required>
  Subtitle text (1-40000 characters).
</ParamField>

<ParamField body="scenes[].templateOverride.subtitles[].minimumDuration" type="number">
  Minimum duration in seconds.
</ParamField>

<ParamField body="scenes[].templateOverride.subtitles[].styleId" type="string">
  ID of saved text style.
</ParamField>

<ParamField body="scenes[].templateOverride.subtitles[].styleName" type="string">
  Name of saved text style.
</ParamField>

<ParamField body="scenes[].templateOverride.subtitles[].style" type="object">
  Inline style configuration. See [subtitleStyle Object](#subtitlestyle-object).
</ParamField>

### templateOverride.layers Array

Layers allow you to customize text, image, and video elements within template scenes.

```json theme={null}
{
  "layers": [
    [
      { "layerId": "headline", "type": "text", "text": "Updated headline" },
      { "layerId": "logo", "type": "image", "url": "https://example.com/logo.png" }
    ]
  ]
}
```

<Note>
  The following fields are nested inside the `scenes[].templateOverride.layers` structure, which is an array of arrays. The `[][]` notation indicates that `layers` is an array of arrays: the outer `[]` represents each subtitle group, and the inner `[]` represents each layer element within that group. For example, `scenes[].templateOverride.layers[][].layerId` means `layerId` is a property of each layer element inside the nested array structure.
</Note>

<ParamField body="scenes[].templateOverride.layers[][].layerId" type="string">
  ID of the layer to modify (max 100 characters).
</ParamField>

<ParamField body="scenes[].templateOverride.layers[][].type" type="string">
  Layer type. Options: `text`, `image`, `video`
</ParamField>

<ParamField body="scenes[].templateOverride.layers[][].text" type="string">
  Text content (max 40000 characters). For `text` type only.
</ParamField>

<ParamField body="scenes[].templateOverride.layers[][].url" type="string">
  Media URL. For `image` or `video` type only.
</ParamField>

<ParamField body="scenes[].templateOverride.layers[][].styleId" type="string">
  Text style ID. For `text` type only.
</ParamField>

<ParamField body="scenes[].templateOverride.layers[][].styleName" type="string">
  Text style name. For `text` type only.
</ParamField>

<ParamField body="scenes[].templateOverride.layers[][].style" type="object">
  Inline text style. See [subtitleStyle Object](#subtitlestyle-object). For `text` type only.
</ParamField>

<ParamField body="scenes[].templateOverride.layers[][].deleteLayer" type="boolean">
  Delete this layer.
</ParamField>

***

## Response

When the storyboard request is successfully submitted, a job is created and a job ID is returned. Use this job ID to poll the [Get Storyboard Preview Job by ID](/api-reference/jobs/get-storyboard-preview-job-by-id) endpoint for the completed storyboard preview.

<ResponseField name="success" type="boolean">
  Indicates whether the request was successful
</ResponseField>

<ResponseField name="data" type="object">
  Contains the storyboard job information

  <ResponseField name="jobId" type="string">
    Unique identifier for the storyboard preview job. Use this to track the job status and retrieve results via the [Get Storyboard Preview Job by ID](/api-reference/jobs/get-storyboard-preview-job-by-id) endpoint.
  </ResponseField>
</ResponseField>

<ResponseExample>
  ```json 200 - Job Created theme={null}
  {
      "success": true,
      "data": {
          "jobId": "a1d36612-326d-4b81-aece-411f8aed4c70"
      }
  }
  ```

  ```json 400 - Invalid Request Body theme={null}
  {
      "code": "INVALID_REQUEST_BODY",
      "message": "Request body validation failed.",
      "fields": [
          {
              "name": "scenes",
              "errors": "scenes is required"
          }
      ]
  }
  ```

  ```json 401 - Unauthorized theme={null}
  {
      "message": "Unauthorized"
  }
  ```
</ResponseExample>

## Next Steps

Once you have the `jobId`, poll the [Get Storyboard Preview Job by ID](/api-reference/jobs/get-storyboard-preview-job-by-id) endpoint to check the job status and retrieve the completed storyboard preview. Use a polling interval of 10–30 seconds.

When the job completes, you will receive:

* **`renderParams`**: The rendering data for the video. To customize the video, update this data and use the [Render Video](/api-reference/videos/render-video) API to render with your modifications. To update the preview with changes, save the updated data using the [Update Storyboard Elements](/api-reference/video-storyboard/update-storyboard-elements) API.
* **`storyboard`**: The processed input storyboard. If you want to change anything in the original storyboard request, use this processed response to make a new request with updates; it will process faster since the storyboard is already broken down into scenes, voices, and other components.
* **`previewUrl`**: The preview URL for the video storyboard. Use this to view the preview in a browser or embed it in an iframe for app integrations. See the [Embed Preview Player](/integrations/storyboard-video-preview/embed-preview-player) guide for details.

***

## Code Examples

<Tip>
  Replace `YOUR_API_KEY` with your actual API key
</Tip>

### Basic Text to Video Preview

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.pictory.ai/pictoryapis/v2/video/storyboard \
    --header 'Authorization: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "videoName": "demo_text_to_video",
      "voiceOver": {
        "enabled": true,
        "aiVoices": [{"speaker": "Brian", "speed": 100}]
      },
      "scenes": [
        {
          "story": "AI is transforming how we create content. It automates tasks and saves time.",
          "createSceneOnEndOfSentence": true
        }
      ]
    }' | python -m json.tool
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.pictory.ai/pictoryapis/v2/video/storyboard', {
    method: 'POST',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      videoName: 'demo_text_to_video',
      voiceOver: {
        enabled: true,
        aiVoices: [{ speaker: 'Brian', speed: 100 }]
      },
      scenes: [{
        story: 'AI is transforming how we create content. It automates tasks and saves time.',
        createSceneOnEndOfSentence: true
      }]
    })
  });

  const result = await response.json();
  console.log('Job ID:', result.data.jobId);
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.pictory.ai/pictoryapis/v2/video/storyboard',
      headers={
          'Authorization': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'videoName': 'demo_text_to_video',
          'voiceOver': {
              'enabled': True,
              'aiVoices': [{'speaker': 'Brian', 'speed': 100}]
          },
          'scenes': [{
              'story': 'AI is transforming how we create content. It automates tasks and saves time.',
              'createSceneOnEndOfSentence': True
          }]
      }
  )

  result = response.json()
  print(f"Job ID: {result['data']['jobId']}")
  ```

  ```php PHP theme={null}
  <?php

  $url = 'https://api.pictory.ai/pictoryapis/v2/video/storyboard';

  $payload = [
      'videoName' => 'demo_text_to_video',
      'voiceOver' => [
          'enabled' => true,
          'aiVoices' => [['speaker' => 'Brian', 'speed' => 100]]
      ],
      'scenes' => [[
          'story' => 'AI is transforming how we create content. It automates tasks and saves time.',
          'createSceneOnEndOfSentence' => true
      ]]
  ];

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: YOUR_API_KEY',
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

  $response = curl_exec($ch);
  curl_close($ch);

  $result = json_decode($response, true);
  echo "Job ID: " . $result['data']['jobId'] . PHP_EOL;
  ?>
  ```

  ```go Go theme={null}
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "io"
      "net/http"
  )

  func main() {
      url := "https://api.pictory.ai/pictoryapis/v2/video/storyboard"

      payload := map[string]interface{}{
          "videoName": "demo_text_to_video",
          "voiceOver": map[string]interface{}{
              "enabled": true,
              "aiVoices": []map[string]interface{}{
                  {"speaker": "Brian", "speed": 100},
              },
          },
          "scenes": []map[string]interface{}{
              {
                  "story":                    "AI is transforming how we create content. It automates tasks and saves time.",
                  "createSceneOnEndOfSentence": true,
              },
          },
      }

      requestBody, _ := json.Marshal(payload)

      req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
      if err != nil {
          panic(err)
      }

      req.Header.Set("Authorization", "YOUR_API_KEY")
      req.Header.Set("Content-Type", "application/json")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          panic(err)
      }
      defer resp.Body.Close()

      body, _ := io.ReadAll(resp.Body)

      var result map[string]interface{}
      json.Unmarshal(body, &result)

      data := result["data"].(map[string]interface{})
      fmt.Println("Job ID:", data["jobId"])
  }
  ```
</CodeGroup>

### Preview with Smart Layout

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.pictory.ai/pictoryapis/v2/video/storyboard', {
    method: 'POST',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      videoName: 'smart_layout_video',
      smartLayoutName: 'modern minimalist',
      voiceOver: {
        enabled: true,
        aiVoices: [{ speaker: 'Emma', speed: 100 }]
      },
      scenes: [{
        story: 'Professional video creation has never been easier. Let AI handle the visuals.',
        createSceneOnEndOfSentence: true
      }]
    })
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      'https://api.pictory.ai/pictoryapis/v2/video/storyboard',
      headers={
          'Authorization': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'videoName': 'smart_layout_video',
          'smartLayoutName': 'modern minimalist',
          'voiceOver': {
              'enabled': True,
              'aiVoices': [{'speaker': 'Emma', 'speed': 100}]
          },
          'scenes': [{
              'story': 'Professional video creation has never been easier. Let AI handle the visuals.',
              'createSceneOnEndOfSentence': True
          }]
      }
  )
  ```
</CodeGroup>

### Preview with AI Story Generation

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.pictory.ai/pictoryapis/v2/video/storyboard', {
    method: 'POST',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      videoName: 'ai_generated_script',
      voiceOver: {
        enabled: true,
        aiVoices: [{ speaker: 'Matthew', speed: 100 }]
      },
      scenes: [{
        storyCoPilot: {
          prompt: 'Benefits of remote work for modern businesses',
          videoType: 'Explainer',
          duration: 90,
          platform: 'LinkedIn',
          tone: 'professional'
        },
        createSceneOnEndOfSentence: true
      }]
    })
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      'https://api.pictory.ai/pictoryapis/v2/video/storyboard',
      headers={
          'Authorization': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'videoName': 'ai_generated_script',
          'voiceOver': {
              'enabled': True,
              'aiVoices': [{'speaker': 'Matthew', 'speed': 100}]
          },
          'scenes': [{
              'storyCoPilot': {
                  'prompt': 'Benefits of remote work for modern businesses',
                  'videoType': 'Explainer',
                  'duration': 90,
                  'platform': 'LinkedIn',
                  'tone': 'professional'
              },
              'createSceneOnEndOfSentence': True
          }]
      }
  )
  ```
</CodeGroup>

### Preview with AI-Generated Background Image

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.pictory.ai/pictoryapis/v2/video/storyboard', {
    method: 'POST',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      videoName: 'ai_background_image_video',
      voiceOver: {
        enabled: true,
        aiVoices: [{ speaker: 'Brian', speed: 100 }]
      },
      scenes: [{
        story: 'Experience the beauty of nature through AI-generated imagery.',
        createSceneOnEndOfSentence: true,
        background: {
          type: 'image',
          aiVisual: {
            model: 'seedream3.0',
            mediaStyle: 'photorealistic'
          },
          settings: {
            zoomAndPan: true
          }
        }
      }]
    })
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      'https://api.pictory.ai/pictoryapis/v2/video/storyboard',
      headers={
          'Authorization': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'videoName': 'ai_background_image_video',
          'voiceOver': {
              'enabled': True,
              'aiVoices': [{'speaker': 'Brian', 'speed': 100}]
          },
          'scenes': [{
              'story': 'Experience the beauty of nature through AI-generated imagery.',
              'createSceneOnEndOfSentence': True,
              'background': {
                  'type': 'image',
                  'aiVisual': {
                      'model': 'seedream3.0',
                      'mediaStyle': 'photorealistic'
                  },
                  'settings': {
                      'zoomAndPan': True
                  }
              }
          }]
      }
  )
  ```
</CodeGroup>

### Preview with AI-Generated Background Video Clip

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.pictory.ai/pictoryapis/v2/video/storyboard', {
    method: 'POST',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      videoName: 'ai_background_video_clip',
      aspectRatio: '16:9',
      voiceOver: {
        enabled: true,
        aiVoices: [{ speaker: 'Brian', speed: 100 }]
      },
      scenes: [{
        story: 'The future of technology is unfolding before our eyes.',
        createSceneOnEndOfSentence: true,
        background: {
          type: 'video',
          aiVisual: {
            prompt: 'Futuristic cityscape at night with flying vehicles and neon signs',
            model: 'pixverse5.5',
            videoDuration: '8s'
          }
        }
      }]
    })
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      'https://api.pictory.ai/pictoryapis/v2/video/storyboard',
      headers={
          'Authorization': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'videoName': 'ai_background_video_clip',
          'aspectRatio': '16:9',
          'voiceOver': {
              'enabled': True,
              'aiVoices': [{'speaker': 'Brian', 'speed': 100}]
          },
          'scenes': [{
              'story': 'The future of technology is unfolding before our eyes.',
              'createSceneOnEndOfSentence': True,
              'background': {
                  'type': 'video',
                  'aiVisual': {
                      'prompt': 'Futuristic cityscape at night with flying vehicles and neon signs',
                      'model': 'pixverse5.5',
                      'videoDuration': '8s'
                  }
              }
          }]
      }
  )
  ```
</CodeGroup>

### Full Featured Preview Example

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.pictory.ai/pictoryapis/v2/video/storyboard', {
    method: 'POST',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      videoName: 'full_featured_video',
      aspectRatio: '16:9',
      language: 'en',
      saveProject: true,
      brandName: 'My Brand',

      // Background music
      backgroundMusic: {
        enabled: true,
        autoMusic: true,
        volume: 0.3
      },

      // AI Voice-over
      voiceOver: {
        enabled: true,
        aiVoices: [{
          speaker: 'Brian',
          speed: 100,
          amplificationLevel: 0
        }]
      },

      // Logo
      logo: {
        url: 'https://example.com/logo.png',
        position: 'top-right',
        width: '12%'
      },

      // Subtitle styling
      subtitleStyle: {
        fontFamily: 'Montserrat',
        fontSize: 48,
        color: 'rgba(255,255,255,1)',
        position: 'bottom-center',
        alignment: 'center'
      },

      // Scenes
      scenes: [{
        story: 'Welcome to our company. We create innovative solutions. Join us on this journey.',
        createSceneOnEndOfSentence: true,
        highlightKeywords: true,
        sceneTransition: 'fade'
      }]
    })
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      'https://api.pictory.ai/pictoryapis/v2/video/storyboard',
      headers={
          'Authorization': 'YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'videoName': 'full_featured_video',
          'aspectRatio': '16:9',
          'language': 'en',
          'saveProject': True,
          'brandName': 'My Brand',

          # Background music
          'backgroundMusic': {
              'enabled': True,
              'autoMusic': True,
              'volume': 0.3
          },

          # AI Voice-over
          'voiceOver': {
              'enabled': True,
              'aiVoices': [{
                  'speaker': 'Brian',
                  'speed': 100,
                  'amplificationLevel': 0
              }]
          },

          # Logo
          'logo': {
              'url': 'https://example.com/logo.png',
              'position': 'top-right',
              'width': '12%'
          },

          # Subtitle styling
          'subtitleStyle': {
              'fontFamily': 'Montserrat',
              'fontSize': 48,
              'color': 'rgba(255,255,255,1)',
              'position': 'bottom-center',
              'alignment': 'center'
          },

          # Scenes
          'scenes': [{
              'story': 'Welcome to our company. We create innovative solutions. Join us on this journey.',
              'createSceneOnEndOfSentence': True,
              'highlightKeywords': True,
              'sceneTransition': 'fade'
          }]
      }
  )
  ```
</CodeGroup>

***

## Error Handling

<AccordionGroup>
  <Accordion title="400 - Missing Required Fields">
    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "INVALID_REQUEST",
        "message": "videoName is required"
      }
    }
    ```

    **Solution:** Ensure `videoName` and `scenes` are provided.
  </Accordion>

  <Accordion title="400 - Invalid Scene Configuration">
    ```json theme={null}
    {
      "success": false,
      "error": {
        "message": "Scene must have exactly one of: story, storyCoPilot, blogUrl, pptUrl, audioUrl, or videoUrl"
      }
    }
    ```

    **Solution:** Each scene can only have one content source.
  </Accordion>

  <Accordion title="400 - Smart Layout Conflict">
    ```json theme={null}
    {
      "success": false,
      "error": {
        "message": "maxSubtitleLines is not allowed when smartLayoutId or smartLayoutName is provided"
      }
    }
    ```

    **Solution:** Remove `maxSubtitleLines` when using smart layouts.
  </Accordion>

  <Accordion title="401 - Unauthorized">
    ```json theme={null}
    {
      "message": "Unauthorized"
    }
    ```

    **Solution:** Check your API key is valid and correctly formatted in the Authorization header.
  </Accordion>

  <Accordion title="429 - Rate Limit Exceeded">
    **Solution:** Implement exponential backoff and space out requests.
  </Accordion>
</AccordionGroup>

***

## Related Guides

<CardGroup cols={2}>
  <Card title="AI-Generated Background Images" icon="image" href="/guides/ai-generated-visuals/background-images">
    Generate AI images as scene backgrounds
  </Card>

  <Card title="AI-Generated Background Video Clips" icon="video" href="/guides/ai-generated-visuals/background-videos">
    Generate AI video clips as scene backgrounds
  </Card>

  <Card title="AI Voice-Over" icon="microphone" href="/guides/text-to-video/ai-voiceover">
    Add professional AI narration
  </Card>

  <Card title="Smart Layouts" icon="table-layout" href="/guides/smart-layouts-and-subtitles/smart-layouts">
    Apply professional visual layouts
  </Card>

  <Card title="Story CoPilot" icon="wand-magic-sparkles" href="/guides/story-copilot/ai-story-generation">
    Generate scripts with AI
  </Card>

  <Card title="Background Music" icon="music" href="/guides/advanced-features/background-music">
    Add music to your videos
  </Card>

  <Card title="Brand Settings" icon="palette" href="/guides/branding-customization/brand-settings">
    Apply consistent branding
  </Card>

  <Card title="Subtitle Styles" icon="closed-captioning" href="/guides/branding-customization/subtitle-styles">
    Customize caption formatting
  </Card>
</CardGroup>

***

## Next Steps

After creating your storyboard preview:

<CardGroup cols={2}>
  <Card title="Check Preview Status" icon="clock" href="/api-reference/jobs/get-storyboard-preview-job-by-id">
    Monitor preview generation progress and retrieve results
  </Card>

  <Card title="Render Final Video" icon="film" href="/api-reference/videos/render-from-preview">
    Convert approved preview into final video file
  </Card>

  <Card title="Update Project" icon="pen-to-square" href="/api-reference/projects/update-project">
    Modify scenes or settings before rendering
  </Card>

  <Card title="Get Project Details" icon="folder-open" href="/api-reference/projects/get-project-by-id">
    Retrieve full project information
  </Card>
</CardGroup>

### Supporting APIs

<CardGroup cols={2}>
  <Card title="Get Voiceover Tracks" icon="microphone" href="/api-reference/voiceovers/get-voiceover-tracks">
    List available AI voices for your preview
  </Card>

  <Card title="Get Text Styles" icon="font" href="/api-reference/branding/get-text-styles">
    View saved subtitle styles
  </Card>

  <Card title="Get Video Brands" icon="palette" href="/api-reference/branding/get-video-brands">
    List available brands
  </Card>

  <Card title="Search Media" icon="images" href="/api-reference/media-management/search-media">
    Find stock visuals for your scenes
  </Card>
</CardGroup>
