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

# List Intro & Outro Templates

> Retrieve every intro and outro overlay template with its fields, default animation, default colours and preview images

Retrieves the intro/outro overlay catalogue: the 27 designs you can name in [`elements_config.intro_outro`](/api-reference/videos/create-narrated-slideshow), plus the nine animation presets that apply to them.

The catalogue is static and identical for every account, so there is nothing to page through and reading it costs no credits. Use it to build a template picker without hardcoding the catalogue: everything the [visual gallery](/api-reference/videos/intro-outro-templates) shows is served here, preview images included.

## Query Parameters

<ParamField query="kind" type="string" default="all">
  Which half of the catalogue to return.

  **Allowed values:** `intro`, `outro`, `all`

  * `intro`: The 15 designs valid in the `intro` slot
  * `outro`: The 12 designs valid in the `outro` slot
  * `all`: Both (default)

  `animations` is returned in full whatever you pass — the presets are the same at both ends.
</ParamField>

## Response

<ResponseField name="templates" type="array" required>
  The designs matching `kind`, intros first.

  <Expandable title="Template properties">
    <ResponseField name="templates[].id" type="string" required>
      The template id, `snake_case`. This is what you send as `templateId` on an overlay selection, and the only handle a design has.
    </ResponseField>

    <ResponseField name="templates[].name" type="string" required>
      English display name, for a picker's label. Presentation only — it is never accepted as `templateId`.
    </ResponseField>

    <ResponseField name="templates[].kind" type="string" required>
      `intro` or `outro`. A design is valid only in its own slot.
    </ResponseField>

    <ResponseField name="templates[].template_version" type="integer" required>
      The version to send as `templateVersion`. Currently `1` for every design.
    </ResponseField>

    <ResponseField name="templates[].default_animation" type="string" required>
      The preset the design was delivered with. `animation` is required on every selection and has no server-side default, so this is a recommendation rather than a fallback.
    </ResponseField>

    <ResponseField name="templates[].fields" type="array" required>
      The inputs the design renders, declared per template. Every intro takes `title` (required) and `subtitle`; the eleven contact-card outros take `agent_name` (required), `contact_line` and `agent_photo`; `custom_image` takes one required image field, also called `custom_image`, and no text at all.

      <Expandable title="Field properties">
        <ResponseField name="templates[].fields[].id" type="string" required>
          The key to use in `values` or `assets`. **A key that is not one of these is accepted and silently ignored**, so read the ids from here rather than guessing.
        </ResponseField>

        <ResponseField name="templates[].fields[].type" type="string" required>
          `text` or `image`.
        </ResponseField>

        <ResponseField name="templates[].fields[].sent_in" type="string" required>
          Which half of the selection carries the value: `values` for text fields, `assets` for image fields (as a public HTTPS URL).
        </ResponseField>

        <ResponseField name="templates[].fields[].required" type="boolean" required>
          Whether the field must be sent. A required field that is missing, empty or whitespace-only is rejected with `400 VALIDATION_ERROR`, whose `details.field` is the field's dotted path (`elements_config.intro_outro.intro.values.<id>` for a text field, `...outro.assets.<id>` for an image field); no task is created. `title` is required on every intro, `agent_name` on the eleven contact-card outros, and `custom_image` on the outro of the same name.
        </ResponseField>

        <ResponseField name="templates[].fields[].max_length" type="integer | null" required>
          Characters the design was drawn to hold, or `null` for an image field. The API accepts strings up to 500 characters; a longer value is fitted down to size rather than refused.
        </ResponseField>

        <ResponseField name="templates[].fields[].default_value" type="string | null" required>
          Sample copy for previewing the design, published so a template picker in your own product has something to show. **It is never rendered.** An optional field you omit draws nothing, exactly as an empty string would, and a required field you omit is a `400 VALIDATION_ERROR`. `null` on image fields.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="templates[].default_colors" type="object" required>
      The colours the design ships with, in the two slots branding repaints.

      <Expandable title="Colour properties">
        <ResponseField name="templates[].default_colors.primary" type="string | null" required>
          Colour of the run the design leads with — an intro's `title`, an outro's `agent_name`. This is what `brandColorPrimary` replaces. `null` on `custom_image`, which draws no type of its own and so has nothing to repaint.
        </ResponseField>

        <ResponseField name="templates[].default_colors.contrast" type="string | null" required>
          Colour of the line beside it — `subtitle`, `contact_line` — and of the rules, frames, brackets and rings the design draws. This is what `brandColorContrast` replaces. `null` on `custom_image`, for the same reason.
        </ResponseField>

        <ResponseField name="templates[].default_colors.plate" type="string | null" required>
          The outro card's own background, and `null` for every intro: an intro declares no surface, so what sits behind its type is your video.

          On the two designs that draw a gradient card (`navy_neon`, `gradient_script`) this is the first stop, which is the tone the name actually sits on.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="templates[].preview_urls" type="object" required>
      Rendered previews of the design, as `landscape` and `portrait` image URLs. Every design has both layouts, and the one that renders follows the video's own shape — `orientation` on the slideshow and living-property endpoints, `format` on land — never a field on the overlay itself.

      <Note>
        Intro previews are drawn on a neutral grey. An intro carries no background of its own, so over your video the type sits on whatever frame it opens on.
      </Note>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="animations" type="array" required>
  The nine animation presets, valid on both slots. A preset is one directional transition: an intro plays it as an exit, an outro as an entrance.

  <Expandable title="Animation properties">
    <ResponseField name="animations[].id" type="string" required>
      The value to send as `animation`.
    </ResponseField>

    <ResponseField name="animations[].description" type="string" required>
      One line describing the motion, written to read correctly at either end.
    </ResponseField>
  </Expandable>
</ResponseField>

## Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.vibepeak.ai/v1/intro-outro/templates?kind=outro \
    -H "Authorization: Bearer vpk_live_xxxxx"
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    'https://api.vibepeak.ai/v1/intro-outro/templates?kind=outro',
    { headers: { Authorization: 'Bearer vpk_live_xxxxx' } }
  );

  const { templates, animations } = await response.json();
  ```

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

  response = requests.get(
      'https://api.vibepeak.ai/v1/intro-outro/templates',
      headers={'Authorization': 'Bearer vpk_live_xxxxx'},
      params={'kind': 'outro'}
  )

  data = response.json()
  ```
</CodeGroup>

## Example Response

```json theme={null}
{
  "templates": [
    {
      "id": "serif_business_card",
      "name": "Serif Business Card",
      "kind": "outro",
      "template_version": 1,
      "default_animation": "slide_up",
      "fields": [
        {
          "id": "agent_name",
          "type": "text",
          "required": true,
          "max_length": 32,
          "default_value": "First Name Last Name",
          "sent_in": "values"
        },
        {
          "id": "contact_line",
          "type": "text",
          "required": false,
          "max_length": 64,
          "default_value": "example@vibepeak.ai · (555) 123-4567",
          "sent_in": "values"
        },
        {
          "id": "agent_photo",
          "type": "image",
          "required": false,
          "max_length": null,
          "default_value": null,
          "sent_in": "assets"
        }
      ],
      "default_colors": {
        "primary": "#040404",
        "contrast": "#A44A20",
        "plate": "#FFFFFF"
      },
      "preview_urls": {
        "landscape": "https://docs.vibepeak.ai/images/intro-outro/outro/serif_business_card.jpg",
        "portrait": "https://docs.vibepeak.ai/images/intro-outro/outro/serif_business_card-portrait.jpg"
      }
    },
    {
      "id": "custom_image",
      "name": "Custom image",
      "kind": "outro",
      "template_version": 1,
      "default_animation": "fade",
      "fields": [
        {
          "id": "custom_image",
          "type": "image",
          "required": true,
          "max_length": null,
          "default_value": null,
          "sent_in": "assets"
        }
      ],
      "default_colors": {
        "primary": null,
        "contrast": null,
        "plate": "#000000"
      },
      "preview_urls": {
        "landscape": "https://docs.vibepeak.ai/images/intro-outro/outro/custom_image.jpg",
        "portrait": "https://docs.vibepeak.ai/images/intro-outro/outro/custom_image-portrait.jpg"
      }
    }
  ],
  "animations": [
    { "id": "fade", "description": "Opacity only. The overlay dissolves without moving." },
    {
      "id": "slide_up",
      "description": "Travels upward: an intro leaves through the top, an outro arrives from below."
    }
  ]
}
```

## Using a template

Take the `id`, the `template_version` and an `animation`, then fill `values` and `assets` with the field ids the response gave you. Every field the response marks `"required": true` must be sent with a non-blank value, and every optional one you leave out simply renders nothing:

```json theme={null}
"elements_config": {
  "enabled": false,
  "intro_outro": {
    "enabled": true,
    "outro": {
      "templateId": "serif_business_card",
      "templateVersion": 1,
      "animation": "slide_up",
      "values": {
        "agent_name": "Alex Rivera",
        "contact_line": "alex@rivera.example · +34 600 000 000"
      },
      "assets": { "agent_photo": "https://example.com/agent-photo.jpg" },
      "brandColorPrimary": "#1A73E8"
    }
  }
}
```

`custom_image` is the one design whose fields do not follow that shape: it has no text field, so `values` stays empty and the whole selection is the image.

```json theme={null}
"elements_config": {
  "enabled": false,
  "intro_outro": {
    "enabled": true,
    "outro": {
      "templateId": "custom_image",
      "templateVersion": 1,
      "animation": "fade",
      "values": {},
      "assets": { "custom_image": "https://example.com/listing-flyer.jpg" }
    }
  }
}
```

<Note>
  `custom_image` is an outro like the other eleven: it covers the same closing window and adds no duration. When the image's aspect ratio differs from the video's, the server extends its background to the video's shape before rendering, so the image is never cropped. That happens while the create request is being accepted, so such a request takes a few seconds, and up to about 25 seconds when the ratios differ. The image must be a JPG, PNG or WEBP of at most 8 MB whose shortest edge is at least 400 px. It costs no extra credits.
</Note>

## Errors

<ResponseField name="INVALID_PARAMETER" type="400">
  `kind` was something other than `intro`, `outro` or `all`.
</ResponseField>
