> This page is for Платформа, version Предыдущая версия.
> 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.

# Обзор пользовательских действий

<Info title="Примеры приложений">
  


Если вы хотите создать собственное приложение с пользовательскими действиями, наши примеры приложений помогут вам начать работу:



</Info>

* [JavaScript](https://github.com/Frameio/custom-actions-example-app)
* [Python](https://github.com/Frameio/custom-actions-app-python)

Пользовательские действия — это способ создания интеграций непосредственно в Frame.io как программируемых компонентов пользовательского интерфейса. Это позволяет создать целый класс рабочих процессов, которые могут быть запущены пользователями в приложении, используя ту же базовую систему маршрутизации событий, что и [Веб-перехватчики](doc:webhooks). В настоящее время пользовательские действия доступны для ресурсов и отображаются в контекстном меню или меню, вызываемом правой кнопки мыши, для любого ресурса, как показано на изображении ниже. <img alt="actions-1" src="/_fern-img/69bc65d3924a350e0c1d5a8062e41b15cbc3b01f1f3b8ec5050356b76aa1989a.webp" />

Ресурс — это надежное представление файла в S3 и его контекста в Frame.io. Включает перекодировки, контекст пользователя/команды/проекта и метаданные. Когда пользователь нажимает пользовательское действие на ресурсе, Frame.io отправляет полезную нагрузку на предоставленный вами URL-адрес. Принимающее приложение может затем ответить с кодом состояния HTTP, чтобы просто подтвердить получение, или может ответить с настраиваемым обратным вызовом, который может выполнить рендеринг дополнительного пользовательского интерфейса в Frame.io.





## Настройка пользовательского действия



<Info title="Проверка разрешений">
  


Чтобы создать пользовательские действия для команды, требуются разрешения менеджера команды. Попросите администратора изменить ваши разрешения, если у вас нет доступа.



</Info>
 Пользовательские действия можно настроить в области [Пользовательские действия](https://developer.frame.io/actions) на [developer.frame.io](/). Для действия требуется:
| Имя поля | Описание |
| ---------- | ---------- |
| Имя | Название, которое вы выбираете для пользовательского действия. Оно будет показано в меню доступных пользовательских действий в Frame.io. |
| Описание | Объясните назначение действия для справки (описание не будет отображаться в веб-приложении Frame.io). |
| Событие | Внутренний ключ события для различения стандартных событий веб-перехватчика и ваших собственных. |
| URL-адрес | Место доставки событий |
| Команда | Команда, которая будет использовать пользовательское действие. |




## Нажмите «Содержимое полезной нагрузки Frame.io»




Когда пользователь нажимает ваше пользовательское действие, полезная нагрузка отправляется на URL-адрес, указанный вами в поле URL.

```json
POST /your/url
{
  "action_id": "2444cccc-7777-4a11-8ddd-05aa45bb956b",
  "interaction_id": "aafa3qq2-c1f6-4111-92b2-4aa64277c33f",
  "project": {
    "id": "a7d6a74b-d45d-4019-9069-24651e0b9f64"
  },
  "resource": {
    "id": "9q2e5555-3a22-44dd-888a-abbb72c3333b",
    "type": "asset"
  },
  "team": {
    "id": "54353cd2-c6ee-4aa1-954a-ce9e19602aa9"
  },
  "type": "my.action",
  "user": {
    "id": "fb57eee0-79f2-4bc7-9b70-99fbc175175c"
  }
}
```




Эту полезную нагрузку можно использовать для определения следующего:




* Какое из ваших пользовательских действий нажато
* Какой ресурс нажат
* Какой пользователь выполнил действие



| Имя поля | Описание |
| ---------- | ---------- |
| `action_id` | Уникальный идентификатор этого действия. Он всегда будет одинаковым для данного действия. |
| `interaction_id` | Это уникальный идентификатор, созданный Frame.io, который можно использовать для отслеживания транзакции. Этот идентификатор будет одинаковым на протяжении всей последовательности действия, включая формы обратного вызова. |
| `тип` | Название события, введенное в поле Event при настройке действия. |
| `resource.id` | Идентификатор ресурса, из которого вы запустили действие (обычно ресурс). |
| `resource.type` | Тип ресурса, из которого вы запустили действие (обычно *ресурс*) |



<Info title="О взаимодействиях">
  `interaction_id` предоставляется как уникальный идентификатор, который поможет вам отслеживать взаимодействие по мере его развития. Если вам не нужно отвечать пользователю, просто верните код состояния 200, и все готово. Хотя это необязательно, мы рекомендуем включить информацию о результате действия, например простое сообщение о выполнении или предупреждение об ошибке. Пользовательские действия поддерживают обратные вызовы сообщений.
</Info>

<Info title="Повторные попытки и таймауты">
  


Наше приложение ожидает ответ менее чем за 5 секунд и будет повторять попытки до 5 раз в ожидании ответа. Лучше всего отвечать незамедлительно и выполнять любые действия асинхронно после запуска через пользовательское действие.



</Info>


## Создание обратного вызова для сообщений

В вашем ответе HTTP на событие веб-перехватчика вы можете вернуть объект JSON, описывающий сообщение, которое будет возвращено инициирующему пользователю в пользовательском интерфейсе Frame.io. Если вы хотите попробовать создать сообщение и посмотреть, как оно будет выглядеть, воспользуйтесь нашим [Custom Action Builder](https://developer.frame.io/app/custom-actions/builder). Он позволяет настраивать обратные вызовы сообщений или формы и сразу видеть, как они будут отображаться в веб-приложении Frame.io.

Пример объекта:

```json
{
  "title": "Success!",
  "description": "The thing worked! Nice."
}
```





Для пользователя отобразится предупреждение, которое выглядит так:

<img alt="actions-3" src="/_fern-img/a7fe1ec18a4467f8b450b31d1e3a70ab26beece9f5ed828166f4d35973e55c3c.webp" />

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

Этого достаточно для многих случаев использования, но иногда начальная полезная нагрузка и последующие вызовы к API-интерфейсу Frame.io не предоставляют достаточно контекста для принимающего приложения. Для таких сценариев мы также поддерживаем **Form Callbacks**.

## Создание обратного вызова для форм




Допустим, требуется дополнительная информация, прежде чем начать процесс. Например, можно добавлять контент в систему, которая требует дополнительных сведений и настроек. Можно «описать» в своем ответе форму, которую пользователь действительно увидит! И заполнит! И она будет отправлена прямо вам!





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

```json
{
  "title": "Need some more info!",
  "description": "Getting ready to submit this file!",
  "fields": [
    {
      "type": "text",
      "label": "Title",
      "name": "title",
      "value": "MyVideo.mp4"
    },
    {
      "type": "select",
      "label": "Captions",
      "name": "captions",
      "options": [
        {
          "name": "Off",
          "value": "off"
        },
        {
          "name": "On",
          "value": "on"
        }
      ]
    }
  ]
}
```

<img alt="actions-form" src="/_fern-img/4538043046be16b30b0230c21291dde8ae51554dc1da719bec8b9f7561c7c8a1.webp" />

Когда пользователь отправит форму, вы получите событие по тому же URL-адресу, что и в исходном запросе POST:

```json
POST /your/url​
{
  "type": "your-specified-event-name",
  "interaction_id": "the-same-id-as-before",
  "action_id": "unique-id-for-this-custom-action",
  "data":{
    "title": "MyVideo.mp4",
    "captions": "off"
  }
}
```

Все настраиваемые поля, которые вы добавили в форму, отображаются в разделе `data` полезной нагрузки JSON, отправляемой Frame.io. Используйте `interaction_id` для сопоставления исходного запроса и этих новых данных формы.Если хотите, можно ответить сообщением (или даже другой формой!).

Связывая действия, формы и сообщения, можно эффективно программировать целые рабочие процессы ресурсов в Frame.io с бизнес-логикой из внешней системы.





Проявите фантазию!Нет никаких ограничений.





### Сведения о форме

Как и сообщения, формы поддерживают атрибуты `заголовок` и `описание`, которые отображаются в верхней части формы. Помимо этого, каждое поле формы принимает следующие базовые атрибуты:
* `тип` — указывает пользовательскому интерфейсу Frame.io, какой тип данных ожидать и рендеринг какого компонента выполнять.
* `метка` — отображается в пользовательском интерфейсе как заголовок над полем.
* `имя` — ключ, по которому поле будет идентифицироваться в последующей полезной нагрузке.
* `значение` — значение для предварительного заполнения поля.




### Поддерживаемые типы полей

**Текстовое поле**

Простое текстовое поле без дополнительных параметров.

```json
{  
  "type": "text",
  "label": "Title",
  "name": "title",
  "value": "MyVideo.mp4"
}
```

**Текстовая область**

Простая текстовая область без дополнительных параметров.

```json
{  
  "type": "textarea",
  "label": "Description",
  "name": "description",
  "value": "This video is really, really popular."
}
```

**Select list**
Defines a picklist that the user can choose from. Must include an `options` list, each member of which should include a human-readable `name`, and a machine-parseable `value`.

```json
{
  "type": "select",
  "label": "Captions",
  "name": "captions",
  "value": "off",
  "options": [
       {
         "name": "Off",
         "value": "off"
       },
       {
         "name": "On",
         "value": "on"
      }
   ]
}
```

` **Список выбора**. Определяет список выбора, из которого пользователь может выбирать.Должен включать список `вариантов`, каждый участник которого должен содержать доступное для чтения пользователем `имя` и `значение`, которое может распознать машина.

```json

{


  

&quot;type&quot;: select&quot;,


  

&quot;label&quot;: &quot;Captions&quot;,


  

&quot;name&quot;: &quot;captions&quot;,


  

&quot;value&quot;: &quot;off&quot;,


  

&quot;options&quot;: [


       

{


         

&quot;name&quot;: &quot;Off&quot;,


         

&quot;value&quot;: &quot;off&quot;


       

},


       

{


         

&quot;name&quot;: &quot;On&quot;,


         

&quot;value&quot;: &quot;on&quot;


      

}


   

]




}

```

## Пользовательские действия и модель разрешений Frame.io

Веб-перехватчики и пользовательские действия имеют специальную модель разрешений: они принадлежат **команде**, а не конкретному пользователю, который существует в команде или учетной записи. Это означает:
* Любой администратор или менеджер команды может cоздать пользовательское действие в команде.
* Любой администратор или менеджер команды может изменить или удалить пользовательское действие, которое существует в команде. После изменения все пользователи сразу увидят результат изменений.




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




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





### Проверка

В запрос `POST` включается следующее:
| Имя | Описание |
| ---------- | ---------- |
| `X-Frameio-Request-Timestamp` | Время запуска пользовательского действия. |
| `X-Frameio-Signature` | Вычисленная подпись |
**Метка времени** — это время подписи запроса на выходе из сети Frame.io. Можно использовать для предотвращения атак повторного воспроизведения. Мы рекомендуем проверять, чтобы это время отличалось от локального времени не более чем на 5 минут. **Подпись** — это хеш HMAC SHA-256, использующий ключ подписи, предоставленный при первом создании пользовательского действия.

#### Проверка подписи



1. Извлечение подписи из заголовков HTTP
2. Создайте сообщение для подписи путем объединения версии, времени доставки и тела запроса

* `v0:timestamp:body`
3. Вычислите подпись HMAC SHA256 с помощью вашего секретного ключа подписи.

*Примечание. К предоставленной подписи добавлен префикс `v0=`. В настоящее время в Frame.io существует только одна версия для подписи запросов. Необходимо добавить этот префикс к вашей вычисленной подписи.
4. Сравните!





**`Python`**

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

def verify_signature(curr_time, req_time, signature, body, secret):
    """
    Verify webhook/custom action 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): Custom Action body from the received POST
        secret (str): The secret for this Custom Action 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
```