Clip events#
Clip webhooks send notifications about Clip creation, supported metadata updates, availability changes, and deletion. Confirm Clip webhook availability for your account with the Storyteller team before enabling an integration.
Notification triggers#
| Configured trigger | When it is used |
|---|---|
| Created | A Clip is created or duplicated: in the CMS, as an Integrations API draft, or by an add-clip workflow or media import. A duplicate has its own Storyteller id. |
| Updated | A supported Clip property changes, or the Clip's media finishes processing. See the list below. |
| Published | A Clip becomes audience-available, through a manual change or its scheduled start. |
| Unpublished | A Clip becomes unavailable, through a manual change or its scheduled end. |
| Deleted | A Clip is deleted. |
Created, Updated, Published, and Unpublished send "eventType": "clip.changed".
Deleted sends "eventType": "clip.deleted". The configured triggers can share
one endpoint. They control when to notify; the body describes current state.
A Clip that is already live when it is created sends Created only. Check
status to see whether it is audience-available. A new Clip's video and
thumbnail are usually still processing when Created is sent, so thumbnailUrl
can be null. An Updated notification follows when processing finishes.
Updated includes:
- changes to
internalTitleordisplayTitlein the base language - changing or resetting a static thumbnail
- adding or removing a category association, including removal caused by content targeting and category corrections Storyteller applies for your account
- changes to the Clip's external ID, primary action, or base-language long description
- a Clip's video or custom thumbnail finishing processing, including after the video is replaced
An operation that leaves these values unchanged does not trigger an update. Maintenance that Storyteller runs for your account can occasionally send Updated when nothing visible has changed; refetching the Clip handles this.
An availability change sends Published or Unpublished if it crosses the availability boundary. If it changes the status or availability window without crossing that boundary, it sends Updated.
Changes only to translations are not update triggers. Editing a category
definition does not send an update for every associated Clip, and editing an
action does not send an update for every Clip that uses it. Updates made
through an add-clip workflow after the Clip was created do not send
notifications.
Payload#
Created, Updated, Published, and Unpublished use the same shape. All four can describe a draft, scheduled, published, or archived Clip, depending on its state when the request is prepared. Example values are illustrative:
{
"id": "11111111-1111-1111-1111-111111111111",
"eventType": "clip.changed",
"externalId": "match-highlights-42",
"internalTitle": "Match 42 — final whistle",
"displayTitle": "The winning moment",
"thumbnailUrl": "https://media.example.com/clip-thumbnail.jpg",
"categories": [
{
"title": "Highlights",
"externalId": "highlights",
"publishAt": null,
"removeAt": null
}
],
"status": "Published",
"availableFrom": "2026-09-15T12:00:00+00:00",
"availableUntil": "2026-09-16T12:00:00+00:00"
}
| Field | Type | Meaning |
|---|---|---|
id |
UUID string | The Storyteller Clip identifier. Keep this as the mapping to your own record. |
eventType |
string | clip.changed for this metadata payload; clip.deleted for deletion. |
externalId |
string or null | The Clip's external identifier, when set. |
internalTitle |
string | The base-language title used to identify the Clip in the CMS. |
displayTitle |
string | The base-language title intended for display to the audience. |
thumbnailUrl |
string or null | The selected static thumbnail URL. It can be null before a usable thumbnail exists. |
categories |
array | Current category associations. An empty array means no associations. |
categories[].title |
string | The category name. |
categories[].externalId |
string or null | The category's external identifier, when set. |
categories[].publishAt |
null | Always null in the current payload. Clip category associations have no schedule. |
categories[].removeAt |
null | Always null in the current payload. Clip category associations have no schedule. |
status |
string | Effective availability: Draft, Scheduled, Published, or Archived. |
availableFrom |
date-time or null | The start of the Clip's availability window. Null means no scheduled start restriction. |
availableUntil |
date-time or null | The end of the Clip's availability window. Null means no scheduled end restriction. |
Date-time values use ISO 8601. The payload contains compact metadata, without video playback URLs, full media details, or translations. The title fields are separate values; neither is filled from the other.
Availability#
The Clip's effective status combines its editorial status with its availability
window:
| Status | Meaning |
|---|---|
Draft |
The Clip is a draft and is not audience-available. |
Scheduled |
The Clip is published editorially, but its availability window has not started. |
Published |
The Clip is published editorially and is within its availability window. |
Archived |
The Clip is archived editorially, or its availability window has ended. |
The start is inclusive and the end is exclusive: a published Clip is available
at availableFrom and unavailable at availableUntil. A draft or archived Clip
remains unavailable even if its timestamps would otherwise allow access.
Scheduled notifications are asynchronous. The receiver may see a later state
by the time the request arrives. Use status to interpret the supplied snapshot,
and follow the synchronization guidance
when current state matters.
Deletion payload#
{
"id": "11111111-1111-1111-1111-111111111111",
"eventType": "clip.deleted"
}
The deletion body contains id and "eventType": "clip.deleted". Keep the mapping
to your own record even if you also use externalId. Repeated deletes should
succeed when the record has already been removed.
Delivery behavior#
Clip requests can include an agreed API key in X-Api-Key. Each request has a
30-second timeout. Failed delivery gets up to three retries with delays of 30,
120, and 600 seconds after successive failures. See
Receiving notifications for response handling,
authentication, and retry limits.