> For the complete documentation index, see [llms.txt](https://docs.graspil.com/ru/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.graspil.com/ru/api/automations.md).

# Автоматизации

Методы для программного управления автоматизациями (workflows): создание, редактирование, публикация, остановка, просмотр и удаление. Это те же действия, что доступны в личном кабинете в разделе [«Автоматизации»](/ru/app/automations.md) — через API удобно, если вы хотите создавать и менять автоматизации из своей системы, а не вручную через конструктор.

{% hint style="info" %}
Методы автоматизаций доступны только на тарифе **Premium**.
{% endhint %}

### Что такое автоматизация

Автоматизация — это правило вида «когда происходит **X** → сделать **Y**». Например: «когда пользователь совершил событие "оплата" → отправить ему сообщение с благодарностью» или «каждый день в 10:00 → отправить запрос на внешний сервер».

Автоматизация устроена как граф (схема) из узлов:

* **Триггер** — с чего всё начинается. Ровно один на автоматизацию: по событию, по расписанию или вручную.
* **Действие** — что выполнить: отправить сообщение, сделать запрос на внешний сервер, изменить поле пользователя и т.д.
* **Условие** — разветвление: если выполняется условие — выполнение идёт по одной ветке, если нет — по другой (или останавливается).
* **Пауза** — подождать заданное время или подождать, пока пользователь совершит другое событие, и только потом продолжить.

Узлы соединяются друг с другом стрелками («рёбрами») — точно так же, как в визуальном конструкторе автоматизаций в личном кабинете. По сути, через API вы собираете ту же схему, что и мышкой в дашборде, только в виде JSON.

### Как это работает вкратце

1. Вы создаёте автоматизацию — метод `create`. На этом этапе можно указать только название, а схему добавить позже.
2. Через `update` вы сохраняете схему (граф) автоматизации — черновиком. Черновик можно сохранять сколько угодно раз, в нём допускается неполная схема (например, ещё нет ни одного действия).
3. Когда схема готова — публикуете её через `publish` (или сразу при `update` с флагом `activate: true`). При публикации схема строго проверяется: должен быть один триггер, хотя бы одно действие, и все узлы должны быть связаны друг с другом.
4. Опубликованная автоматизация начинает работать самостоятельно — отслеживает свой триггер и выполняет действия. Управлять вручным запуском или следить за исполнением через API в этой версии не нужно — это происходит автоматически.
5. Если нужно временно отключить автоматизацию — `unpublish`. Чтобы посмотреть список и детали — `list` и `get`. Удалить безвозвратно — `delete`.

{% hint style="info" %}
Опубликованная версия схемы никогда не редактируется «на месте» — при любом изменении через `update` создаётся новая версия-черновик, а старая опубликованная версия продолжает работать, пока вы не опубликуете новую.
{% endhint %}

### Авторизация

Если ваш API-ключ привязан к одному боту (обычный ключ из раздела «Мои боты» — см. [Авторизацию](/ru/api/auth.md)) — ничего дополнительно указывать не нужно.

Если вы используете ключ из раздела [«API-ключи»](https://app.graspil.com/api-keys), выданный сразу на несколько ботов — в **каждом** запросе обязательно нужно указать, какого бота касается автоматизация, полем (для `POST`) или параметром (для `GET`) `resource_key`. В отличие от методов рассылок и отчётов, для автоматизаций это поле обязательно всегда, даже если ваш ключ привязан к одному боту.

{% hint style="warning" %}
Ключ должен быть выпущен на ваш аккаунт (тот же, что вы используете для входа в личный кабинет), а не «общий» ключ ресурса без владельца. Если у роли, к которой относится ключ, есть только право на просмотр автоматизаций (без права редактирования) — методы изменения (`create`, `update`, `publish`, `unpublish`, `delete`) вернут ошибку `403`.
{% endhint %}

### Формат ответа

Успешный ответ:

{% code overflow="wrap" %}

```json
{ "ok": true, "data": { ... } }
```

{% endcode %}

Ответ с ошибкой:

{% code overflow="wrap" %}

```json
{ "ok": false, "error": "...", "error_code": 400 }
```

{% endcode %}

***

## Объект автоматизации

Это то, что возвращают методы `create`, `get`, `publish`, `unpublish`, и каждый элемент в `list`.

| Поле                | Тип          | Описание                                       |
| ------------------- | ------------ | ---------------------------------------------- |
| `id`                | string       | ID автоматизации                               |
| `resource_key`      | string       | Бот, к которому привязана автоматизация        |
| `name`              | string       | Название (видно только вам, в дашборде)        |
| `status`            | int          | Статус — см. таблицу ниже                      |
| `trigger_type`      | string       | Тип триггера: `manual`, `event` или `schedule` |
| `graph_definition`  | object       | Текущая опубликованная схема (узлы и связи)    |
| `active_version_id` | string\|null | ID опубликованной версии схемы                 |

#### Статусы автоматизации

| Код | Значение                        |
| --- | ------------------------------- |
| `0` | Черновик — ещё не опубликована  |
| `1` | Активна — работает              |
| `2` | Остановлена (через `unpublish`) |
| `3` | Архивирована                    |
| `4` | Ошибка                          |

Метод `update` дополнительно возвращает объект **версии** — конкретного черновика схемы, который вы редактируете:

| Поле               | Тип    | Описание                                     |
| ------------------ | ------ | -------------------------------------------- |
| `id`               | string | ID версии                                    |
| `workflow_id`      | string | ID автоматизации, которой принадлежит версия |
| `graph_definition` | object | Схема этой версии                            |
| `version_name`     | string | Название версии (для вашего удобства)        |

***

## Схема автоматизации (`graph_definition`)

Схема — это набор узлов (`nodes`) и связей между ними (`edges`):

{% code overflow="wrap" %}

```json
{
  "nodes": [
    { "id": "trigger_1", "type": "trigger", "data": { "trigger_type": "event", "event_ids": [7] } }
  ],
  "edges": [
    { "source": "trigger_1", "target": "action_1" }
  ]
}
```

{% endcode %}

У каждого узла свой `id` (вы придумываете его сами, главное — не повторяться внутри одной схемы) и `type` — один из: `trigger`, `action`, `condition`, `condition_switch`, `wait`, `wait_event`. Содержимое узла (что конкретно он делает) лежит в поле `data` и зависит от типа.

Связи (`edges`) определяют порядок выполнения: `source` — из какого узла, `target` — в какой узел идёт стрелка.

У узла есть необязательное поле `position` (`{ "x": number, "y": number }`) — координаты на холсте визуального редактора. Если его не передать, редактор сам расставит узлы друг за другом без наложения, поэтому при создании схемы через API/агента поле `position` можно не указывать.

{% hint style="info" %}
При сохранении черновика (`update`) схема не обязана быть полной — можно сохранить пустую схему или схему без действий и доделать её позже. Полная проверка (один триггер, хотя бы одно действие, все узлы связаны) включается только при публикации (`publish` или `update` с `activate: true`).
{% endhint %}

Если при публикации схема не прошла проверку, в ответе придёт список ошибок:

{% code overflow="wrap" %}

```json
{
  "ok": false,
  "error": {
    "validation_errors": {
      "global": [
        { "code": "graph.multiple_triggers", "message": "Граф должен содержать ровно один узел-триггер." }
      ],
      "nodes": {
        "trigger_1": [
          { "code": "trigger.no_event", "message": "Для триггера нужно выбрать событие." }
        ]
      }
    }
  }
}
```

{% endcode %}

### Узел-триггер (`trigger`)

С чего начинается выполнение автоматизации. Тип берётся из `data.trigger_type`:

| `trigger_type` | Когда срабатывает                                     | Что нужно указать в `data`                                                                         |
| -------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `manual`       | Запускается вручную (для теста)                       | —                                                                                                  |
| `event`        | Когда пользователь совершил одно из выбранных событий | `event_ids` — массив ID событий из вашего каталога событий                                         |
| `schedule`     | По расписанию                                         | `launch_frequency` (`day`, `week`, `month` или `year`), `launch_time` (время в формате `HH:MM:SS`) |

Пример — запуск по событию с ID `7`:

{% code overflow="wrap" %}

```json
{ "id": "trigger_1", "type": "trigger", "data": { "trigger_type": "event", "event_ids": [7] } }
```

{% endcode %}

{% hint style="info" %}
Для триггеров `event` и `schedule` можно дополнительно сузить аудиторию — например, запускать автоматизацию только для пользователей с определённым языком интерфейса. Это необязательно; формат условий такой же, как у фильтра аудитории рассылок — см. раздел «Аудитория рассылки» в документации по [рассылкам](/ru/api/broadcasts.md).
{% endhint %}

### Узел-действие (`action`)

Что выполнить. Тип берётся из `data.action_type`. Во всех текстовых полях действий можно использовать переменные вида `{{user.first_name}}` или `{{event.value_num}}` — на момент выполнения они автоматически заменятся реальными значениями.

| `action_type`         | Что делает                                   | Что нужно указать в `data`                                                                                                                                                                                          |
| --------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `send_message`        | Отправить сообщение пользователю в Telegram  | `type` (`sendMessage`, `sendPhoto`, `sendVideo` и т.д.) и `message` — содержимое, формат такой же, как у сообщений рассылки, см. раздел «Содержимое сообщения» в документации по [рассылкам](/ru/api/broadcasts.md) |
| `webhook`             | Отправить HTTP-запрос на ваш сервер          | `method` (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`), `url`                                                                                                                                                           |
| `create_event`        | Записать новое событие в аналитику           | `resource_key`, `event_name`                                                                                                                                                                                        |
| `change_custom_field` | Изменить дополнительное поле пользователя    | `field_key`, `operation` (`set`, `increase` или `decrease`), `value`                                                                                                                                                |
| `amocrm` / `bitrix24` | Создать или обновить сделку/контакт в CRM    | `operation`, `integration_key` (заранее настроенная интеграция)                                                                                                                                                     |
| `yandex_metrika`      | Передать офлайн-конверсию в Яндекс.Метрику   | `integration_key`, `id_type`, `id_path`, `target`                                                                                                                                                                   |
| `keitaro`             | Отправить постбэк конверсии в трекер Keitaro | `integration_key`, `subid`, `status`                                                                                                                                                                                |

Кнопка в `message.reply_markup.inline_keyboard` с полем `"workflow_branch": true` и своим `"id"` помечается как ветка сценария — сервер сам проставит ей `callback_data` и свяжет с узлом `wait_event` (см. раздел «Кнопки, продолжающие сценарий» ниже).

#### Интеграции (`amocrm`, `bitrix24`, `yandex_metrika`, `keitaro`)

Эти действия используют заранее настроенную интеграцию из раздела «Интеграции» в личном кабинете — её идентификатор передаётся в `data.integration_key`. Узел только ссылается на интеграцию, сами учётные данные (домен, токен, ID счётчика, postback key) в схеме не хранятся.

**`amocrm`** — создать или обновить сделку в AmoCRM.

| Поле `data`         | Тип    | Описание                                                                                             |
| ------------------- | ------ | ---------------------------------------------------------------------------------------------------- |
| `integration_key`   | string | Ключ интеграции AmoCRM                                                                               |
| `operation`         | string | `create_lead`, `update_lead` или `upload_utm`                                                        |
| `name_template`     | string | Шаблон названия сделки (для `create_lead`/`update_lead`), поддерживает `{{переменные}}`              |
| `user_fields`       | object | Карта `{id_поля_amoCRM: путь_или_шаблон}` — какие поля сделки заполнить и откуда взять значение      |
| `deal_id_path`      | string | Откуда брать ID существующей сделки (для `update_lead`/`upload_utm`); по умолчанию `amo_crm.deal_id` |
| `create_if_missing` | bool   | Для `update_lead` — создать сделку, если не найдена                                                  |
| `include_utms`      | bool   | Подмешать UTM-метки в кастомные поля                                                                 |
| `utm_field_map`     | object | Карта `{utm_параметр: id_поля_amoCRM}`                                                               |
| `dry_run`           | bool   | Не отправлять запрос в AmoCRM, а вернуть тело запроса (для отладки)                                  |

{% code overflow="wrap" %}

```json
{
  "id": "action_amo",
  "type": "action",
  "data": {
    "action_type": "amocrm",
    "integration_key": "amo_main",
    "operation": "create_lead",
    "name_template": "Заявка от {{user.first_name}}",
    "user_fields": { "123456": "{{user.username}}" },
    "include_utms": true,
    "utm_field_map": { "utm_source": "789012" }
  }
}
```

{% endcode %}

**`bitrix24`** — обновить поля сделки/лида/контакта в Bitrix24 (привязка идёт по Telegram ID пользователя через IM-поле).

| Поле `data`       | Тип    | Описание                                                                                       |
| ----------------- | ------ | ---------------------------------------------------------------------------------------------- |
| `integration_key` | string | Ключ интеграции Bitrix24                                                                       |
| `operation`       | string | Сейчас поддерживается только `update_deal`                                                     |
| `update_targets`  | array  | Какие сущности обновлять: `deal`, `lead`, `contact` (можно несколько); по умолчанию `["deal"]` |
| `user_fields`     | object | Карта `{код_поля_Bitrix24: шаблон}`, например `{"COMMENTS": "{{event.value_str}}"}`            |

{% code overflow="wrap" %}

```json
{
  "id": "action_bitrix",
  "type": "action",
  "data": {
    "action_type": "bitrix24",
    "integration_key": "bitrix_main",
    "operation": "update_deal",
    "update_targets": ["deal", "lead"],
    "user_fields": { "UF_CRM_PAID": "{{event.value_num}}" }
  }
}
```

{% endcode %}

**`yandex_metrika`** — передать офлайн-конверсию по CalibratedConversion API.

| Поле `data`          | Тип    | Описание                                                                             |
| -------------------- | ------ | ------------------------------------------------------------------------------------ |
| `integration_key`    | string | Ключ интеграции Яндекс.Метрики (в её настройках задаётся `counter_id`)               |
| `id_type`            | string | Тип идентификатора посетителя: `client_id`, `yclid` или `user_id`                    |
| `id_path`            | string | Шаблон/путь, откуда взять значение идентификатора, например `{{user.ym_client_id}}`  |
| `target`             | string | Шаблон названия цели в Метрике                                                       |
| `date_time_template` | string | Необязательно — шаблон времени конверсии (unix-время); по умолчанию — текущий момент |
| `price_template`     | string | Необязательно — сумма конверсии                                                      |
| `currency`           | string | Необязательно — код валюты, учитывается только вместе с `price_template`             |

{% code overflow="wrap" %}

```json
{
  "id": "action_ym",
  "type": "action",
  "data": {
    "action_type": "yandex_metrika",
    "integration_key": "ym_main",
    "id_type": "client_id",
    "id_path": "{{user.ym_client_id}}",
    "target": "purchase",
    "price_template": "{{event.value_num}}",
    "currency": "RUB"
  }
}
```

{% endcode %}

**`keitaro`** — отправить постбэк конверсии в трекер Keitaro. Трекер сопоставит конверсию с кликом по `subid` (click\_id) и, если у вас настроены его модули, передаст её дальше в Facebook, Google Ads или TikTok — отдельные интеграции с рекламными кабинетами для этого не нужны.

| Поле `data`            | Тип          | Описание                                                                                                                                                                          |
| ---------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `integration_key`      | string       | Ключ интеграции Keitaro (в её настройках задаются домен трекера и postback key)                                                                                                   |
| `subid`                | string       | Откуда взять click\_id. Обычно он приходит в start-параметре ссылки на бота и уводится в дополнительное поле пользователя — тогда это `{{user.addition_fields.keitaro_click_id}}` |
| `status`               | string       | Статус конверсии: `lead`, `sale`, `rejected`, `reg`, `deposit`, `trash` или ваш собственный                                                                                       |
| `payout`               | string       | Необязательно — сумма конверсии. Отправляется, только если получилось число                                                                                                       |
| `currency`             | string       | Необязательно — код валюты; если не задан, берётся валюта по умолчанию из настроек интеграции                                                                                     |
| `tid`                  | string       | Необязательно — идентификатор транзакции: позволяет записать повторную конверсию, не перезаписывая предыдущую                                                                     |
| `extra_params`         | array/object | Необязательно — дополнительные параметры: `sub_id_1`…`sub_id_30`, а также `em`, `ph`, `fn`, `ln` (их Keitaro передаёт в Facebook как данные пользователя). До 40 штук             |
| `subid_pattern`        | string       | Необязательно — регулярное выражение, если click\_id нужно вырезать из строки; берётся первая скобочная группа                                                                    |
| `ignore_missing_subid` | bool         | Необязательно — если click\_id пуст (органический трафик), узел завершится успешно и сценарий продолжится, вместо ошибки                                                          |

{% code overflow="wrap" %}

```json
{
  "id": "action_keitaro",
  "type": "action",
  "data": {
    "action_type": "keitaro",
    "integration_key": "keitaro_main",
    "subid": "{{user.addition_fields.keitaro_click_id}}",
    "status": "sale",
    "payout": "{{event.value_amount}}",
    "currency": "{{event.unit}}",
    "extra_params": [{ "key": "sub_id_1", "value": "{{user.id}}" }],
    "ignore_missing_subid": true
  }
}
```

{% endcode %}

{% hint style="info" %}
Keitaro отвечает успехом и на неизвестный `subid`, поэтому успешно выполненный узел означает, что трекер принял запрос, а не что конверсия привязалась к клику. Ответ трекера сохраняется в логе автоматизации.
{% endhint %}

Пример — отправить сообщение:

{% code overflow="wrap" %}

```json
{
  "id": "action_1",
  "type": "action",
  "data": {
    "action_type": "send_message",
    "type": "sendMessage",
    "message": { "text": "Привет, {{user.first_name}}! Спасибо за покупку." }
  }
}
```

{% endcode %}

Пример — отправить запрос на свой сервер:

{% code overflow="wrap" %}

```json
{
  "id": "action_2",
  "type": "action",
  "data": {
    "action_type": "webhook",
    "method": "POST",
    "url": "https://example.com/webhook",
    "body_template": "{\"user_id\": {{user.id}}}"
  }
}
```

{% endcode %}

### Узел-условие (`condition`)

Разветвляет выполнение: если условие верно — выполнение идёт по одной ветке, если нет — по другой.

{% code overflow="wrap" %}

```json
{ "id": "cond_1", "type": "condition", "data": { "condition": ["and", ["=", "user.is_premium", 1]] } }
```

{% endcode %}

`condition` — вложенный массив: на верхнем уровне `["and"|"or"|"not", ...]`, листья вида `["оператор", "поле", значение]`.

Допустимые поля:

| Префикс                                           | Что это                                                                                                                                                                        | Пример                                                     |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
| `user.*`                                          | Поля профиля пользователя                                                                                                                                                      | `user.first_name`, `user.language_code`, `user.is_premium` |
| `user.custom_fields.*` / `user.addition_fields.*` | Дополнительные поля пользователя, любой ключ                                                                                                                                   | `user.addition_fields.keitaro_click_id`                    |
| `user.cohort`                                     | Принадлежность когорте — только с `in_cohort`/`not_in_cohort`                                                                                                                  | `["in_cohort", "user.cohort", 42]`                         |
| `events.*`                                        | Колонки события, запустившего сценарий                                                                                                                                         | `events.event_id`, `events.value_int`                      |
| `events.properties.*`                             | Произвольные поля из payload события, включая UTM (`events.properties.utm.current` — метки именно этого запуска, `events.properties.utm.last` — «липкие», последние известные) | `events.properties.utm.current`                            |

Операторы: `and` / `or` / `not` (вложенность условий), `=` / `!=` / `>` / `<` / `>=` / `<=` / `like` / `not like` (2 аргумента: поле, значение), `in` / `not in` (2 аргумента: поле, массив значений), `between` / `not between` (3 аргумента: поле, от, до), `is` (2 аргумента: поле, `null`), `in_cohort` / `not_in_cohort` (2 аргумента: `user.cohort`, id когорты).

Ветвление задаётся не в `data`, а рёбрами (`edges`): у узла `condition` должно быть ровно два исходящих ребра — с `sourceHandle: "true"` (условие выполнилось) и `sourceHandle: "false"` (не выполнилось). Ребро без `sourceHandle` или с другим значением никогда не будет выбрано движком выполнения — сценарий молча остановится на этом узле.

{% code overflow="wrap" %}

```json
{
  "edges": [
    { "source": "cond_1", "target": "action_yes", "sourceHandle": "true" },
    { "source": "cond_1", "target": "action_no", "sourceHandle": "false" }
  ]
}
```

{% endcode %}

### Узел switch-условие (`condition_switch`)

Как `condition`, но с произвольным числом именованных веток вместо двух — удобно, когда вариантов больше двух (например, деление по полу или по когорте) и каскад вложенных `condition` неудобен:

{% code overflow="wrap" %}

```json
{
  "id": "switch_1",
  "type": "condition_switch",
  "data": {
    "cases": [
      { "id": "male", "label": "Мужчины", "condition": ["=", "user.gender", 1] },
      { "id": "female", "label": "Женщины", "condition": ["=", "user.gender", 2] }
    ]
  }
}
```

{% endcode %}

Каждый `case` — тот же формат `condition`, что и у обычного узла-условия (см. выше), с уникальным `id` (не может быть `"default"` — имя зарезервировано). Кейсы проверяются по порядку массива, срабатывает первое совпадение.

Рёбра: одно исходящее ребро на каждый `case` с `sourceHandle: "case:<id>"`, и необязательное ребро с `sourceHandle: "default"` — на случай, если ни один `case` не подошёл.

{% code overflow="wrap" %}

```json
{
  "edges": [
    { "source": "switch_1", "target": "action_male", "sourceHandle": "case:male" },
    { "source": "switch_1", "target": "action_female", "sourceHandle": "case:female" },
    { "source": "switch_1", "target": "action_unknown", "sourceHandle": "default" }
  ]
}
```

{% endcode %}

### Узел-пауза (`wait` и `wait_event`)

`wait` — подождать заданное количество секунд перед продолжением:

{% code overflow="wrap" %}

```json
{ "id": "wait_1", "type": "wait", "data": { "seconds": 3600 } }
```

{% endcode %}

`wait_event` — подождать, пока пользователь совершит конкретное событие (`event_key`), но не дольше `timeout` минут:

{% code overflow="wrap" %}

```json
{ "id": "wait_event_1", "type": "wait_event", "data": { "event_key": 12, "timeout": 1440 } }
```

{% endcode %}

#### Кнопки, продолжающие сценарий (`data.buttons`)

Вместо одного `event_key` узел `wait_event` может ждать клик по одной из нескольких inline-кнопок сообщения, отправленного действием `send_message` — то же самое, что в конструкторе называется «кнопка продолжает сценарий», см. [«Автоматизации» → раздел про кнопки](/ru/app/automations.md):

{% code overflow="wrap" %}

```json
{
  "id": "wait_event_1",
  "type": "wait_event",
  "data": {
    "timeout": 1440,
    "buttons": [
      { "button_id": "b1", "event_type_id": 501 },
      { "button_id": "b2", "event_type_id": 502 }
    ]
  }
}
```

{% endcode %}

В этом режиме `event_key` не требуется. Каждая кнопка из `reply_markup.inline_keyboard` сообщения, помеченная полем `"workflow_branch": true` и своим `"id"`, связывается с записью в `data.buttons` по `button_id`; `event_type_id` сервер проставляет автоматически при сохранении. Исходящее ребро для каждой кнопки задаётся как `sourceHandle: "btn:<button_id>"`. В отличие от обычного `wait_event`, кнопочный узел не завершается по таймауту — он продолжает слушать клики и может срабатывать многократно (таймаут просто продлевает ожидание).

### Полный пример: событие → запрос на сервер → сообщение

{% code overflow="wrap" %}

```json
{
  "nodes": [
    { "id": "trigger_1", "type": "trigger", "data": { "trigger_type": "event", "event_ids": [7] } },
    {
      "id": "action_1",
      "type": "action",
      "data": { "action_type": "webhook", "method": "POST", "url": "https://example.com/webhook" }
    },
    {
      "id": "action_2",
      "type": "action",
      "data": {
        "action_type": "send_message",
        "type": "sendMessage",
        "message": { "text": "Привет, {{user.first_name}}!" }
      }
    }
  ],
  "edges": [
    { "source": "trigger_1", "target": "action_1" },
    { "source": "action_1", "target": "action_2" }
  ]
}
```

{% endcode %}

Такой объект передаётся в поле `graph_definition` при вызове `create` или `update`.

***

## Методы

### POST /v1/automations/create

Создаёт новую автоматизацию (изначально в статусе «черновик»).

#### Параметры

| Параметр           | Тип    | Обязательный | Описание                                                            |
| ------------------ | ------ | ------------ | ------------------------------------------------------------------- |
| `resource_key`     | string | да           | См. раздел «Авторизация» выше                                       |
| `name`             | string | да           | Название автоматизации                                              |
| `trigger_type`     | string | нет          | По умолчанию `manual`. Можно указать здесь же или позже через схему |
| `graph_definition` | object | нет          | Схему можно заполнить сразу или позже через `update`                |

#### Пример запроса

{% code overflow="wrap" %}

```json
POST /v1/automations/create
Api-Key: YOUR_API_KEY
Content-Type: application/json

{
  "resource_key": "bot_main",
  "name": "Приветствие после оплаты"
}
```

{% endcode %}

#### Ответ

{% code overflow="wrap" %}

```json
{ "ok": true, "data": { "item": { "id": "a1b2c3", "status": 0, "name": "Приветствие после оплаты", "...": "..." } } }
```

{% endcode %}

***

### POST /v1/automations/update

Сохраняет схему автоматизации (как черновик версии). Если редактируемая версия совпадает с уже опубликованной — система автоматически создаёт новую версию-черновик, не трогая работающую.

#### Параметры

| Параметр           | Тип    | Обязательный              | Описание                                                                                   |
| ------------------ | ------ | ------------------------- | ------------------------------------------------------------------------------------------ |
| `resource_key`     | string | да                        | См. раздел «Авторизация» выше                                                              |
| `id`               | string | да                        | ID версии для редактирования, либо `"0"`, чтобы создать новую версию                       |
| `wid`              | string | да, если `id` равен `"0"` | ID автоматизации, для которой создаётся новая версия                                       |
| `graph_definition` | object | нет                       | Новая схема                                                                                |
| `version_name`     | string | нет                       | Название версии — для вашего удобства                                                      |
| `name`             | string | нет                       | Новое название самой автоматизации                                                         |
| `activate`         | bool   | нет                       | `true` — сразу опубликовать сохранённую версию (с полной проверкой схемы, как у `publish`) |

{% hint style="info" %}
Если передать `activate: true`, а схема не пройдёт полную проверку — версия всё равно будет сохранена как черновик, а в ответе придёт `ok: false` со списком ошибок и `ver_saved: true`.
{% endhint %}

#### Пример запроса

{% code overflow="wrap" %}

```json
POST /v1/automations/update
Api-Key: YOUR_API_KEY
Content-Type: application/json

{
  "resource_key": "bot_main",
  "id": "0",
  "wid": "a1b2c3",
  "graph_definition": {
    "nodes": [
      { "id": "trigger_1", "type": "trigger", "data": { "trigger_type": "event", "event_ids": [7] } }
    ],
    "edges": []
  }
}
```

{% endcode %}

#### Ответ

{% code overflow="wrap" %}

```json
{ "ok": true, "data": { "item": { "id": "v1", "workflow_id": "a1b2c3", "...": "..." }, "workflow": { "id": "a1b2c3", "status": 0, "...": "..." } } }
```

{% endcode %}

***

### POST /v1/automations/publish

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

#### Параметры

| Параметр       | Тип    | Обязательный | Описание                              |
| -------------- | ------ | ------------ | ------------------------------------- |
| `resource_key` | string | да           | См. раздел «Авторизация» выше         |
| `id`           | string | да           | ID автоматизации                      |
| `version_id`   | string | да           | ID версии, которую нужно опубликовать |

#### Пример запроса

{% code overflow="wrap" %}

```json
POST /v1/automations/publish
Api-Key: YOUR_API_KEY
Content-Type: application/json

{ "resource_key": "bot_main", "id": "a1b2c3", "version_id": "v1" }
```

{% endcode %}

#### Ответ

{% code overflow="wrap" %}

```json
{ "ok": true, "data": { "item": { "id": "a1b2c3", "status": 1, "active_version_id": "v1", "...": "..." } } }
```

{% endcode %}

Если схема не прошла проверку — ответ вернёт `ok: false` со списком ошибок в `error.validation_errors` (формат описан в разделе «Схема автоматизации» выше).

***

### POST /v1/automations/unpublish

Останавливает автоматизацию (статус меняется на «остановлена»). Никаких проверок не требует — остановить можно в любой момент.

#### Параметры

| Параметр       | Тип    | Обязательный | Описание                      |
| -------------- | ------ | ------------ | ----------------------------- |
| `resource_key` | string | да           | См. раздел «Авторизация» выше |
| `id`           | string | да           | ID автоматизации              |

#### Пример запроса

{% code overflow="wrap" %}

```json
POST /v1/automations/unpublish
Api-Key: YOUR_API_KEY
Content-Type: application/json

{ "resource_key": "bot_main", "id": "a1b2c3" }
```

{% endcode %}

#### Ответ

{% code overflow="wrap" %}

```json
{ "ok": true, "data": { "item": { "id": "a1b2c3", "status": 2, "...": "..." } } }
```

{% endcode %}

***

### GET /v1/automations/get

Возвращает одну автоматизацию по ID — текущий статус и опубликованную схему.

#### Параметры

| Параметр       | Тип    | Обязательный | Описание                      |
| -------------- | ------ | ------------ | ----------------------------- |
| `resource_key` | string | да           | См. раздел «Авторизация» выше |
| `id`           | string | да           | ID автоматизации              |

#### Пример запроса

{% code overflow="wrap" %}

```
GET /v1/automations/get?resource_key=bot_main&id=a1b2c3
```

{% endcode %}

#### Ответ

{% code overflow="wrap" %}

```json
{ "ok": true, "data": { "item": { "id": "a1b2c3", "status": 1, "...": "..." } } }
```

{% endcode %}

***

### GET /v1/automations/list

Возвращает список автоматизаций бота.

#### Параметры

| Параметр       | Тип    | Обязательный | Описание                                                        |
| -------------- | ------ | ------------ | --------------------------------------------------------------- |
| `resource_key` | string | да           | См. раздел «Авторизация» выше                                   |
| `project_code` | string | нет          | Фильтр по проекту, если автоматизации сгруппированы по проектам |
| `page`         | int    | нет          | Номер страницы, по умолчанию `1`                                |
| `per_page`     | int    | нет          | Количество на странице, по умолчанию `20`, максимум `100`       |

#### Пример запроса

{% code overflow="wrap" %}

```
GET /v1/automations/list?resource_key=bot_main&page=1&per_page=20
```

{% endcode %}

#### Ответ

{% code overflow="wrap" %}

```json
{
  "ok": true,
  "data": {
    "items": [ { "id": "a1b2c3", "status": 1, "name": "Приветствие после оплаты", "...": "..." } ],
    "count": 1,
    "page": 1,
    "page_count": 1
  }
}
```

{% endcode %}

***

### POST /v1/automations/delete

Удаляет автоматизацию безвозвратно, вместе со всеми её версиями. Действие нельзя отменить.

#### Параметры

| Параметр       | Тип    | Обязательный | Описание                      |
| -------------- | ------ | ------------ | ----------------------------- |
| `resource_key` | string | да           | См. раздел «Авторизация» выше |
| `id`           | string | да           | ID автоматизации              |

#### Пример запроса

{% code overflow="wrap" %}

```json
POST /v1/automations/delete
Api-Key: YOUR_API_KEY
Content-Type: application/json

{ "resource_key": "bot_main", "id": "a1b2c3" }
```

{% endcode %}

#### Ответ

{% code overflow="wrap" %}

```json
{ "ok": true, "data": {} }
```

{% endcode %}

***

## Возможные ошибки

| Код   | Когда возникает                                                                                                                     |
| ----- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `400` | Не передан обязательный параметр, либо схема (`graph_definition`) не прошла проверку при публикации                                 |
| `401` | API-ключ не передан или недействителен                                                                                              |
| `403` | Метод недоступен на вашем тарифе (требуется Premium), у ключа нет права на изменение автоматизаций, либо бот недоступен этому ключу |
| `404` | Автоматизация или версия с указанным `id` не найдена                                                                                |
| `500` | Внутренняя ошибка сервера — повторите запрос позже                                                                                  |

**Пример ошибки:**

{% code overflow="wrap" %}

```json
{ "ok": false, "error": "Premium tariff required", "error_code": 403 }
```

{% endcode %}
