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

# Node Config

> Override workflow action node settings when triggering a template

Use node config overrides when a trigger needs to change the same settings a user can configure in the workflow builder. This is the most precise way to customize a run without editing the saved workflow template.

<Info>
  This page documents frontend workflow-configurable fields only. Backend-only runtime fields are intentionally omitted.
</Info>

## Where Overrides Go

Add one of these fields to `POST /trigger-template`:

* `nodeConfigs`
* `nodeConfigOverrides`
* `actionConfigs`

They all behave the same way. Most integrations should use `nodeConfigs`.

```json theme={null}
{
  "companyId": "company-id-from-your-overlap-account",
  "workflowId": "workflow-id-from-the-overlap-workflow-url",
  "url": "public-source-video-url",
  "nodeConfigs": {
    "add_broll": {
      "enable_ai_broll": true,
      "broll_frequency": "high"
    }
  }
}
```

You can also send overrides as a list:

```json theme={null}
{
  "nodeConfigs": [
    {
      "nodeType": "add_broll",
      "config": {
        "enable_ai_broll": true,
        "broll_frequency": "high"
      }
    }
  ]
}
```

## How Overrides Apply

* Overrides are keyed by workflow node type, such as `add_broll` or `add_subtitles`.
* The public API resolves each node type to the matching node in the selected workflow.
* If the workflow does not contain that node type, the override is skipped and the workflow still runs.
* If the workflow contains the node but the config has invalid field names, invalid types, or invalid enum values, the request returns `INVALID_NODE_CONFIG`.
* Structured overrides win over legacy flat fields when both set the same nested value.

For example, if you send both `broll: true` and `nodeConfigs.add_broll.enabled: false`, the structured `nodeConfigs` value wins for `add_broll.enabled`.

## Quick Example

This example changes clip length, b-roll, subtitles, and vertical reframe behavior for one trigger:

```json theme={null}
{
  "nodeConfigs": {
    "find_clips": {
      "min_length": 30,
      "max_length": 90,
      "model_key": "multimodal",
      "prompt": "Find clips where the speaker explains a concrete product benefit."
    },
    "add_broll": {
      "enable_ai_broll": true,
      "broll_frequency": "high",
      "allowed_methods": ["google_images", "youtube"]
    },
    "add_subtitles": {
      "subtitle_config": {
        "speakerStyles": [
          {
            "subtitleY": 50
          }
        ]
      }
    },
    "convert_to_vertical": {
      "style": "adaptive",
      "split_view": true,
      "force_split_view": true,
      "ignore_content_tiles": false
    }
  }
}
```

## Supported Node Types

| Node type | Frontend-configurable fields |
| - | - |
| `find_clips` | `min_length`, `max_length`, `model_key`, `prompt`, `promptAdjustment`, `pinnedTimestamps`, `pinnedTimestampsOnly`, `pinnedTimestampMode` |
| `convert_to_vertical` | `aspect_ratio`, `style`, `centerVertical`, `zoom` and `gaussian_blur` when `centerVertical` is `true`, `y_offset`, `split_view`, `force_split_view`, `ignore_content_tiles` |
| `style_video` | `style_video_config` |
| `add_broll` | `prompt`, `broll_frequency`, `allowed_methods`, `enable_ai_broll`, `use_broll_library`, `library_folder_ids` |
| `add_subtitles` | `subtitle_config` |
| `add_music` | `background_music_option`, `background_music_options` |
| `add_watermark` | `watermark_config` |
| `apply_branding` | `style`, `watermark_config`, `outro_music_url`, `outro_card_url`, `overlay_url`, `title_config` |
| `add_title_overlay` | `title_config`, `titleConfig` |
| `add_lower_thirds` | `lower_thirds_config`, `speaker_names` (API only) |
| `filler_words` | `filler_words_config` |
| `smart_zoom` | `smart_zoom_config` |
| `add_outro` | `end_card_option`, `outro_music_option` |
| `add_audiogram` | `template`, `audiogram_config` |
| `remove_watermark` | `remove_watermark_config` |
| `add_brainrot` | `brainrot_config` |
| `media_overlay` | `media_overlay_config` |
| `remove_curse_words` | `remove_curse_words_config` |

<Warning>
  `add_subtitles`, `add_title_overlay`, `add_watermark`, and `add_outro` are
  **deprecated but supported**. Use `style_video` for new workflows. Existing
  workflows and their standalone node overrides continue to work.
</Warning>

## Per-Node Examples

### `find_clips`

Controls the clip discovery step.

```json theme={null}
{
  "nodeConfigs": {
    "find_clips": {
      "min_length": 30,
      "max_length": 90,
      "model_key": "multimodal",
      "prompt": "Find clips with clear explanations, strong takeaways, and minimal setup.",
      "promptAdjustment": "Prioritize customer proof points for this run.",
      "pinnedTimestamps": [{ "start": 120, "end": 165 }],
      "pinnedTimestampsOnly": false,
      "pinnedTimestampMode": "search_within"
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `min_length` | number | Minimum target clip length in seconds. |
| `max_length` | number | Maximum target clip length in seconds. |
| `model_key` | string | `conversational` or `multimodal`. |
| `prompt` | string | Replaces the node's clip-finding prompt for this run. |
| `promptAdjustment` | string | Adds one-run guidance to the saved node prompt. |
| `pinnedTimestamps` | object\[] | Source-video ranges such as `{ "start": 120, "end": 165 }` to include as clips. |
| `pinnedTimestampsOnly` | boolean | When `true`, skip automatic discovery and return only `pinnedTimestamps` clips. Defaults to `false`. |
| `pinnedTimestampMode` | string | Use `search_within` to discover individual clips inside `pinnedTimestamps`; omit it for guaranteed timestamp clips. |

### `convert_to_vertical`

Controls the Reframe / Convert to Vertical node.

```json theme={null}
{
  "nodeConfigs": {
    "convert_to_vertical": {
      "aspect_ratio": "9:16",
      "style": "style_three",
      "centerVertical": true,
      "zoom": 1,
      "gaussian_blur": false,
      "y_offset": 0.5,
      "split_view": true,
      "force_split_view": true,
      "ignore_content_tiles": false
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `aspect_ratio` | string | Usually `9:16` for vertical output. |
| `style` | string | `style_one`, `style_two`, `style_three`, `style_four`, `style_none`, or `adaptive`. |
| `centerVertical` | boolean | Enables centered vertical crop mode. `zoom` and `gaussian_blur` only apply when this is `true`. |
| `zoom` | number | Zoom multiplier for centered vertical crop mode. Values below `1` are normalized to `1`. Only applies when `centerVertical` is `true`. |
| `y_offset` | number | Vertical offset used by supported styles. |
| `gaussian_blur` | boolean | Enables blurred background for centered vertical crop mode. Only applies when `centerVertical` is `true`. |
| `split_view` | boolean | Enables split view when reframing. |
| `force_split_view` | boolean | Forces split view for adaptive reframing. |
| `ignore_content_tiles` | boolean | Ignores content tiles for adaptive reframing. |

### `add_broll`

Controls B-roll generation and sourcing.

```json theme={null}
{
  "nodeConfigs": {
    "add_broll": {
      "prompt": "Use product screenshots, event footage, and relevant visual metaphors. Avoid generic stock photos.",
      "broll_frequency": "high",
      "allowed_methods": ["google_images", "youtube"],
      "enable_ai_broll": false,
      "use_broll_library": true,
      "library_folder_ids": ["folder-id-from-your-overlap-library"]
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `prompt` | string | Custom guidance for B-roll selection. |
| `broll_frequency` | string | `low`, `medium`, `high`, or `always_on`. The `always_on` value continuously covers the complete visible video with B-roll. |
| `allowed_methods` | string\[] | Any of `google_images`, `youtube`, `getty`. |
| `enable_ai_broll` | boolean | Enables AI-generated B-roll. |
| `use_broll_library` | boolean | Uses your uploaded B-roll library. |
| `library_folder_ids` | string\[] | Folder IDs to search. Empty array means all folders. |

### `add_subtitles`

Controls subtitle placement and styling.

```json theme={null}
{
  "nodeConfigs": {
    "add_subtitles": {
      "subtitle_config": {
        "maxCharsPerLine": 28,
        "maxLines": 1,
        "wrapWidthPct": 80,
        "subtitleX": 50,
        "subtitleY": 50,
        "speakerStyles": [
          {
            "styleId": "custom",
            "fontColor": "#FFFFFF",
            "fontFamily": "Forma-DJR",
            "fontSize": "42",
            "fontWeight": "900",
            "backgroundColor": "#000000",
            "backgroundOpacity": 0.85,
            "backgroundFillStyle": "block",
            "subtitleX": 50,
            "subtitleY": 50
          }
        ]
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `subtitle_config` | object | Advanced subtitle configuration from the workflow subtitle editor. Send this as a JSON object, not a string. |
| `subtitle_config.speakerStyles` | object\[] or object | Per-speaker subtitle styles. Prefer an array for API requests: index `0` is speaker 0, index `1` is speaker 1, and so on. An object map with numeric keys, such as `{ "0": { ... } }`, is also accepted. |
| `subtitle_config.speakerStyles[0]` | object | Default style for the first speaker and the fallback style most subtitle renders inherit from. For most integrations, put subtitle styling and positioning fields here. If only `speakerStyles[0]` is defined, subtitles inherit that style unless a later speaker has its own entry. |
| `subtitle_config.speakerStyles[n]` | object | Optional override for speaker `n`. Use this only when a specific speaker needs different styling from `speakerStyles[0]`. |
| `subtitle_config.maxCharsPerLine` | number | Maximum characters per subtitle line. This can be set at the root because it controls line breaking for the subtitle layer. |
| `subtitle_config.maxLines` | number | Maximum number of subtitle lines to display at once. |
| `subtitle_config.wrapWidthPct` | number | Subtitle text wrapping width as a percentage of the video width. |
| `subtitle_config.subtitleX` | number | Horizontal subtitle position as a percentage of video width, where `50` is centered. Set this in `speakerStyles[0]` for the usual one-style subtitle setup, or at the root when you intentionally need a layer default. |
| `subtitle_config.subtitleY` | number | Vertical subtitle position as a percentage of video height. Set this in `speakerStyles[0]` for the usual one-style subtitle setup, or at the root when you intentionally need a layer default. |
| `subtitle_config.selectedSpeaker` | number | Editor selection state. Usually omit this in API overrides. |
| `subtitle_config.resolvedStyle` | object | Editor-resolved style metadata. Usually omit this in API overrides. |

<Tip>
  For most subtitle overrides, set style fields inside `subtitle_config.speakerStyles[0]`. For example, `subtitle_config.speakerStyles[0].subtitleY` sets the default subtitle Y position, and that value is inherited by subtitles when no more specific speaker style is present.
</Tip>

`speakerStyles` array entry fields:

| Field | Type | Notes |
| - | - | - |
| `styleId` | string | Subtitle preset/style identifier. |
| `name` | string | Display name for the subtitle style. |
| `fontFamily` | string | Font family used for subtitle text. |
| `fontUrl` | string | Optional font file URL used by the renderer. |
| `fontSize` | string or number | Subtitle font size. |
| `fontWeight` | string | CSS-style font weight such as `400`, `700`, or `900`. |
| `fontColor` | string | Subtitle text color, usually a hex color. |
| `isItalic` | boolean | Renders subtitle text in italic. |
| `textCase` | string | Text case transform, such as `none`, `uppercase`, or `lowercase`. |
| `textAlign` | string | `left`, `center`, or `right`. |
| `textSpacing` | string or number | Letter spacing. |
| `wordSpacing` | string or number | Extra pixels added between words. |
| `verticalStretch` | string or number | Vertical text stretch. |
| `opacity` | number | Overall subtitle opacity, usually between `0` and `1`. |
| `captionPosition` | string | `top`, `middle`, or `bottom`. |
| `subtitleX` | number | Horizontal subtitle position as a percentage of video width. |
| `subtitleY` | number | Vertical subtitle position as a percentage of video height. |
| `maxCharsPerLine` | number | Maximum characters per subtitle line for this speaker style. |
| `maxLines` | number | Maximum subtitle lines for this speaker style. |
| `wrapWidthPct` | number | Wrapping width as a percentage of video width for this speaker style. |
| `backgroundColor` | string | Subtitle background color. |
| `backgroundOpacity` | number | Background opacity, usually between `0` and `1`. |
| `backgroundFillStyle` | string | `wrap`, `block`, or `none`. |
| `backgroundBorderRadius` | string or number | Subtitle background corner radius. |
| `backgroundPadding` | string or number | Subtitle background padding. |
| `backgroundPaddingX` | string | Horizontal background padding. |
| `backgroundPaddingY` | string | Vertical background padding. |
| `outlineColor` | string | Text outline color. |
| `outlineStyle` | string | Text outline style. |
| `outlineWidth` | string or number | Text outline width. |
| `shadowEnabled` | boolean | Enables text shadow. |
| `shadowColor` | string | Text shadow color. |
| `shadowBlur` | string or number | Text shadow blur amount. |
| `shadowOffsetX` | string or number | Text shadow horizontal offset. |
| `shadowOffsetY` | string or number | Text shadow vertical offset. |
| `shadowIntensity` | number | Shadow strength. |
| `amplifySpokenWords` | boolean | Enables emphasized/current-word styling. |
| `amplifiedColor` | string | Color used for amplified spoken words. |
| `amplifiedColors` | object\[] | Optional multi-color or gradient amplified-word settings. |
| `amplifiedOpacity` | number | Opacity for amplified spoken words. |
| `amplifyOpacityTransitionDuration` | number | Transition duration for amplified-word opacity. |
| `highlightWordsColor` | string | Color used for highlighted words. |
| `highlightWordsBaseStyle` | object | Base style applied to highlighted words. |
| `highlightKeywordStyles` | object | Per-keyword highlight style overrides. |
| `textHighlightPersists` | boolean | Keeps highlighted-word styling after the word is spoken. |
| `currentWordBlock` | boolean | Enables block styling for the current word. |
| `currentWordBlockBackgroundColor` | string | Current-word block background color. |
| `currentWordBlockBorderRadius` | string | Current-word block corner radius. |
| `currentWordBlockOpacity` | number | Current-word block opacity. |
| `currentWordBlockPadding` | string | Current-word block padding. |
| `randomColors` | object | Random word-color settings. |
| `shinySegmentHighlight` | boolean | Enables shiny segment highlighting. |
| `shinyWordHighlight` | boolean | Enables shiny word highlighting. |
| `animationStyle` | string | Subtitle animation style. |

### `style_video`

Controls the complete visual treatment from the [Style Video](/nodes/style-video)
node. All styling elements are optional; an empty `layers` array is a valid
no-op.

```json theme={null}
{
  "nodeConfigs": {
    "style_video": {
      "style_video_config": {
        "version": 1,
        "layers": [
          {
            "id": "captions",
            "type": "subtitles",
            "enabled": true,
            "config": {
              "speakerStyles": [
                {
                  "styleId": "custom",
                  "fontColor": "#FFFFFF",
                  "subtitleY": 72
                }
              ]
            }
          },
          {
            "id": "logo",
            "type": "watermark",
            "enabled": true,
            "config": {
              "enabled": true,
              "url": "https://cdn.example.com/logo.png",
              "position": 2,
              "size": 12,
              "padding": 2
            }
          }
        ],
        "outro": {
          "endCardOption": {
            "url": "https://cdn.example.com/end-card.png",
            "duration": 5,
            "secondsBeforeEnd": 0
          }
        },
        "colorGrading": {
          "exposure": 8,
          "contrast": 12,
          "vignette": 10,
          "grain": {
            "amount": 8,
            "animated": true
          }
        }
      }
    }
  }
}
```

Top-level fields:

| Field | Type | Notes |
| - | - | - |
| `style_video_config.version` | number | Required wrapper version. Use `1`. |
| `style_video_config.layers` | object\[] | Required array of visual layers. It may be empty. |
| `style_video_config.stepOrder` | string\[] | Optional authoring order containing each of `title_overlay`, `subtitles`, `graphics`, `outro`, and `color_grading` once. Usually omit it and use the default order. |
| `style_video_config.template` | object | Optional selected-template reference with `id`, `name`, `previewUrl`, and `editConfig`. It is normally retained from the saved workflow instead of constructed in an override. |
| `style_video_config.outro` | object | Optional `endCardOption`, `outroMusicOption`, or both. Each configured option requires a public `url`. |
| `style_video_config.colorGrading` | object | Optional final grade for the base video. |

Layer fields:

| Field | Type | Notes |
| - | - | - |
| `layers[].id` | string | Required stable ID that is unique within the Style Video node. |
| `layers[].type` | string | `title`, `subtitles`, `watermark`, `media_overlay`, or `lower_thirds`. |
| `layers[].enabled` | boolean | Disabled layers keep their configuration but are not applied. |
| `layers[].config` | object | The corresponding title, subtitle, watermark, media-overlay, or lower-third configuration without the standalone node's outer field name. |

Style Video supports multiple title, watermark, and media-overlay layers. It
supports at most one subtitle layer and one lower-third layer. Watermark layers
require `config.url`; media overlays require `config.mediaUrl`.

Color grading fields:

| Field | Type | Notes |
| - | - | - |
| `brightness`, `exposure`, `contrast`, `highlights`, `shadows` | number | Light adjustments. |
| `saturation`, `vibrance`, `temperature`, `tint` | number | Color adjustments. |
| `fade`, `vignette`, `blur` | number | Finishing adjustments. |
| `grain.amount` | number | Film grain amount from `0` to `100`. |
| `grain.size` | number | Film grain size from `0.5` to `8`. |
| `grain.opacity` | number | Film grain opacity from `0` to `1`. |
| `grain.animated` | boolean | Animates the grain pattern when `true`. |
| `grain.seed` | number | Optional deterministic grain seed. |

### `add_music`

Controls background music.

```json theme={null}
{
  "nodeConfigs": {
    "add_music": {
      "background_music_options": [
        {
          "id": "music-track-id",
          "name": "Selected music track",
          "url": "public-music-file-url",
          "thumbnailUrl": "public-thumbnail-url",
          "duration": 120,
          "volume": 0.35
        }
      ]
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `background_music_option` | object | Legacy single-song option. |
| `background_music_options` | object\[] | Multiple music options. The workflow can select per clip. |

Music option fields:

| Field | Type | Notes |
| - | - | - |
| `id` | string | Track ID. |
| `name` | string | Display name. |
| `url` | string | Public audio URL. |
| `thumbnailUrl` | string | Optional thumbnail URL. |
| `duration` | number | Track duration in seconds. |
| `volume` | number | Volume multiplier, usually between `0` and `1`. |

### `add_watermark`

Controls watermark rendering config.

```json theme={null}
{
  "nodeConfigs": {
    "add_watermark": {
      "watermark_config": {
        "enabled": true,
        "url": "public-watermark-image-url",
        "position": 3,
        "size": 18,
        "padding": 24,
        "opacity": 0.9
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `watermark_config.enabled` | boolean | Enables or disables the watermark. |
| `watermark_config.url` | string | Public image URL. |
| `watermark_config.position` | number | Position value used by the renderer. |
| `watermark_config.size` | number | Watermark size. |
| `watermark_config.padding` | number | Edge padding. |
| `watermark_config.opacity` | number | Opacity, usually between `0` and `1`. |

### `apply_branding`

Controls the Apply Branding node.

```json theme={null}
{
  "nodeConfigs": {
    "apply_branding": {
      "style": "default",
      "watermark_config": {
        "enabled": true,
        "url": "public-watermark-image-url"
      },
      "outro_music_url": "public-outro-music-url",
      "outro_card_url": "public-outro-card-image-url",
      "overlay_url": "public-overlay-media-url",
      "title_config": {
        "prompt": "Write a short hook for this clip.",
        "fontColor": "#FFFFFF",
        "backgroundColor": "#000000"
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `style` | string | Branding style name. |
| `watermark_config` | object | Watermark config to apply. |
| `outro_music_url` | string | Public outro music URL. |
| `outro_card_url` | string | Public outro card image URL. |
| `overlay_url` | string | Public overlay media URL. |
| `title_config` | object | Title overlay config to apply. |

### `add_title_overlay`

Controls the Title Overlay node.

```json theme={null}
{
  "nodeConfigs": {
    "add_title_overlay": {
      "title_config": {
        "prompt": "Create a concise title that teases the main insight.",
        "fontFamily": "Roboto",
        "fontWeight": "500",
        "fontColor": "#000000",
        "backgroundColor": "#FFFFFF",
        "backgroundOpacity": 1,
        "backgroundStyle": "wrap",
        "textAlign": "center",
        "yPosition": 0.23,
        "duration": 4,
        "allCaps": false
      }
    }
  }
}
```

Common `title_config` fields:

| Field | Type |
| - | - |
| `prompt` | string |
| `text` | string — preview or fixed primary text; replaced by generated output when generation is enabled |
| `generateTitle` | boolean — default `true`; `false` skips AI title and variable generation, using fixed text and generated-variable samples. Fixed variables remain fixed; references still read the current input. |
| `fontFamily` | string |
| `fontWeight` | string |
| `fontColor` | string |
| `fontSize` | number |
| `lineHeight` | number |
| `characterSpacing` | number |
| `padding` | number |
| `verticalPadding` | number |
| `borderRadius` | number |
| `backgroundColor` | string |
| `backgroundOpacity` | number |
| `backgroundStyle` | string |
| `boxShadow` | string |
| `textShadow` | string |
| `yPosition` | number |
| `positionDynamically` | boolean (default `false`; anchors the title to a detected split-view seam) |
| `avoidFaces` | boolean (default `false`; moves the title away from detected face and subject regions) |
| `duration` | number |
| `allCaps` | boolean |
| `textAlign` | string |
| `fontScale` | number |
| `lineMargin` | number |
| `titlePresetId` | string — apply a styled title template (see [Styled title templates](#styled-title-templates) below). When set, the template's design drives the look and the flat typography/background fields above are ignored. |
| `titlePaletteId` | string — color palette for templates that define one |
| `presetOverrides` | object — per-template style/position customizations layered on the template (see below) |
| `presetTextOverrides` | object — fixed text for a template's non-primary lines, keyed by element id (e.g. `text-secondary`). Fixed text overrides generation for that block. |
| `presetGenerationBlocks` | array — ordered semantic generation blocks carried by a preset. Each entry contains `elementId`, `kind` (`name` or `title`), and optional `primary`. |
| `titleVariables` | array — generated, fixed, or reference variables; see [Title variables](#title-variables) |
| `titleVariableBindings` | object — text templates keyed by title element ID, using tokens such as `{{headline}}` |
| `titleVariableImageBindings` | object — image-slot bindings, each containing one image token such as `{{logo}}` or `{{clip.thumbnail}}`, a fixed HTTP(S) image URL, or an empty string to clear |

By default this node generates a title for each clip with AI and ignores `text`. To use your own fixed title instead, set `generateTitle` to `false` and provide `text`:

```json theme={null}
{
  "nodeConfigs": {
    "add_title_overlay": {
      "title_config": { "text": "Our Exact Title", "generateTitle": false }
    }
  }
}
```

The same fixed title is applied to every clip in the run. For different per-clip
content, configure AI generation or title variables, or edit each clip after
generation with [Update Clip](/api-reference/update-clip).

#### Title variables

Define as many variables as your title needs in `titleVariables`. A variable
can generate a result, hold a fixed value, or reference current workflow data.
Its `id` is the stable token used by templates; `name` is the editable display
label shown on its colored block in the editor. Existing variables without a
`source` retain generated behavior.

| Variable field | Type | Meaning |
| - | - | - |
| `id` | string | Unique variable identifier used in `{{id}}` tokens. Start with a letter and use letters, numbers, and underscores. Keep it stable when renaming the display label. |
| `name` | string | User-facing name for this variable. |
| `source` | `generated`, `fixed`, or `reference` | Defaults to `generated`. Fixed and reference values never invoke AI. |
| `outputType` | `text`, `number`, `boolean`, or `image` | Required result type. Image variables must use `fixed` or `reference`. |
| `prompt` | string | Generation instructions. May be empty for fixed or reference variables. Reference tokens can appear in generated prompts. |
| `value` | string, number, or boolean | Fixed value, or generated sample/resolved value, matching `outputType`. Image values are image URLs. Reference variables ignore stored values. |
| `reference` | string | Required for `source: "reference"`; one of the reference keys listed below, matching `outputType`. |

`titleVariableBindings` maps text element IDs to reusable text templates.
Use `text-primary` for a custom title's main text and for most presets' primary
text. The older `__primary__` key is still accepted and is saved as the primary
element's ID. Supporting fields use the preset's editable element IDs, such as
`text-author`, `text-secondary`, or `text-likes` for the tweet designs.

Each template can combine fixed copy with multiple tokens, and a token may be
repeated or reused across fields. Numbers and booleans render as text,
including `0` and `false`. Unknown, malformed, or unfinished tokens render as
empty text. Braces inside a variable's resolved value remain literal text and
are not expanded again. Variables change field contents while preserving
typography, placement, animation, and uploaded graphics.

`titleVariableImageBindings` maps a preset's image slot to exactly one image
token, such as `{ "avatar-image": "{{logo}}" }`. You can use a fixed image
variable or a current-input image reference such as `{{clip.thumbnail}}`.
Image bindings also accept a fixed HTTP(S) image URL or an empty string to
clear the slot. They do not combine multiple tokens or interpolate surrounding
text. The slot retains its authored fitting, crop, and animation.

Available workflow references:

| Reference | Type | Current input value |
| - | - | - |
| `source.title` | text | Source title |
| `source.description` | text | Source description |
| `source.url` | text | Source URL |
| `clip.title` | text | Clip title |
| `clip.description` | text | Clip description |
| `clip.transcript` | text | Clip transcript |
| `clip.keywords` | text | Clip keywords |
| `clip.people` | text | People identified for the clip |
| `clip.duration` | number | Clip duration in seconds |
| `clip.thumbnail` | image | Clip thumbnail URL |

Use text and number keys directly in text templates or generated prompts, for example
`{{source.title}}` or `Summarize these points: {{clip.transcript}}`. For an image
slot, use an image reference. The workflow picker exposes only references
available from upstream inputs, not fields from downstream or disconnected
nodes. Runtime references are refreshed from the current input. Missing or
incompatible references resolve empty; saved sample values cannot stand in for
missing input from another run.

```json theme={null}
{
  "title_config": {
    "titlePresetId": "tweet-overlay",
    "titleVariables": [
      {
        "id": "post",
        "name": "Post body",
        "outputType": "text",
        "prompt": "Summarize the clip's main idea in a conversational post of 15 to 35 words.",
        "value": "Small, consistent improvements add up."
      },
      {
        "id": "speaker",
        "name": "Author",
        "source": "fixed",
        "outputType": "text",
        "prompt": "",
        "value": "Alex Morgan"
      },
      {
        "id": "source_title",
        "name": "Source title",
        "source": "reference",
        "outputType": "text",
        "prompt": "",
        "reference": "source.title"
      },
      {
        "id": "logo",
        "name": "Brand avatar",
        "source": "fixed",
        "outputType": "image",
        "prompt": "",
        "value": "https://cdn.example.com/brand-avatar.png"
      }
    ],
    "titleVariableBindings": {
      "text-primary": "{{post}}",
      "text-author": "{{speaker}}",
      "text-secondary": "From {{source_title}}"
    },
    "titleVariableImageBindings": {
      "avatar-image": "{{logo}}"
    }
  }
}
```

Use the inner `title_config` object as a Style Video title layer's
`layers[].config`, or pass the wrapper under `nodeConfigs.add_title_overlay`.
At run time, generated variables run independently for each clip, fixed values
stay unchanged, and references read the current input. Set
`generateTitle: false` to use generated samples without AI generation; this
does not freeze references.
A primary variable binding supplies the title instead of the legacy headline
prompt. When **Use Source Title** resolves a source title, that exact title
takes precedence for the primary field; supporting variable fields still use
their generated values.

The workflow editor simulates one generated variable using sample inputs from
**Preview workflow values**; Studio uses the current clip's context. Preview
samples do not override the actual input used by a workflow run.
Definitions, text/image bindings, and resolved values are retained with the
saved title so Studio can reopen and edit them. Reusable templates keep the
sources, prompts, fixed values, and bindings for subsequent runs.

#### Styled title templates

Set `titlePresetId` to render one of the built-in styled title templates — the same templates available in the workflow editor's Text panel — instead of the flat title styling. The same fields work inside the top-level `titleConfig` object of the [trigger endpoint](/api-reference/trigger#selecting-a-styled-title-template). The AI-generated title fills the template's primary line, and the template's design (fonts, colors, backplate, animation) is preserved.

Supplying `titlePresetId` selects that template from a clean preset state for the run. Any palette, `presetOverrides`, `presetTextOverrides`, or `presetGenerationBlocks` stored on the workflow's previously selected template are cleared first. The API seeds the template's editor sample text and semantic generation blocks, then applies the fields in your request. This matches selecting a different template in the workflow editor and prevents customizations from the old template leaking into the new one.

Available `titlePresetId` values:

| `titlePresetId` | Description |
| - | - |
| `cyan-block-title` | Bold headline on a solid color block (palettes available) |
| `cyan-divider-title` | Headline with a colored left divider bar (palettes available) |
| `context-caption` | Multi-line highlighted caption stack |
| `cal-sans-pill-title` | Rounded black title card |
| `tiktok-3d` | Offset 3D-border box, TikTok style (palettes available) |
| `instagram-wrap` | Rounded per-line wrapped text |
| `daily-vlog-title` | Handwritten title + subtitle (two lines) |
| `vertical-video-hook` | Featured person name + per-clip editorial hook (two lines) |
| `editorial-masthead` | Editorial section label, serif headline, supporting line, and optional corner logo (6s) |
| `cinematic-chapter` | Centered serif chapter title and fine rules (7s) |
| `launch-card` | Product announcement with a rounded panel and optional logo (6s) |
| `kinetic-stack` | One title wrapping into staggered colored blocks (6s) |
| `quote-spotlight` | Statement card with a separate attribution (7s) |
| `field-notes` | Numbered paper note with a takeaway and supporting line (6s) |
| `broadcast-bulletin` | Bulletin label, headline, context, and optional corner logo (6s) |
| `speaker-spotlight` | Featured speaker name and role with an optional logo (7s) |
| `tweet-card` | Tweet-style body, profile, timestamp, engagement counts, and optional circular avatar on a card background (8s) |
| `tweet-minimal` | Profile image, display name, handle, and post text only; transparent background with no timestamp, logo, or engagement row (8s) |
| `tweet-overlay` | White tweet-style text near the top of a black screen or dark video, with a transparent background (8s) |
| `ios-message` | Messages conversation with one wrapping message, received message, contact name and contact image (8s) |
| `reddit-post` | Reddit post with title, body, community, author and community image (8s) |

The workflow runtime also recognizes these twelve library presets when called
directly with `title_config.titlePresetId`; callers do not need to copy
`presetGenerationBlocks` from the editor. It supplies each preset's default
duration, placement, palette, and semantic generation blocks before applying
caller overrides. Speaker Spotlight generates a featured person's name.
Both tweet variants generate a 15–35 word post body. Supporting text and attribution
fields remain fixed unless explicitly configured for generation.
iOS Text Message generates a 10–25 word message; Reddit Post generates a
6–15 word post title. Both supply a format-specific default prompt, while an
explicit caller prompt takes precedence. Their image slot IDs are
`contact-image` and `community-image`, respectively. iOS palettes are
`imessage`, `sms`, and `dark`; Reddit palettes are `light`, `dark`, and `dim`.

Optional customizations layered on the chosen template:

* `titlePaletteId` — a palette id for templates that define palettes. `cyan-block-title` and `cyan-divider-title`: `breaking-news`, `national-news`, `politics`, `world-news`, `local-news`, `weather`, `entertainment`. `tiktok-3d`: `tiktok`, `grape-lime`, `sunset`. `instagram-wrap`: `clean`, `midnight`, `peach`.
* `presetOverrides` — an object of style/position tweaks applied on top of the template. Supported keys include `fontColor`, `fontFamily`, `fontWeight`, `fontStyle` (`"italic"` / `"normal"`), `textAlign`, `textTransform`, `lineHeight`, `letterSpacing`, `wrapWidth`, `maxLines`, `backgroundColor`, `backgroundStyle`, `padding`, `borderRadius`, `textShadow`, `boxShadow`, and geometry (`xPosition`, `yPosition`, `scale`, `width`, `height`, `rotation`). Positions are `0`–`1` fractions of the frame.
* `presetTextOverrides` — fixed text for a template's secondary line(s), keyed by element id (e.g. `{ "text-secondary": "Episode #4" }` for the Daily Vlog subtitle). The primary line uses the generated title or fixed `text`; a configured variable binding supplies the contents of its bound field.
* `presetOverrides.graphicSources` — image URLs keyed by the preset's image slot: `brand-logo` for the new branded title designs, or `avatar-image` for Tweet Card. Set a source to `""` to remove it. The source is saved with the title and retains its authored placement, fit, and animation.

Example — generate a tweet-style body while supplying the profile and footer:

```json theme={null}
{
  "title_config": {
    "titlePresetId": "tweet-card",
    "titlePaletteId": "light",
    "prompt": "Summarize this clip's central idea as a concise, conversational post.",
    "presetTextOverrides": {
      "text-author": "Your Brand",
      "text-handle": "@yourbrand",
      "text-secondary": "From our latest episode",
      "text-replies": "24",
      "text-reposts": "128",
      "text-likes": "1.2K"
    },
    "presetOverrides": {
      "graphicSources": {
        "avatar-image": "https://cdn.example.com/avatar.png"
      }
    }
  }
}
```

Use this config directly with the title node or under
`nodeConfigs.add_title_overlay` for a workflow trigger. For a Style Video title
layer, place the inner `title_config` object in `layers[].config`. Tweet Card's
palette IDs are `light`, `dim`, and `dark`. For the backgroundless version,
select `tweet-overlay`; it defaults to the `white` palette and `yPosition: 0.22`,
with `blue` and `warm` accent palettes also available. Both versions share the
same text and avatar IDs. Author, handle, timestamp/source, and
counts are editable display values; generation does not retrieve a real post.

Example — a Breaking News headline template, recolored and nudged higher:

```json theme={null}
{
  "nodeConfigs": {
    "add_title_overlay": {
      "title_config": {
        "prompt": "Create a concise, punchy breaking-news headline.",
        "titlePresetId": "cyan-block-title",
        "titlePaletteId": "breaking-news",
        "presetOverrides": {
          "fontColor": "#FFFFFF",
          "textTransform": "uppercase",
          "yPosition": 0.18
        }
      }
    }
  }
}
```

<Info>
  When `titlePresetId` is set, the flat typography/background fields (`fontFamily`, `backgroundColor`, etc.) are ignored — adjust the template with `presetOverrides` instead.
</Info>

### `add_lower_thirds`

Adds a speaker-name lower-third card when each speaker first talks.

Add the **Add Lower Thirds** node to your workflow in the portal and style it there (preset, colours, position). Then name the people in each video on the trigger call with `speaker_names` — the names change every run, the styling does not.

```json theme={null}
{
  "nodeConfigs": {
    "add_lower_thirds": {
      "speaker_names": [
        { "name": "Jamie O'Hara", "title": "Presenter" },
        { "name": "Gabby Agbonlahor", "title": "Former Striker" }
      ]
    }
  }
}
```

**`speaker_names` is positional, ordered by who speaks first.** The first entry names the first person heard in the video, the second entry the second, and so on — the same "Speaker 1 / Speaker 2" model used in the studio editor. `title` is optional; omit it for a name-only card.

To leave one speaker unnamed while naming a later one, pass `null` (or `{}`) in their position so the remaining names stay aligned:

```json theme={null}
{ "speaker_names": [null, { "name": "Gabby Agbonlahor" }] }
```

Cards are timed from the transcript: each appears 1 second after that speaker's first word and runs for the preset's duration. A speaker who is never named, or who never speaks, simply gets no card. When two speakers talk at nearly the same moment, their cards play back to back rather than overlapping.

<Info>
  `speaker_names` is available through the API only — there is no field for it in the workflow builder, because who appears in a video changes with every run.
</Info>

#### Overriding the styling

`lower_thirds_config` overrides the styling set in the builder. It **merges**, so send only what you want to change and everything else is kept:

```json theme={null}
{
  "nodeConfigs": {
    "add_lower_thirds": {
      "speaker_names": [{ "name": "Jamie O'Hara", "title": "Presenter" }],
      "lower_thirds_config": {
        "titlePresetId": "red-accent-lower-third",
        "titlePaletteId": "broadcast-blue",
        "presetOverrides": {
          "fontColor": "#FFFFFF",
          "secondaryTextColor": "#D0D0D0",
          "accentColor": "#0A84FF",
          "cardBackgroundColor": "#101010",
          "xPosition": 0.18,
          "yPosition": 0.74
        }
      }
    }
  }
}
```

| Field | Description |
| - | - |
| `titlePresetId` | Card template. One of `red-accent-lower-third` (default), `graphik-rail-lower-third`, `split-credit`, or `editorial-white-lower-third`. |
| `titlePaletteId` | Colour palette for a preset that offers palettes. The Editorial White preset uses its fixed white design by default. |
| `presetOverrides.fontColor` | Name (primary) text colour. |
| `presetOverrides.secondaryTextColor` | Title/role (secondary) text colour. |
| `presetOverrides.primaryFontSize` | Name font size in pixels. |
| `presetOverrides.secondaryFontSize` | Title/role font size in pixels. |
| `presetOverrides.accentColor` | Accent bar colour for presets with an accent bar. |
| `presetOverrides.cardBackgroundColor` | Background box behind the card. Omit for no box. Editorial White defaults to transparent and uses a dark box when enabled. |
| `presetOverrides.cardPadding` | Text inset inside the Editorial White card, in reference pixels (`0`–`80`). The text fits within the padded area. |
| `presetOverrides.xPosition` / `yPosition` | Card position as a fraction of the frame (`0`–`1`), measured to the card's top-left corner. Lower `yPosition` moves the card up. |
| `presetOverrides.scale`, `width`, `height`, `rotation` | Fine placement adjustments. |

<Info>
  Changing `titlePresetId` resets that preset's colours and palette to their defaults (a colour chosen for one template does not carry to another), but keeps your position. To change template *and* colours in one call, send both in the same request.
</Info>

<Warning>
  If you send `speaker_names` to a workflow that has no **Add Lower Thirds** node, the request is rejected — add the node in the builder first. Everything else about the run is unchanged.
</Warning>

### `filler_words`

Controls filler word, stutter, and silence cleanup.

```json theme={null}
{
  "nodeConfigs": {
    "filler_words": {
      "filler_words_config": {
        "enabled": true,
        "stutteredWordsEnabled": true,
        "silencesEnabled": false,
        "minSilenceDuration": 1,
        "words": ["um", "uh", "like", "you know"]
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `enabled` | boolean | Enables filler word removal. |
| `fromVideo` | boolean | Detects filler words from the video. |
| `minRepetitions` | number | Repetition threshold. |
| `stutteredFromVideo` | boolean | Detects stuttered words from video. |
| `stutteredWordsEnabled` | boolean | Enables stuttered word removal. |
| `silencesEnabled` | boolean | Enables silence removal. |
| `minSilenceDuration` | number | Minimum silence duration to remove. |
| `words` | string\[] | Words or phrases to remove. |

### `smart_zoom`

Controls Smart Zoom.

```json theme={null}
{
  "nodeConfigs": {
    "smart_zoom": {
      "smart_zoom_config": {
        "frequency": "MEDIUM",
        "transition_length": 0.1,
        "additional_instructions": "Prefer zooms when the speaker changes topics."
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `frequency` | string | Smart zoom frequency. |
| `transition_length` | number | Transition length. |
| `additional_instructions` | string | Additional prompt guidance. |

### `add_outro`

Controls end card and outro music.

```json theme={null}
{
  "nodeConfigs": {
    "add_outro": {
      "end_card_option": {
        "url": "public-end-card-image-url",
        "duration": 5,
        "secondsBeforeEnd": 2
      },
      "outro_music_option": {
        "url": "public-outro-music-url",
        "name": "Outro music",
        "secondStart": 0,
        "duration": 5,
        "secondsBeforeEnd": 2,
        "volume": 0.25
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `end_card_option.url` | string | Public end card image URL. |
| `end_card_option.duration` | number | End card duration in seconds. |
| `end_card_option.secondsBeforeEnd` | number | When the end card starts relative to clip end. |
| `outro_music_option.url` | string | Public audio URL. |
| `outro_music_option.name` | string | Display name. |
| `outro_music_option.secondStart` | number | Audio start offset in seconds. |
| `outro_music_option.duration` | number | Audio duration in seconds. |
| `outro_music_option.secondsBeforeEnd` | number | When outro music starts relative to clip end. |
| `outro_music_option.volume` | number | Volume multiplier. |

### `add_audiogram`

Controls audiogram display.

```json theme={null}
{
  "nodeConfigs": {
    "add_audiogram": {
      "template": "farnam",
      "audiogram_config": {
        "frontend": true,
        "source": "custom",
        "orientation": "vertical",
        "audiogramY": 50,
        "audiogramColor": "#000000",
        "backgroundType": "color",
        "backgroundColor": "#000000",
        "backgroundImageUrl": "",
        "textColor": "#FFFFFF",
        "centerText": true,
        "blackBarEnabled": true,
        "subtextEnabled": false,
        "fontWeight": "700"
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `template` | string | Audiogram template/source. |
| `audiogram_config.frontend` | boolean | Keeps audiogram rendering in frontend metadata mode. |
| `audiogram_config.source` | string | Template source. |
| `audiogram_config.orientation` | string | `horizontal` or `vertical`. |
| `audiogram_config.audiogramY` | number | Audiogram vertical position. |
| `audiogram_config.audiogramColor` | string | Waveform color. |
| `audiogram_config.backgroundType` | string | Background mode. |
| `audiogram_config.backgroundColor` | string | Background color. |
| `audiogram_config.backgroundImageUrl` | string | Optional background image URL. |
| `audiogram_config.textColor` | string | Text color. |
| `audiogram_config.centerText` | boolean | Centers title text. |
| `audiogram_config.blackBarEnabled` | boolean | Enables black bar style. |
| `audiogram_config.subtextEnabled` | boolean | Enables subtext. |
| `audiogram_config.fontWeight` | string | Font weight. |

### `remove_watermark`

Controls watermark removal.

```json theme={null}
{
  "nodeConfigs": {
    "remove_watermark": {
      "remove_watermark_config": {
        "enabled": true
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `enabled` | boolean | Enables or disables watermark removal. |
| `timeoutSeconds` | number | Maximum seconds to spend on each clip, including retries while the service is busy. Default `3600`. |
| `maxConcurrency` | integer | Clips processed at once. Default `5`. |

Watermark removal finds logos, watermarks, and sponsor badges placed on top of the video. Captions, subtitles,
lower-third bars, chat overlays, full-width show banners, and anything physically in the scene are left alone. Parts
of the video where the watermark isn't on screen, such as full-screen B-roll, are left untouched.

If removal fails or no watermark is found, the clip passes through unchanged with `watermarkRemovalFailed: true`.

### `add_brainrot`

Controls Brainrot split-screen style.

```json theme={null}
{
  "nodeConfigs": {
    "add_brainrot": {
      "brainrot_config": {
        "category": "minecraft",
        "cropPosition": "bottom",
        "verticalY": 50,
        "videoUrl": "public-background-video-url"
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `category` | string | Brainrot category. |
| `cropPosition` | string | Background crop placement. |
| `randomVideoUrl` | string | Optional randomly selected source URL. |
| `verticalY` | number | Vertical placement. |
| `videoUrl` | string | Public background video URL. |

### `media_overlay`

Controls media overlays.

```json theme={null}
{
  "nodeConfigs": {
    "media_overlay": {
      "media_overlay_config": {
        "mediaUrl": "public-overlay-media-url",
        "opacity": 1,
        "scale": 0.3,
        "xPosition": 50,
        "yPosition": 50,
        "startOffset": 0,
        "endOffset": 0,
        "animationDuration": 1,
        "introTransitionId": "none",
        "outroTransitionId": "fade"
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `mediaUrl` | string | Public image or video URL. |
| `opacity` | number | Overlay opacity. |
| `scale` | number | Overlay scale. |
| `xPosition` | number | Horizontal position. |
| `yPosition` | number | Vertical position. |
| `startOffset` | number | Seconds after the clip starts before the overlay appears. |
| `endOffset` | number | Seconds before the clip ends when the overlay disappears. |
| `animationDuration` | number | Intro/outro transition duration in seconds. |
| `introTransitionId` | string | Optional intro transition preset ID. |
| `outroTransitionId` | string | Optional outro transition preset ID. |

### `remove_curse_words`

Controls curse word handling.

```json theme={null}
{
  "nodeConfigs": {
    "remove_curse_words": {
      "remove_curse_words_config": {
        "enabled": true,
        "mode": "silence",
        "words": ["damn", "hell"],
        "allowedWords": ["dick"]
      }
    }
  }
}
```

Fields:

| Field | Type | Notes |
| - | - | - |
| `enabled` | boolean | Enables curse word handling. |
| `mode` | string | `silence`, `beep`, or `remove`. |
| `words` | string\[] | Words to silence, beep, or remove. |
| `allowedWords` | string\[] | Words that are never censored even when they match the list, such as the surname `Dick`. Matching is case-insensitive and also covers plurals and possessives. |

## Legacy Flat Fields

These flat trigger fields still work and are converted into node configs internally:

| Flat field | Equivalent node override |
| - | - |
| `minLengthTarget` | `find_clips.min_length` |
| `maxLengthTarget` | `find_clips.max_length` |
| `promptAdjustment` | `find_clips.promptAdjustment` |
| `pinnedTimestamps` | `find_clips.pinnedTimestamps` |
| `pinnedTimestampsOnly` | `find_clips.pinnedTimestampsOnly` |
| `pinnedTimestampMode` | `find_clips.pinnedTimestampMode` |
| `musicUrl` | `add_music.background_music_option.url` |
| `broll: true` | `add_broll.enabled` |
| `broll: { ... }` | Merged into `add_broll` |
| `removeFillerWords` | `filler_words.filler_words_config.enabled` |
| `removeStutteredWords` | `filler_words.filler_words_config.stutteredWordsEnabled` |
| `removeSilences` | `filler_words.filler_words_config.silencesEnabled` |
| `subtitleConfig` | `add_subtitles.subtitle_config` and `add_subtitles.subtitle_config.speakerStyles["0"]` |
| `watermarkUrl` | `add_watermark.watermark_config.url` |
| `titleConfig` | `add_title_overlay.title_config` |
| `outroImageUrl` | `add_outro.end_card_option.url` |
| `outroMusicUrl` | `add_music.outro_music_option.url` |

<Card title="Trigger Template" icon="rocket-launch" color="#ff2700" href="/api-reference/trigger">
  Use node config overrides when triggering a workflow template
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.