Skip to content

Add Clip#

Creates Clips from source media. Use when you want Storyteller to ingest a media URL and create a Clip with optional publish status, categories, collections, thumbnail, and action links.

Clips are created as Published by default. Set the optional per-media PublishStatus metadata to Draft when a Clip needs editorial review, to Published with AvailableUntil when a live Clip should expire, or to Scheduled when it should go live in the future.

  • Workflow ID: add-clip

Basic Usage#

Minimal Example Request#

{
    "workflows": [
        "add-clip"
    ],
    "mediaUrls": [
        "https://cdn.example.com/videos/highlight-001.mp4"
    ],
    "metadata": {
        "https://cdn.example.com/videos/highlight-001.mp4": {
            "Title": "Derby Day Highlight"
        }
    }
}

Because PublishStatus is omitted, this request creates a Published Clip.

Required Metadata#

Key Type Required Remarks
Title string Yes Per-media. Clip title used internally.

Minimal Example Request with Optional Metadata#

{
    "workflows": [
        "add-clip"
    ],
    "mediaUrls": [
        "https://cdn.example.com/videos/highlight-001.mp4"
    ],
    "metadata": {
        "https://cdn.example.com/videos/highlight-001.mp4": {
            "Title": "Derby Day Highlight",
            "DisplayTitle": "Highlight",
            "CreationTime": "2025-10-26T11:41:15+00:00",
            "PublishStatus": "Draft"
        }
    }
}

Optional Basic Metadata#

Key Type Required Remarks
DisplayTitle string No Per-media. Display title shown for the clip. If not provided, defaults to Title.
CreationTime DateTime No Per-media. ISO 8601 creation time; defaults to current time if omitted.
PublishStatus string No Per-media. Exact supported values are Draft, Published, and Scheduled. Defaults to Published when omitted or blank.
AvailableFrom DateTimeOffset No Per-media. Strictly future inclusive start as an ISO 8601 date/time with an offset. Required, and only accepted, when PublishStatus is Scheduled.
AvailableUntil DateTimeOffset or null No Per-media. Optional exclusive end as an ISO 8601 date/time with an offset. Accepted with Published or Scheduled; it must be future for Published and later than AvailableFrom for Scheduled.

Creating a Draft Clip#

Use Draft when the Clip should be fully ingested and available to authorized CMS editors without appearing in published Clip feeds or viewer search. It becomes viewer-facing only after it is published.

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "PublishStatus": "Draft"
    }
  }
}

Values are case-sensitive. Values other than Draft, Published, and Scheduled are rejected.

Draft clears any existing AvailableFrom and AvailableUntil values. Availability fields supplied with Draft are rejected.

Publishing a Clip with an Expiry#

Use Published with an optional future AvailableUntil to make the Clip live immediately and expire it at a precise instant:

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "PublishStatus": "Published",
      "AvailableUntil": "2026-08-12T00:00:00+01:00"
    }
  }
}

Published always clears AvailableFrom. At exactly AvailableUntil, the effective status is Archived and viewer-facing reads exclude the Clip. Storyteller then persists the archive and clears the completed availability window.

Scheduling a Clip#

Availability scheduling must be enabled for the tenant. Use Scheduled with an AvailableFrom value and, optionally, an AvailableUntil value:

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "PublishStatus": "Scheduled",
      "AvailableFrom": "2026-08-04T18:00:00+01:00",
      "AvailableUntil": "2026-08-05T00:00:00+01:00"
    }
  }
}

AvailableFrom must be later than the workflow request time. The window is half-open: the Clip is available at exactly AvailableFrom and unavailable at exactly AvailableUntil. AvailableUntil can be omitted for a schedule with no automatic expiry. Supplied offsets describe an instant and are normalized by Storyteller.

The scheduling feature is checked during tenant-aware workflow processing. If it is not enabled, metadata validation can succeed but the workflow step fails before the Clip is created or updated; use the workflow status endpoint to observe that failure.

Availability fields require an explicit compatible PublishStatus: AvailableFrom requires Scheduled, while AvailableUntil supports Scheduled or Published. When updating an existing Clip:

  • omitting or leaving PublishStatus blank preserves its editorial status and availability dates;
  • Scheduled requires and replaces a strictly future AvailableFrom; omitting AvailableUntil preserves the existing end date, while setting it to null clears the end date;
  • Published publishes immediately and clears AvailableFrom; an explicit future AvailableUntil replaces the end, explicit null clears it, and omission preserves an existing future end;
  • a Published update that would preserve an elapsed end is rejected, so a successful update cannot remain archived by an elapsed window; and
  • Draft removes the Clip from viewer-facing results and clears both availability dates.

cURL Example (Basic)#

curl -X POST "https://integrations.usestoryteller.com/api/workflows/execute" \
  -H "x-storyteller-api-key: $ST_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<'JSON'
{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "DisplayTitle": "Derby Day: 90s Highlight"
    }
  }
}
JSON

Advanced Usage#

Clips can be created with additional metadata to set up more properties to work with optional categories, collections, thumbnail, and action links.

External Identifiers#

Track clips using your own external identifier system:

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "ExternalId": "ext-clip-001"
    }
  }
}

Metadata:

Key Type Remarks
ExternalId string External identifier for the clip asset that can be used for future reference.

Associate primary and secondary action links with clips:

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "PrimaryActionLinkId": "11111111-1111-4111-8111-111111111111",
      "SecondaryActionLinkIds": [
        "22222222-2222-4222-8222-222222222222",
        "33333333-3333-4333-8333-333333333333"
      ]
    }
  }
}

Metadata:

Key Type Remarks
PrimaryActionLinkId Guid Primary action link associated with the clip. Must be a valid GUID of an existing action link.
SecondaryActionLinkIds ArrayOf(Guid) Additional action links. Each must be a valid GUID of an existing action link.

Categories#

Using Existing Categories (by External ID)#

Both CategoryIds and Categories can be used to specify categories by their External IDs.

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "CategoryIds": ["match-highlights", "featured"]
    }
  }
}
{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "Categories": [
        {
          "ExternalId": "match-highlights"
        },
        {
          "ExternalId": "featured"
        }
      ]
    }
  }
}

Creating New Categories#

To create a new category all of it's properties must be specified in Categories:

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "Categories": [
        {
          "ExternalId": "match-highlights",
          "DisplayTitle": "Match Highlights",
          "InternalTitle": "Match Highlights",
          "AvailableForNavigation": true,
          "ShowInClips": false,
          "Type": "Other"
        }
      ]
    }
  }
}

When creating a new category the following must be true:

  • ExternalId is required and must be unique
  • InternalTitle will default to ExternalId if not provided, but must be unique in the system
  • DisplayTitle is optional (defaults to InternalTitle if not provided)
  • ShowInClips must be set to false

Metadata:

Key Type Remarks
CategoryIds ArrayOf(string) Category external IDs to associate with the clip. Categories must already exist.
Categories ArrayOf(object) Rich category objects for creating or referencing categories.

Category Object Properties:

Property Type Required Remarks
ExternalId string Yes Unique external identifier for the category.
DisplayTitle string No Display title shown to users.
InternalTitle string No Internal title for CMS use. Defaults to ExternalId if not provided.
AvailableForNavigation bool No Whether category appears in navigation. Defaults to false.
ShowInClips bool No Whether category is shown in clips list. Defaults to false. Currently only false is supported.
Type string No Category type (e.g., "Other", "Player").

Collections#

Using Existing Collections (by Internal ID)#

Existing Collections can be referenced by their Internal ID specified in the Collections array:

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "Collections": [
        {
          "InternalId": "coll-100"
        }
      ]
    }
  }
}

Creating New Collections#

Editorial collections can be created by specifying the type accordingly:

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "Collections": [
        {
          "InternalId": "coll-100",
          "InternalTitle": "Season 2025 Highlights",
          "DisplayTitle": "Season '25 Highlights",
          "Type": "Editorial"
        }
      ]
    }
  }
}

CategoryBased collections require the CategoryExternalId to be pointing to an existing Category by its External ID. In the following example the existing Category is also added to the Clip so it'll be included in the Collection from the Category.

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "Categories": [
        {
          "ExternalId": "premier-league"
        }
      ],
      "Collections": [
        {
          "InternalId": "coll-100",
          "InternalTitle": "Season 2025 Highlights",
          "DisplayTitle": "Season '25 Highlights",
          "Type": "CategoryBased",
          "CategoryExternalId": "premier-league"
        }
      ]
    }
  }
}

Metadata:

Key Type Remarks
Collections ArrayOf(object) Collections to associate the clip with.

Collection Object Properties:

Property Type Required Remarks
InternalId string Yes* Unique internal identifier.
InternalTitle string No Internal title for CMS use. Defaults to InternalId.
DisplayTitle string No Display title shown to users. Truncated to max length if needed.
Type string Yes Collection type: "Editorial" or "CategoryBased". Editorial collections associate clips directly while Category Based collections include Clips when added to the category.
CategoryExternalId string No Links collection to a category. Required when creating a category-based collection.

Item Metadata#

Add arbitrary key-value metadata to clips:

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "ItemMetadata": {
        "editor": "jdoe",
        "series": "Derby Day",
        "publisher_name": "example-publisher",
        "production_date": "2025-10-01"
      }
    }
  }
}

Metadata:

Key Type Remarks
ItemMetadata object Arbitrary key-value pairs stored as clip metadata. Useful for tracking custom fields.

Custom Thumbnails#

Static Thumbnail URL#

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "ThumbnailUrl": "https://cdn.example.com/images/highlight-001-thumb.jpg"
    }
  }
}

Template-Based Thumbnail#

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "ThumbnailTemplate": "thumb-template-01",
      "TemplateMetadata": {
        "style": "bold",
        "watermark": "on"
      }
    }
  }
}

Template with Custom Thumbnail#

{
  "workflows": ["add-clip"],
  "mediaUrls": ["https://cdn.example.com/videos/highlight-001.mp4"],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "ThumbnailUrl": "https://cdn.example.com/images/highlight-001-thumb.jpg",
      "ThumbnailTemplate": "thumb-template-01",
      "TemplateMetadata": {
        "overlay": "team-logo"
      }
    }
  }
}

Metadata:

Key Type Remarks
ThumbnailUrl string Must be an absolute URL. Used as custom thumbnail or as base image for template.
ThumbnailTemplate string Thumbnail Template ID to apply. Can be used alone (uses auto-generated thumbnail) or with ThumbnailUrl. With a request-level template, ThumbnailUrl is required (see Studio Template Clips).
TemplateMetadata object Template-specific key-value pairs passed to the template processor.

Thumbnail Processing Behavior:

  • ThumbnailUrl only: Sets custom thumbnail directly
  • ThumbnailTemplate only: Applies template to auto-generated thumbnail from video
  • Both: Applies template to provided custom thumbnail URL

Studio Template Clips#

Set the request-level template to the external ID of a Studio template to render each Clip's video from that template instead of ingesting the media URL as the video. The template must be available to the Integrations API and have its template properties configured; each property's payload metadata key names the per-media metadata value that fills it.

{
  "workflows": ["add-clip"],
  "template": "example-clip-template",
  "mediaUrls": ["https://cdn.example.com/images/summary-001.jpg"],
  "metadata": {
    "https://cdn.example.com/images/summary-001.jpg": {
      "Title": "Morning Summary",
      "ExternalId": "summary-001",
      "CheckDuplicateExternalIds": true,
      "ThumbnailUrl": "https://cdn.example.com/images/summary-001-thumb.jpg",
      "ThumbnailTemplate": "example-thumbnail-template",
      "headline": "Three things to know this morning",
      "summary": "A short summary rendered by the template"
    }
  }
}

Template Clip Behavior:

  • Each media URL creates one Clip and starts one Studio render of its video. The media URL is available to the template as the mediaUrl payload metadata key, for example to fill a background image or video.
  • Template values are matched to the template's properties by payload metadata key and must be sent as strings. Required properties without a value fail validation.
  • A text property whose template element is a bulleted or numbered list takes its items as one newline-separated string, for example "First point\nSecond point\nThird point". Each non-blank line becomes one list item, styled like the template's first item, and is shown as plain text: markup in a line is not interpreted.
  • Non-list text values are inserted as HTML, so callers must HTML-encode plain text, for example Fans &amp; Critics &lt;React&gt;. Newline-separated values for list elements are plain text and encoded per item, so don't encode them.
  • Image values use the image's real dimensions; the template's frame, scale and focal point decide the crop. If the image can't be read, the template's sample image dimensions are used.
  • The video's duration is the media's duration for a video media URL, and the tenant's default Clip duration otherwise. A duration value in seconds overrides this only when the template has a duration property and the request sends it.
  • All other Clip metadata applies as for other Clips: ExternalId and CheckDuplicateExternalIds, categories, collections, item metadata, action links, eyebrow and PublishStatus with its availability fields.
  • The workflow finishes once the Clip is created and its render has started. The video renders and processes afterwards, and a Published Clip appears in Clip feeds only once its video is ready. A Draft Clip stays a draft.
  • ThumbnailUrl sets a custom thumbnail, which is used instead of the thumbnail generated from the rendered video.
  • ThumbnailTemplate frames the ThumbnailUrl image with a thumbnail template, which reads it as its thumbnailUrl payload metadata key. With a request-level template it requires a ThumbnailUrl, because the video is still rendering when the thumbnail is made; a request that sends ThumbnailTemplate without ThumbnailUrl is rejected with a validation error. The thumbnail template renders as soon as the Clip is created, and its output stays the Clip's thumbnail when the video finishes rendering. It also receives the request template's values, so a key that both templates name fills both.
  • A request with a template always creates a new Clip. Updating a Clip is not supported with a template; a request that sends both operationId and template is rejected with a validation error.

Complete Advanced Example#

{
  "workflows": ["add-clip"],
  "mediaUrls": [
    "https://cdn.example.com/videos/highlight-001.mp4"
  ],
  "metadata": {
    "https://cdn.example.com/videos/highlight-001.mp4": {
      "Title": "Derby Day Highlight",
      "DisplayTitle": "Derby Day: 90s Highlight",
      "PublishStatus": "Draft",
      "ExternalId": "ext-clip-001",
      "ItemMetadata": {
        "editor": "jdoe",
        "series": "Derby Day",
        "publisher_name": "example-publisher"
      },
      "PrimaryActionLinkId": "11111111-1111-4111-8111-111111111111",
      "SecondaryActionLinkIds": [
        "22222222-2222-4222-8222-222222222222",
        "33333333-3333-4333-8333-333333333333"
      ],
      "CategoryIds": ["match-highlights", "featured"],
      "Categories": [
        {
          "ExternalId": "match-highlights",
          "DisplayTitle": "Match Highlights",
          "InternalTitle": "Match Highlights",
          "AvailableForNavigation": true,
          "ShowInClips": false,
          "Type": "Other"
        }
      ],
      "Collections": [
        {
          "InternalId": "coll-100",
          "InternalTitle": "Season 2025 Highlights",
          "DisplayTitle": "Season '25 Highlights",
          "Type": "Editorial",
          "CategoryExternalId": "featured"
        }
      ],
      "ThumbnailUrl": "https://cdn.example.com/images/highlight-001-thumb.jpg",
      "ThumbnailTemplate": "thumb-template-01",
      "CreationTime": "2025-10-01T10:00:00Z",
      "TemplateMetadata": {
        "style": "bold",
        "watermark": "on"
      }
    }
  },
  "workflowProcessedWebhookUrl": "https://partner.example.com/webhooks/processed",
  "workflowFailedWebhookUrl": "https://partner.example.com/webhooks/failed"
}

Webhooks#

Both workflow completion and failure webhooks are optional but recommended for tracking workflow execution status:

Key Type Required Remarks
workflowProcessedWebhookUrl string No URL called when workflow completes successfully.
workflowFailedWebhookUrl string No URL called when workflow fails.