> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.synthesia.io/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.synthesia.io/docs/_mcp/server.

# Webhook events

> Explore Synthesia’s API webhook events to receive real-time notifications for video processing statuses. Learn how to implement event-driven workflows with video.completed and video.failed events.

All webhook events follow the same pattern. At the top level, there will be two keys: one that describes the event that occurred, and one that contains the event-specific payload.

**`Event`**

```json Event
{
  "type": "video.completed",
  "data": {
    ...
  }
}
```

| Object Keys | Type   | Description                                                              |
| :---------- | :----- | :----------------------------------------------------------------------- |
| **type**    | string | The event type. Available event types: `video.completed`,`video.failed`. |
| **data**    | JSON   | The event payload.                                                       |

## video.completed

The **video.completed** event is sent when a video finishes processing.\
**Note:** This event is *not* sent when a template preview is completed.

<table>
  <thead>
    <tr>
      <th>
        Object Keys
      </th>

      <th>
        Type
      </th>

      <th>
        Description
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>
        **callbackId**
      </td>

      <td>
        string
      </td>

      <td>
        Arbitrary metadata set for the video when creating the video.
      </td>
    </tr>

    <tr>
      <td>
        **captions**
      </td>

      <td>
        JSON
      </td>

      <td>
        A JSON object with time-limited download URLs for the video captions in `vtt` and `srt` formats.
      </td>
    </tr>

    <tr>
      <td>
        **createdAt**
      </td>

      <td>
        integer
      </td>

      <td>
        UNIX timestamp representing the time video was created.
      </td>
    </tr>

    <tr>
      <td>
        **description**
      </td>

      <td>
        string
      </td>

      <td>
        Description of the video (used on the [video's share page](https://share.synthesia.io/606b3b89-fde7-4d0f-bc02-a944998fcb8d)).
      </td>
    </tr>

    <tr>
      <td>
        **download**
      </td>

      <td>
        string
      </td>

      <td>
        A time-limited URL which may be used to download the video.

        This field is only available if the video status is `complete`.
      </td>
    </tr>

    <tr>
      <td>
        **duration**
      </td>

      <td>
        string
      </td>

      <td>
        Duration of the video.

        This field is only available if the video status is `complete`.
      </td>
    </tr>

    <tr>
      <td>
        **id**
      </td>

      <td>
        string
      </td>

      <td>
        Unique identifier for the video.
      </td>
    </tr>

    <tr>
      <td>
        **lastUpdatedAt**
      </td>

      <td>
        integer
      </td>

      <td>
        UNIX timestamp representing the time video was last updated.
      </td>
    </tr>

    <tr>
      <td>
        **status**
      </td>

      <td>
        string
      </td>

      <td>
        Describes the processing status of the video.

        * `in_progress`: the video is being processed.
        * `complete`: the video was processed successfully.
        * `error`: an error occurred during processing.
        * `rejected`: the video was rejected during moderation due to inappropriate content.
      </td>
    </tr>

    <tr>
      <td>
        **title**
      </td>

      <td>
        string
      </td>

      <td>
        Title of the video (used on the [video's share page](https://share.synthesia.io/606b3b89-fde7-4d0f-bc02-a944998fcb8d)).
      </td>
    </tr>

    <tr>
      <td>
        **thumbnail**
      </td>

      <td>
        JSON
      </td>

      <td>
        A JSON object with time-limited download URLs for static (`.jpg`) and animated (`.gif`) video thumbnails.

        This field is only available if the video status is `complete`.\
        If an animated GIF thumbnail is not present, only the URL for the static thumbnail will be returned.
      </td>
    </tr>

    <tr>
      <td>
        **visibility**
      </td>

      <td>
        string
      </td>

      <td>
        Describes the visibility settings of the video.

        * If `public`, the video's share page is active.
        * If `private`, the video's share page is not active; visitors will receive a [404 Not Found response](http://google.com).
      </td>
    </tr>
  </tbody>
</table>

**`Event`**

```json Event
{
  "type": "video.completed",
  "data": {
    ...
  }
}
```

**`video.completed`**

```json video.completed
{
  "data": {
    "callbackId": "john@example.com",
    "captions": {
    	"srt": "https://...",
   	 	"vtt": "https://...",
  	},
    "createdAt": 1602512112,
    "description": "This is my first synthetic video, made with the Synthesia API!",
    "download": "https://...",
    "duration": "0:00:59.000000",
    "id": "1234-...",
    "lastUpdatedAt": 1602512112,
    "status": "complete",
    "thumbnail": {
    	"image": "https://...",
   	 	"gif": "https://...",
  	},
    "title": "Hello, World!",  
    "visibility": "private"
  },
  "type": "video.completed"
}
```

## video.failed

The **video.failed** event is sent when a video fails to process.

| Object Keys     | Type    | Description                                                                                                                   |
| :-------------- | :------ | :---------------------------------------------------------------------------------------------------------------------------- |
| **createdAt**   | integer | UNIX timestamp representing the time video was created.                                                                       |
| **description** | string  | Description of the video (used on the [video's share page](https://share.synthesia.io/606b3b89-fde7-4d0f-bc02-a944998fcb8d)). |
| **id**          | string  | Unique identifier for the video.                                                                                              |
| **message**     | string  | Describes why the video failed to process.                                                                                    |
| **status**      | string  | Describes the processing status of the video (`error`).                                                                       |
| **title**       | string  | Title of the video (used on the [video's share page](https://share.synthesia.io/606b3b89-fde7-4d0f-bc02-a944998fcb8d)).       |

**`Event`**

```json Event
{
  "type": "video.failed",
  "data": {
    ...
  }
}
```

**`video.failed`**

```json video.failed
{
  "data": {
    "id": "1234-...",
    "title": "Hello, World!",
    "description": "This is my first synthetic video, made with the Synthesia API!",
    "status": "error",
    "createdAt": 1602512112,
    "message": "Video failed: User does not have access to Avatar 1234-abcd"
  },
   "type": "video.failed" 
}
```