> This page is for Платформа, version V4 (default).
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - Версия 4 экспериментальная: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - Предыдущая версия: https://next.developer.frame.io/platform/v2/llms.txt

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

# Веб-перехватчики в версии V4

## Что такое веб-перехватчик?

**Веб-перехватчик** — это обратный вызов HTTP типа push, который Frame.io отправляет сразу же, как только в вашей учетной записи \*\* происходит важное событие\*\* (например, завершается перекодирование нового файла, добавляется комментарий или создается проект).

Вместо того чтобы опрашивать API-интерфейс, вы указываете публичный URL-адрес HTTPS. Frame.io в реальном времени отправляет на него полезную нагрузку JSON, что позволяет вам выполнять следующие действия.

#### Синхронизировать метаданные с внешними системами DAM/MAM

#### Отправлять уведомления в каналы Slack или тикет-системы

Подробнее о том, что такое веб-перехватчик и как он работает — на сайте [https://docs.webhook.site/](https://docs.webhook.site/).

## Обзор конечных точек

| **Операция**                                        | **Конечная точка**                                                    | **Подробности**                                       |
| --------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------- |
| **Создание** веб-перехватчика                       | POST /v4/accounts/\{account\_id}/workspaces/\{workspace\_id}/webhooks | Тело с параметрами `name`, `url`, `events[]`          |
| **Список** всех веб-перехватчиков для рабочей среды | GET /v4/accounts/\{account\_id}/workspaces/\{workspace\_id}/webhooks  | Поддерживает разбивку на страницы                     |
| **Отображение** отдельного веб-перехватчика         | GET /v4/webhooks/\{webhook\_id}                                       | Возвращает секретный ключ подписи только при создании |
| **Обновление** веб-перехватчика                     | PATCH /v4/webhooks/\{webhook\_id}                                     | Меняет `url`, `events` или `is_active`                |
| **Удаление** веб-перехватчика                       | DELETE /v4/webhooks/\{webhook\_id}                                    | Немедленно прекращает доставку запросов               |

> **Warning**
>
> **Аутентификация** — все конечные точки V4 требуют токен доступа OAuth 2.0, полученный через Adobe Developer Console. Устаревшие токены разработчика и JWT **не** принимаются.

## Изменения и обновления в Frame V4

> **Info**
>
> Веб-перехватчики, созданные в устаревшей версии, переносятся в V4 со следующими изменениями.
>
> 1. **Структура полезной нагрузки**. Добавлен идентификатор учетной записи в полезную нагрузку.
> 2. **Изменения в конечных точках**. Идентификатор `team_id` больше не передается в полезной нагрузке JSON. Вместо этого он указывается в параметре пути в URL-адресе: `https://api.frame.io/v4/accounts/:account_id/workspaces/:workspace_id/webhooks`.
> 3. **Интеграция с API-интерфейсом**. В связи с изменениями в структуре API-интерфейса, конечных точках и методах аутентификации, любой существующий код для входящих веб-перехватчиков, который выполняет последующие вызовы к API-интерфейсу Frame.io для обогащения данных и поиска ресурсов, потребует обновления.
> 4. **Типы событий**. Веб-перехватчики для ресурсов были разделены на отдельные события для файлов и папок. Любые веб-перехватчики, перенесенные из предыдущей версии с событиями для ресурсов, необходимо обновить, указав соответствующие события для файлов и папок.

> **Warning**
>
> **Статус веб-перехватчиков после миграции**. При переходе вашей учетной записи на Frame.io V4 существующие веб-перехватчики предыдущих версий автоматически отключаются. Это позволяет изменить конечные точки веб-перехватчиков и логику интеграции для работы с обновлениями V4 перед их повторной активацией. Веб-перехватчики, не обновленные для совместимости с V4, при включении без надлежащих изменений будут работать с ошибками. Можно проверить, какие веб-перехватчики неактивны, просмотрев поле `is_active` через API-интерфейс или проверив [настройки веб-перехватчиков](https://next.frame.io/settings/webhooks) перед их повторным включением.

## Подписки на события веб-перехватчиков

При создании и обновлении веб-перехватчиков указывайте, какие именно события вас интересуют. Можно выбрать любое количество событий. Однако обратите внимание, что система работает эффективнее, если вы подписываетесь на меньшее число событий. Логически разделяйте веб-перехватчики, используя разные схемы именования и разные конечные точки. Это позволит вам выстроить бизнес-логику на принимающей стороне так, чтобы тратить меньше ресурсов на фильтрацию и маршрутизацию данных в общих функциях.

> **Note**
>
> Область действия событий. Все события ограничены областью действия рабочей среды, указанной при создании веб-перехватчика. Это означает, что уведомления будут отправляться для действий, совершенных во всех проектах в данной рабочей среде.

### Проекты

| Событие           | Описание                              |
| ----------------- | ------------------------------------- |
| `project.created` | Был **создан** новый проект.          |
| `project.updated` | Были **обновлены** настройки проекта. |
| `project.deleted` | Был **удален** проект.                |

### Файлы

| Событие                 | Описание                                                                                                                                                                                                                                              |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `file.created`          | В Frame.io **создан** файл. *Примечание.* Срабатывает до того, как завершится добавление файла. Если вашему обработчику нужен файл, добавление которого было полностью завершено, рекомендуем вместо этого подписаться на событие `upload.completed`. |
| `file.ready`            | Все перекодировки были **завершены**. Срабатывает после того, как файл был добавлен и обработан.                                                                                                                                                      |
| `file.updated`          | Изменилось имя файла или другая сопутствующая информация.                                                                                                                                                                                             |
| `file.deleted`          | Был **удален** файл (вручную или иным способом).                                                                                                                                                                                                      |
| `file.upload.completed` | Был **добавлен** файл.                                                                                                                                                                                                                                |
| `file.versioned`        | Для файла была **создана** новая версия.                                                                                                                                                                                                              |

### Папки

| Событие          | Описание                            |
| ---------------- | ----------------------------------- |
| `folder.created` | Была **создана** новая папка.       |
| `folder.updated` | Были **обновлены** настройки папки. |
| `folder.deleted` | Была **удалена** папка.             |

### Комментарии

| Событие               | Описание                                                   |
| --------------------- | ---------------------------------------------------------- |
| `comment.created`     | Был **создан** новый комментарий или ответ на комментарий. |
| `comment.updated`     | Был обновлен комментарий.                                  |
| `comment.deleted`     | Был **удален** комментарий.                                |
| `comment.completed`   | Комментарий был отмечен как **выполненный**.               |
| `comment.uncompleted` | Комментарий был отмечен как **невыполненный**.             |

### Метаданные

| Событие                  | Описание                                    |
| ------------------------ | ------------------------------------------- |
| `metadata.value.updated` | Были обновлены поля метаданных для ресурса. |

### Коллекции

| Событие              | Описание                          |
| -------------------- | --------------------------------- |
| `collection.created` | Была **создана** новая коллекция. |
| `collection.updated` | Была **обновлена** коллекция.     |
| `collection.deleted` | Была **удалена** коллекция.       |

### Пользовательские поля

| Событие               | Описание                                      |
| --------------------- | --------------------------------------------- |
| `customfield.created` | Было **создано** новое пользовательское поле. |
| `customfield.updated` | Было **обновлено** пользовательское поле.     |
| `customfield.deleted` | Было **удалено** пользовательское поле.       |

### Общие ресурсы

| Событие         | Описание                           |
| --------------- | ---------------------------------- |
| `share.created` | Был **создан** новый общий ресурс. |
| `share.updated` | Был **обновлен** общий ресурс.     |
| `share.deleted` | Был **удален** общий ресурс.       |
| `share.viewed`  | Был **просмотрен** общий ресурс.   |

## Полезная нагрузка сообщения веб-перехватчика

Полезная нагрузка веб-перехватчиков всегда содержит поле `type`, указывающее на произошедшее событие, и объект `resource`. Объект `resource` содержит тип (`type`) и идентификатор (`ID`) ресурса Frame.io, связанного с событием.

### Пример полезной нагрузки

```json
{
  "account": {
    "id": "6f70f1bd-7e89-4a7e-b4d3-7e576585a181"
  },
  "project": {
    "id": "7e46e495-4444-4555-8649-bee4d391a997"
  },
  "resource": {
    "id": "d3075547-4e64-45f0-ad12-d075660eddd2",
    "type": "file"
  },
  "type": "file.ready",
  "user": {
    "id": "56556a3f-859f-4b38-b6c6-e8625b5da8a5"
  },
  "workspace": {
    "id": "378fcbf7-6f88-4224-8139-6a743ed940b2"
  }
}
```

В приведенном выше примере события `file.created` поле `resource.id` указывает на `ID` созданного файла. Кроме того, в полезную нагрузку включены объекты `workspace`, `project` и `user`, которые содержат связанные идентификаторы `workspace.id`, `project.id` и `user.id`. Их можно использовать для сокращения количества вызовов API-интерфейса путем фильтрации входящих событий или поиска кэшированных данных на вашей стороне.

> **Warning**
>
> **Мы не предоставляем никакой дополнительной информации о ресурсе, на который оформлена подписка, помимо его идентификатора**.
>
> Если вашему приложению требуются дополнительные сведения или контекст, мы рекомендуем выполнить вызов API-интерфейса для поиска подробной информации о запрашиваемых ресурсах.

## Безопасность

По умолчанию все веб-перехватчики имеют неизменяемый секретный ключ подписи, который можно использовать для проверки того, действительно ли запрос исходит от Frame.io.

Полезная нагрузка ответа для настроенного вами веб-перехватчика содержит секретный ключ подписи, уникальный для этого конкретного веб-перехватчика. Он **предоставляется только в первоначальном ответе на создание веб-перехватчика**, поэтому сохраните его в надежном месте — в хранилище секретных ключей или в переменных среды. Используйте его в дальнейшем для проверки того, что веб-перехватчик поступает непосредственно с наших серверов и не был перехвачен или каким-либо образом изменен.

### Проверка подписей веб-перехватчиков

Чтобы защитить интеграцию от атак типа «человек посередине» и атак повторного воспроизведения, важно проверять подпись полезной нагрузки веб-перехватчика. Проверка гарантирует, что полезная нагрузка веб-перехватчика действительно была отправлена платформой Frame.io, а ее содержимое не было изменено при передаче.

В запрос `POST` включаются следующие заголовки HTTP.

| Название заголовка                            | Описание                                                 | Пример                                                                |
| --------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------- |
| `X-Frameio-Request-Timestamp`                 | Временная метка отправки запроса                         | `1604004499`                                                          |
| `X-Frameio-Signature`                         | Вычисленная подпись веб-перехватчика                     | `v0=a77ce6856e609c884575c2fd211d07a9ad1c3f72e19c06ff710e8f086ffca883` |
| `user-agent: &quot;Frame.io V4 API&quot;`     | Пользовательский агент в заголовке для v4                |                                                                       |
| `user-agent: &quot;Frame.io Legacy API&quot;` | Пользовательский агент в заголовке для устаревшей версии |                                                                       |

**`Python`**

```python title="Python"
import hmac
import hashlib

def verify_signature(curr_time, req_time, signature, body, secret):
    """
    Verify Webhook signature
    :Args:
        curr_time (float): Current epoch time
        req_time (float): Request epoch time
        signature (str): Signature provided by the Frame.io API for the given request
        body (str): Webhook body from the received POST
        secret (str): The secret for this Webhook that you saved when you first created it
    """
    if int(curr_time) - int(req_time) < 500:
        message = 'v0:{}:{}'.format(req_time, body)
        calculated_signature = 'v0={}'.format(hmac.new(
            bytes(secret, 'latin-1'),
            msg=bytes(message, 'latin-1'),
            digestmod=hashlib.sha256).hexdigest())
        if calculated_signature == signature:
            return True
    return False
```

**Временная метка** — это системное время Frame.io на момент отправки исходящего веб-перехватчика. Его можно использовать для предотвращения атак [повторного воспроизведения](https://en.wikipedia.org/wiki/Replay_attack). Мы рекомендуем проверять, чтобы это время отличалось от локального времени не более чем на 5 минут. **Подпись** — это хеш HMAC SHA256, использующий ключ подписи, предоставленный при первоначальном создании веб-перехватчика. **Выполните следующие шаги для проверки подписи.**

#### Извлечение подписи

Извлеките подпись из заголовков HTTP.

#### Создание сообщения для подписи

Создайте сообщение для подписи, объединив версию, время доставки и тело запроса в формате `v0:timestamp:body.`

#### Вычисление HMAC SHA256

Вычислите подпись HMAC SHA256 с помощью вашего секретного ключа подписи.

#### Сравнение подписей

Сравните вычисленную вами подпись с той, которая была предоставлена.

> **Note**
>
> Предоставленная подпись имеет префикс `v0=`. В настоящее время в Frame.io существует только одна версия для подписания запросов. Убедитесь, что этот префикс добавлен к вычисленной вами подписи.

## Повторные попытки и ведение журналов

#### Политика повторных попыток

* В общей сложности пять попыток (первоначальная + 4 повторных).

* Экспоненциальная задержка, начинающаяся с 15 с (+ случайное отклонение).

* Статус, отличный от `2xx`, или превышение времени ожидания >5 секунд вызывают повторную попытку.

#### Ведение журнала сбоев

Frame.io ведет **журнал сбоев**, содержащий следующие данные: `webhook_id`, `account_id`, `event_type`, `resource_id`, `user_id`.

## Руководство по веб-перехватчикам

### Шаг 1. Настройка принимающей стороны (выполняется в первую очередь, чтобы узнать свой URL-адрес)

В этом руководстве мы используем сервис [webhook.site](http://webhook.site/), который позволяет легко и быстро развернуть одноразовый приемник веб-перехватчиков. Его можно использовать для проверки полезной нагрузки и отправки базовых ответов без какой-либо реальной бизнес-логики. При первом переходе на сайт [https://webhook.site](https://webhook.site/) для вас создается уникальная конечная точка веб-перехватчика, которую можно сразу скопировать и использовать.

Этот URL-адрес уникален для вашего сеанса.

![Пример шага 1](/_fern-files/frame-io.docs.buildwithfern.com/09ca9e64de4cd7b5b0982e6c2ae5f0978320cd11272b448b7f9f8c2aff1239ab/docs/pages/v4/guides/webhook_site_example.gif)

### Шаг 2. Выбор событий, на которые нужно подписаться

В этом руководстве мы не будем усложнять задачу и настроим подлписку веб-перехватчика только на события `file.created`. Полезная нагрузка JSON, которую мы будем использовать для создания веб-перехватчика, выглядит следующим образом.

```json
{
    "data": {
        "name": "asset.created sample webhook",
        "events": ["file.created"],
        "url": "https://webhook.site/c05f2216-9558-4816-bc09-f77ee7b9de40"
    }
}
```

### Шаг 3. Создание ресурса веб-перехватчика с помощью Postman

Выполните вызов API-интерфейса с помощью Postman для создания ресурса веб-перехватчика, указав в полезной нагрузке конечную точку с сайта [webhook.site](http://webhook.site/).

### Шаг 4. Тестирование

Теперь, когда вы создали подписку веб-перехватчика и настроили конечные точки для его получения, пришло время протестировать систему. Для этого запустите первый веб-перехватчик, выполнив соответствующее действие, которое заставит его сработать.

Поскольку в нашем примере была настроена реакция на триггер `file.created`, мы загрузим новый ресурс в любой проект в пределах той учетной записи и рабочей среды, для которых был создан этот веб-перехватчик.

![Пример шага 4](/_fern-files/frame-io.docs.buildwithfern.com/7503b906ce873425c6477487378fe9c513d5cbddc524754f0e1fe8ba10de5c16/docs/pages/v4/guides/trigger_asset_created_webhook.gif)

## Дополнительные ресурсы

#### [Ngrok](https://ngrok.com/)

**Ngrok** — это прекрасный инструмент для разработчиков, работающих с веб-перехватчиками, которым требуется доступный из интернета публичный URL-адрес. Он создает безопасные туннели из вашей локальной среды в интернет, позволяя локальному серверу принимать полезную нагрузку веб-перехватчиков в реальном времени.

#### [Hookdeck](https://hookdeck.com/)

**Hookdeck** — это платформа, разработанная для надежного управления веб-перехватчиками с помощью надежного шлюза событий. Она централизует обработку веб-перехватчиков, гарантируя, что ни одно событие не будет пропущено, а также предлагает такие функции, как фильтрация, организация очереди и выполнение повторных попыток при сбое веб-перехватчиков.

#### [Webhook.site](https://webhook.site)

**Webhook.site** — это превосходный инструмент для прототипирования и тестирования веб-перехватчиков, который предлагает простую, но мощную платформу для перехвата и анализа запросов HTTP, отправляемых на уникальные, автоматически генерируемые URL-адреса.

#### [Val.town](https://www.val.town/)

**Val.town** — это отличный инструмент для быстрого прототипирования обработчиков веб-перехватчиков, поскольку он упрощает процесс написания, тестирования и развертывания небольших функций на JavaScript и Python прямо из браузера.