# 08. Интеграции и API

# Конструктор API

<span style="font-weight: 400;">*«API — это продукт. API — это также то, как вы разрабатываете, продаете и доставляете цифровые и все чаще физические продукты своим клиентам»* — Кин Лейн, главный евангелист Postman</span>

---

<span style="font-weight: 400;">Коммуникационная low-code платформа Metabot </span>обладает встроенным конструктором API для организации взаимодействия с внешними системами по REST в соответствии со стандартом OpenAPI 3.

У любого чат-бота, создаваемого на Metabot, есть внутреннее API — для обращений внешних систем к чат-боту, и внешнее API — для обращений чат-бота к внешним системам.

API состоит из **точек интеграции**, называемых **эндпоинтами (endpoints)** или **конечными точками** (точками доступа, точками связи и т.п.)<span style="font-weight: 400;">. Настройка точек интеграции происходит в разделах **Внутреннее** и **Внешнее API** доступное из меню **Настроек бота**.</span>

[![Снимок экрана 2024-02-05 123004.png](https://docs.metabot24.ru/uploads/images/gallery/2024-02/scaled-1680-/UmhXhPFcg3VxtSl4-snimok-ekrana-2024-02-05-123004.png)](https://docs.metabot24.ru/uploads/images/gallery/2024-02/UmhXhPFcg3VxtSl4-snimok-ekrana-2024-02-05-123004.png)

**Внутреннее API** представляет из себя конструктор API для вашего чат-бота. Здесь вы можете создать и кастомизировать ваши точки доступа к чат-боту, задать **алиас (alias)** точки и возвращаемый ответ с помощью JavaScript. В JavaScript можно планировать другие задания в очереди работ чат-бота (асинхронные), а также вызывать внешнее API (колбэк/callback).

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

Кастомное внутреннее API является синхронным, это значит что для возвращения ответа по API не будет планироваться отдельного задания в очереди, поэтому очень важно не делать сложные вычисления в таком API.

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

Если вы хотите получить ответ от внешнего API позже, в момент выполнения отдельного асинхронного «вложенного» задания, то для этого вам необходимо вызвать внешний API в запущенном скрипте или триггере (с помощью внешнего эндпоинта или JS функции api.callEndpoint). Таким образом, вы можете создать любую цепочку связанных заданий и получить результат идентичный вызову коллбеков в необходимых точках.

Вызвать внешнее API можно с помощью JS функции **api.callEndpoint(...)**, подробности смотрите ниже, в разделе с описанием внешнего API.

### Внутреннее API

[![1.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/doLKsWheI27b3RwT-1.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/doLKsWheI27b3RwT-1.png)

#### Структура конечной точки внутреннего API

Описание полей внутреннего эндпоинта представлена в таблице ниже.

<table border="1" id="bkmrk-%D0%A4%D0%BB%D0%B0%D0%B3-%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D0%95%D1%81%D0%BB%D0%B8" style="border-collapse: collapse; width: 100%; height: 900.927px;"><tbody><tr style="height: 29.7917px; background-color: #c2e0f4;"><td style="width: 20.7664%; height: 29.7917px;">Поле</td><td style="width: 79.2336%; height: 29.7917px;">Описание</td></tr><tr style="height: 46.5625px;"><td style="width: 20.7664%; height: 46.5625px;">Флаг активности</td><td style="width: 79.2336%; height: 46.5625px;">Если убрать флаг, то при обращению через API к данному endpoint будет возвращена ошибка.</td></tr><tr style="height: 236.958px;"><td style="width: 20.7664%; height: 236.958px;">Алиас</td><td style="width: 79.2336%; height: 236.958px;">Дополнительный уникальный идентификатор. Используется как часть URL-адреса для обращения к конечной точке через API, а также для вызова в JavaScript функциях.

Разрешенные символы: буква, цифра, подчеркивание, дефис, слэш (косая черта)

Шаблон URL-адреса конечной точки:

https://адресплатформы/api/v1/bots/**{bot\_id}**/call/**{alias}**

Для каждого бота создается свое пространство имен для API, что означает Алиас должен быть уникален в пределах бота.

</td></tr><tr style="height: 528.427px;"><td style="width: 20.7664%; height: 528.427px;">JavaScript для вычисления API ответа (Response Body)

</td><td style="width: 79.2336%; height: 528.427px;">JavaScript для вычисления содержимого API ответа. Данный JS код будет выполнен при обращении к внутреннему API (по алиасу), результат выполнения кода будет являться телом ответа на API запрос.

Это значит, что API ответ вычисляется на основе JavaScript. В JavaScript должен присутствовать ключевой оператор return для возврата значения из JS. Выражение которое указывается после return является ответом (Response Body) на API запрос.

Можно возвращать:

- Строку (будет сконвертирована в json, если формат валидный);
- Массив;
- Объект (в том числе JSON-объект).

Пример:

```JavaScript
return {
  "key": "value",
  "lead_name": lead.getData('name'),
  "request_param_name": request.json.name
};
```

В JS можно выполнять любой код, например обращаться к пользователям, или устанавливать переменные в memory, планировать задания бота (триггеры, рассылки, скрипты), а также вызывать внешнее API c помощью api.callEndpoint или другие методов объекта api: post/get/postJson/getJson/request.

</td></tr><tr style="height: 59.1875px;"><td style="width: 20.7664%; height: 59.1875px;">Комментарий</td><td style="width: 79.2336%; height: 59.1875px;">Любой текст. Доступно указание любых HTML-тэгов.

</td></tr></tbody></table>

<p class="callout warning">На данный момент доступен вызов кастомного внутреннего API только с методом POST и в формате JSON. Методы GET, PUT, PATCH, DELETE не поддерживаются.</p>

[![2.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/ftwxa6XXu4o6Fvpg-2.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/ftwxa6XXu4o6Fvpg-2.png)

<p class="callout info">Список всех конечных точек внутреннего API сортируется по следующим полям: наименование, алиас, id. Поэтому вы можете управлять сортировкой записей изменяя наименование или алиас. В будущем будет добавлена произвольная сортировка.</p>

#### Вызов внутреннего API

Узнать структуру запроса и проверить работу внутреннего API можно c помощью Swagger, доступного по адресу платформы. Если платформа устанавливается в контуре вашей сети, то адрес сервера нужно узнать у вашей ИТ службы.

[API публичного сервиса](https://app.metabot24.com/api/docs.) под управлением нашей команды можно посмотреть по ссылке.

<p class="callout info align-left"><span data-key="b1af53ee4a554b10a4e768bf3c26cc52">Чтобы получить доступ к Swagger к публичному серверу, нужно **[зарегистрировать аккаунт](https://app.metabot24.com/register)** на платформе по ссылке</span><span data-key="5b2399e9298141fb981d00067aed258a">, затем подтвердить электронную почту и авторизоваться на платформе.</span></p>

<p class="callout warning"><span data-key="5b2399e9298141fb981d00067aed258a">**Внимание!** При работе в Swagger платформы будут выполняться реальные API запросы, а не эмуляция API.</span></p>

[![3.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/MohapVGZvUKxJZKJ-3.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/MohapVGZvUKxJZKJ-3.png)

Также проверить работу внутреннего API можно c помощью Postman или любого другого софта для тестирования API.

![4.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/MK433vR9RKhjoGfL-4.png)

##### Параметры запроса

В URL запроса нужно указать идентификатор бота **botId** на платформе и **alias** внутреннего эндпоинта в боте.

В теле запроса размещаются данные запроса, например:

```JSON
{
  "lead_id": 135,
  "ticket_id": 7,
  "trigger_id": 1,
  "trigger_code": "trigger_short_code",
  "script_request_params": {
    "first_param": 7,
    "second_param": {
      "any_key": "any_value"
    }
  }
}
```

С параметрами тела запроса к внутреннему эндпоинту можно ознакомиться в таблице ниже.

<table border="1" id="bkmrk-%D0%9F%D0%BE%D0%BB%D0%B5-%D0%9E%D0%B1%D1%8F%D0%B7%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D1%8C-" style="border-collapse: collapse; width: 100%;"><tbody><tr style="background-color: #c2e0f4;"><td style="width: 20.7682%;">Поле</td><td style="width: 18.0451%;">Обязательность заполнения</td><td style="width: 61.1867%;">Описание</td></tr><tr><td style="width: 20.7682%;">lead\_id

</td><td style="width: 18.0451%;">-

</td><td style="width: 61.1867%;">В JS будет подготовлен и доступен полноценный объект lead, если у лида есть персона, то также будет доступен объект person.</td></tr><tr><td style="width: 20.7682%;">ticket\_id

</td><td style="width: 18.0451%;">-

</td><td style="width: 61.1867%;">В JS будет подготовлен и доступен полноценный объект ticket.</td></tr><tr><td style="width: 20.7682%;">trigger\_id или trigger\_code

</td><td style="width: 18.0451%;">-

</td><td style="width: 61.1867%;">В JS будут доступны переменные triggerId, triggerName.</td></tr><tr><td style="width: 20.7682%;">script\_request\_params

</td><td style="width: 18.0451%;">-

</td><td style="width: 61.1867%;">В JS будет подготовлены и доступны полноценные объекты request и last\_request.</td></tr></tbody></table>

##### Авторизация запросов API

Для авторизации запросов чат-бота используется **Authorization Bearer Token**.

При каждом вызове API добавьте в заголовок авторизации &lt;Access Token&gt;. Параметры заголовков для всех запросов:

```JavaScript
authorization: Bearer <Access Token>
Host: https://app.metabot24.com
```

##### Генерация токена доступа к API

Чтобы получить API токен, нужно создать API пользователя и сгенерировать токен в в Админ-панели Metabot, для этого:

1\. Cоздайте или привяжите нового пользователя в разделе **Пользователи бизнеса**.

[![16.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/ICbyiQWT4Yey5WSg-16.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/ICbyiQWT4Yey5WSg-16.png)

2\. При создании пользователя включаем опцию **Пользователь API** и указываем имя пользователя. Если необходимо указываем роль пользователя и доступ к какому боту нужно получить по API, или оставляем поля по умолчанию.

[![17.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/Fe1i6PYWwUIL6ouv-17.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/Fe1i6PYWwUIL6ouv-17.png)

3\. Нажмите на ссылку **Сгенерировать API-токен**.

[![18.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/8LR3ajAdETKk4YBg-18.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/8LR3ajAdETKk4YBg-18.png)

4\. Скопируйте полученный API-токен и используйте его в ваших запросах.

[![19.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/r4Omh2BFD1riJbtE-19.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/r4Omh2BFD1riJbtE-19.png)

5\. Можете использовать скопированный API-токен для API на странице Swagger (на странице /api/docs). Токен указывается на форме авторизации, которая открывается нажатием на кнопку **Authorize**.

[![20.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/SR6chGXDBrgDTJfx-20.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/SR6chGXDBrgDTJfx-20.png)

<p class="callout info">Если вдруг не найдете опцию создания API токена в вашем аккаунте, запросите токен в поддержке.</p>

### Внешнее API

[![5.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/iTmbNhJvBOIImY87-5.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/iTmbNhJvBOIImY87-5.png)

При создании новой конечной точки открывается окно создания со следующими параметрами:

[![6.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/WUSUpqPVTdfeTzS4-6.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/WUSUpqPVTdfeTzS4-6.png)

[![7.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/gT3v2Uc0wp2st5Wu-7.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/gT3v2Uc0wp2st5Wu-7.png)

#### Вызов внешнего API из чат-бота

Метод для вызова внешнего API из JavaScript:

```JavaScript
api.callEndpoint(
  string $externalApiEndpointCode, 
  string|null $uri = null,
  string|null $method = null, 
  string|null $format = null, 
  array|object|string|null $body = null, 
  array|object|string|null $headers = [],
  array|object|string|null $requestOptions = [], 
  array|object|string|null $httpClientConfig = [], 
  string|null $proxyUrl = null
): array|string|null
```

##### Пример №1 вызова внешнего API из JavaScript

```JavaScript
response = api.callEndpoint("endpoint_1");
```

Параметры переданные в аргументах функции callEndpoint обладают наивысшим приоритетом, т.е. при подготовке параметров они идут перед теми, которые заданы другим способом, например, в настройках конечной точки или с помощью api сеттеров setHeaders / setRequestOptions / и т.д., или системными атрибутами бота.

При этом, все параметры суммируются в порядке приоритетов, за исключением тела запроса $body. Если аргумент $body указан в функции, то JS код из настроек конечной точки не учитывается, и в API в качестве тела запроса будет передано то, что указано в аргументе $body функции callEndpoint.

Таким образом, $body можно вычислить заранее (или хранить где-то в атрибутах или таблице) и передавать в аргументе функции или вычислять его в скрипте который вызывает api.callEndpoint, а не вычислять во вложенном JS самого эндпоинта. Если перекрываем $body — то JS из эндпоита вызываться не будет для вычисления тела запроса, т.к. тело перекрыто аргументом обладающим наивысшим приоритетом.

##### Пример №2 вызова внешнего API из JavaScript с перекрытием $body и других параметров

```
api.setHeaders({"Token": "my token"});
response = api.callEndpoint("endpoint_2", null, 'POST', 'TEXT', "MY BODY TEXT");
```

URL конечной точки заданный в настройках внешнего API (в интерфейсе) будет задействован, только если не указан $uri в аргументах функции (для второго по счету аргумента функции callEndpoint задан параметр null). Таким образом пустая строка в аргументе для URL перекрывает параметры указанные в настройках точки.

#### Структура конечной точки внешнего API

Описание полей внешнего эндпоинта представлена в таблице ниже.

<table border="1" id="bkmrk-%D0%9F%D0%BE%D0%BB%D0%B5-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D0%A4%D0%BB%D0%B0%D0%B3-%D0%B0" style="border-collapse: collapse; width: 100%; height: 1238.42px;"><tbody><tr style="height: 29.7917px; background-color: #c2e0f4;"><td style="width: 21.8804%; height: 29.7917px;">Поле</td><td style="width: 78.1196%; height: 29.7917px;">Описание</td></tr><tr style="height: 46.5833px;"><td style="width: 21.8804%; height: 46.5833px;">Флаг активности</td><td style="width: 78.1196%; height: 46.5833px;">Если убрать флаг, то вызов данного Endpoint не будет выполняться и метод api.callEndpoint(...) вернет null.</td></tr><tr style="height: 169.771px;"><td style="width: 21.8804%; height: 169.771px;">Код</td><td style="width: 78.1196%; height: 169.771px;">Дополнительный уникальный идентификатор. Используется для указания объекта, например, в JavaScript функциях. В этом случае Код, используется как первый аргумент ($externalApiEndpointCode) метода api.callEndpoint(...).

Для каждого бота создается свое пространство имен для внешнего API, это значит что Код должен быть уникален в пределах бота.

</td></tr><tr style="height: 46.5833px;"><td style="width: 21.8804%; height: 46.5833px;">URL конечной точки (Endpoint URL)</td><td style="width: 78.1196%; height: 46.5833px;">Допустимо использование макропеременных.</td></tr><tr style="height: 700.875px;"><td style="width: 21.8804%; height: 700.875px;">JavaScript для вычисления API запроса (Request Body)</td><td style="width: 78.1196%; height: 700.875px;">JavaScript для вычисления содержимого API запроса. Данный скрипт будет выполнен перед обращением к внешнему API, результат выполнения скрипта будет являться телом запроса к внешнему API.

Это значит, что тело API запроса вычисляется на основе JavaScript. В JavaScript должен присутствовать ключевой оператор return для возврата значения из JS. Выражение которое указывается после return является телом API запроса (Request Body).

Можно возвращать:

- Строку (будет сконвертирована в json, если формат валидный);
- Массив;
- Объект (в том числе JSON-объект);
- Любое другое выражение (если в конечной точке указан формат TEXT), для результата вычисления которого возможна автоматическая конвертация в строку (например число или булево).

Пример (если формат запроса JSON):

```JavaScript
return {
  "key": "value",
  "lead_name": lead.getData('name'),
  "request_param_name": request.json.name
};
```

Другой пример (если формат запроса TEXT):

```
let a = false;
return a;
```

В JS можно выполнять любой код, например обращаться к пользователям, или устанавливать переменные в memory, планировать задания бота (триггеры, рассылки, скрипты), а также вызывать внешнее API c помощью api.callEndpoint или другие методов объекта api: post/get/postJson/getJson/request.

</td></tr><tr style="height: 49.25px;"><td style="width: 21.8804%; height: 49.25px;">Метод(тип) HTTP запроса</td><td style="width: 78.1196%; height: 49.25px;">POST / GET / PATCH / и т.д.

</td></tr><tr style="height: 35.3958px;"><td style="width: 21.8804%; height: 35.3958px;">Формат HTTP запроса</td><td style="width: 78.1196%; height: 35.3958px;">JSON / TEXT

</td></tr><tr style="height: 160.167px;"><td style="width: 21.8804%; height: 160.167px;">Заголовки HTTP запроса (HTTP Headers)</td><td style="width: 78.1196%; height: 160.167px;">Заголовки, которые будут переданы в HTTP запросе. В данном поле указывается JSON объект или массив. Допустимо использование макропеременных.

Также, можно воспользоваться JS методом api.setHeaders(...) или передать заголовки HTTP запроса прямо в аргументах функции api.callEndpoint(...). Также доступна установка заголовков HTTP запроса с помощью атрибута бота **sys\_api\_headers**.

##### Пример 1 для HTTP Headers[![8.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/jwcxMvQOrm5th6xo-8.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/jwcxMvQOrm5th6xo-8.png)

В JavaScript устанавливаем memory атрибут:

```JavaScript
memory.setJsonAttr("my_headers", {"token": "my_token"});
```

Далее используем этот атрибут в поле Headers с помощью макроподстановки:

```JavaScript
{{ &$$my_headers }}
```

Обратите внимание, в данном примере выполняется полное заполнение JSON с помощью макроподстановки.

##### Пример 2 для HTTP Headers

[![11.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/ALPD46LO07CSkQ5A-11.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/ALPD46LO07CSkQ5A-11.png)

JavaScript:

```JavaScript
memory.setAttr('someValue', 'my value');
```

Headers:

```JSON
{
     "some_param": "{{ &$someValue }}",
     "other_param": 11
}
```

Обратите внимание, в данном примере выполняется частичная замена JSON с помощью макроподстановки.

##### Пример 3 для HTTP Headers

[![12.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/ySw5mkyQ1bXW9Uaw-12.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/ySw5mkyQ1bXW9Uaw-12.png)

JavaScript:

```JavaScript
memory.setAttr('anyJsonString', ', "param_3": "my new param"');
```

Headers:

```JSON
{
    "some_param": "lead.getAttr('any_lead_param')",
    "other_param": 11
    {{ &$anyJsonString }}
}
```

Обратите внимание, в данном примере выполняется частичная замена JSON с помощью макроподстановки c атрибутом лида, а также подход похожий на конкатенацию строк, где к JSON клеится строка записанная в атрибут anyJsonString.

</td></tr><tr><td style="width: 21.8804%;">Параметры HTTP запроса (HTTP Request Options)</td><td style="width: 78.1196%;">Параметры HTTP запроса. В данном поле указывается JSON объект или массив.

Допустимо использование макропеременных.

Также, можно воспользоваться v8 методом api.setRequestOptions(...) или передать параметры HTTP запроса в аргументах функции api.callEndpoint(...)

Также доступна установка параметров HTTP запроса помощью переменной бота **sys\_api\_request\_options**.

##### Пример 1 для HTTP Request Options

[![13.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/ntkjaJQBDijTLreV-13.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/ntkjaJQBDijTLreV-13.png)

JavaScript:

```JavaScript
memory.setAttr('leadName', lead.getData('name'));
memory.setAttr('addQueryParams', ', "lead_id":' + lead.getData('id'));
```

HTTP Request Options:

```JSON
{
  "query": {
    "lead_name": "{{ &$leadName }}",
    "new_param": 11
    {{ &$addQueryParams }}
  }
}
```

Пример 2 для HTTP Request Options

[![14.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/GDc5baqwamhQAlWF-14.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/GDc5baqwamhQAlWF-14.png)

 JavaScript:

```JavaScript
memory.setJsonAttr('headers', {
  "token": "aasdsad#$%^&*()"
});

memory.setJsonAttr('request_options', {
  "query": {
    "lead_id": lead.getData('id'),
    "lead_name": lead.getData('name'),
    "new_param": 11,
  }
});
```

HTTP Request Options:

```
{{ &$$request_options }}
```

</td></tr><tr><td style="width: 21.8804%;">Конфиг HTTP клиента (HTTP Client Config)</td><td style="width: 78.1196%;">Параметры HTTP клиента.

В данном поле указывается JSON объект или массив.

Допустимо использование макропеременных.

Также, можно воспользоваться v8 методом api.setHttpConfig(...) или передать конфиг HTTP клиента в аргументах функции api.callEndpoint(...)

Также доступна установка конфига HTTP клиента с помощью переменной бота **sys\_api\_http\_client\_config**.

Пример 1 для HTTP Client Config

[![15.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/YjfZ3BQBsdBeid2M-15.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/YjfZ3BQBsdBeid2M-15.png)

</td></tr><tr><td style="width: 21.8804%;">Настройки прокси (Proxy URL)</td><td style="width: 78.1196%;">Используется для того, чтобы обращаться к определенному ресурсу с помощью прокси сервера.

Шаблон для указания прокси:

```
socks5://login:passwd@www.host.com:port
```

Также, можно воспользоваться v8 методом api.setProxyUrl(...) или передать Proxy URL для HTTP запроса в аргументах функции api.callEndpoint(...). Также доступна установка прокси с помощью переменной бота **sys\_api\_proxy\_url**.

</td></tr><tr><td style="width: 21.8804%;">Комментарий</td><td style="width: 78.1196%;">Любой текст. Доступно указание любых HTML-тэгов.

</td></tr></tbody></table>

[![9.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/FRwWoWWC32DRj5Gw-9.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/FRwWoWWC32DRj5Gw-9.png)

<p class="callout info">Список всех конечных точек внешнего API сортируется по следующим полям: наименование, алиас, id. Поэтому вы можете управлять сортировкой записей изменяя наименование или алиас. В будущем будет добавлена произвольная сортировка.</p>

#### Проверка работы внешнего API

Для тестирования внешнего API можно воспользоваться любым онлайн сервисом для отладки вебхуков (или развернуть аналогичный локально):

- [https://stackoverflow.com/questions/5725430/http-test-server-accepting-get-post-requests](https://stackoverflow.com/questions/5725430/http-test-server-accepting-get-post-requests)
- [https://webhook.site](https://webhook.site/)
- [https://pipedream.com/requestbin](https://pipedream.com/requestbin)
- [http://ptsv2.com](http://ptsv2.com/)

Пример:

[![10.png](https://docs.metabot24.ru/uploads/images/gallery/2022-11/scaled-1680-/JzPDqZ6saUf54EAH-10.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-11/JzPDqZ6saUf54EAH-10.png)

<p class="callout info align-left">С API так же можно работать с помощью JS методов. Все методы и их описание вы можете посмотреть в **[Справочнике по функциям JS](https://docs.metabot24.ru/books/07-spravocnik-po-funkciyam-js/page/spravocnik-vsex-funkcii-Cgt#bkmrk-%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-api:~:text=D1%2581%2Dapi-,%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%20%D1%81%20API,-%D0%9C%D0%B5%D1%82%D0%BE%D0%B4%D1%8B%20bot "Справочник всех функций")**</p>

# Глубокая интеграция цифрового диалога в бизнес-процессы: практический гайд

<span style="font-weight: 400;">Для примера мы разберем интеграцию веб-сайта с чат-ботом для Telegram, но все сказанное ниже справедливо для любого мессенджера.</span>

### <span style="font-weight: 400;">Зачем это нужно</span>

<span style="font-weight: 400;">Представьте, что вам необходимо реализовать один или сразу все из представленных ниже сценариев:</span>

- <span style="font-weight: 400;">Привязать веб-сайт к чат-боту, чтобы отправлять уведомления зарегистрированным пользователям веб-сайта прямо в их Telegram, например, сообщать о смене статуса заказа;</span>
- <span style="font-weight: 400;">Привязать веб-сайт к чат-бот, чтобы зарегистрированные пользователи веб-сайта могли работать с вашим веб-сайтом через чат-бот в мессенджере, используя чат-бот как диалоговый пользовательский интерфейс;</span>
- <span style="font-weight: 400;">Авторизоваться или зарегистрироваться на веб-сайте через чат-бот, без ввода логина и пароля на самом веб-сайте;</span>
- <span style="font-weight: 400;">Открыть страницу веб-сайта в чат-боте с графическим интерфейсом, например, показать список товаров;</span>
- <span style="font-weight: 400;">Зарегистрировать пользователя на веб-сайте через чат-бот, </span><span style="font-weight: 400;">чтобы упростить путь пользователя. </span>

<span style="font-weight: 400;">Эти и другие подобные сценарии применения можно реализовать на платформе Metabot с помощью глубокой интеграции мессенджеров и веб-сайта (deep messaging integration). </span><span style="font-weight: 400;">Вам потребуются базовые навыки программирования, умение работать с REST API и немного терпения.</span>

### <span style="font-weight: 400;">Что это даёт</span>

<span style="font-weight: 400;">С помощью глубокой интеграции вы получите следующие возможности:</span>

- <span style="font-weight: 400;">Сможете упростить онбординг пользователей в ваш бизнес/на сайт, тем самым повысить конверсию и снизить стоимость привлечения пользователя;</span>
- <span style="font-weight: 400;">Сможете захватывать пользователей, которые находятся на очень раннем этапе в воронке продаж, например, тех кто не готов к покупке и обычно не регистрируется при переходе по рекламе;</span>
- <span style="font-weight: 400;">Сможете автоматизировать задачи на любых участках пути покупателя;</span>
- <span style="font-weight: 400;">Отправлять уведомления в мессенджер в любой момент.</span>

### <span style="font-weight: 400;">Как это работает </span>

<span style="font-weight: 400;">Все довольно просто! Хотя нам пришлось много потрудиться, чтобы сделать сложное простым.</span>

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

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

Чтобы связать две разных системы вместе, мы будем на фронте последовательно переводить Алису из одного приложения в другое, а на бэке мы свяжем системы с помощью по REST API.

Схематично глубокую интеграцию можно изобразить следующим образом:

<div drawio-diagram="30"><img src="https://docs.metabot24.ru/uploads/images/drawio/2022-07/2hTS5uRz6rF3k7XR-drawing-4-1659123178.png" alt=""/></div>

<span style="font-weight: 400;">Теперь разберем логику интеграции подробнее. </span>

#### <span style="font-weight: 400;">В какой системе хранить ID</span>

<span style="font-weight: 400;">Есть три подхода связать чат-бот и веб-сайт вместе:</span>

- Чат-бот хранит ID пользователя веб-сайта;
- Веб-сайт хранит ID персоны в чат-боте;
- Веб-сайт и чат-бот одновременно хранят ID пользователей другой системы.

<span style="font-weight: 400;">Нет каких-либо жёстких правил для принятия решения о том, как лучше организовать хранение ID и что лучше использовать для идентификации пользователя при вызове API. Делайте как вам удобно, исходя из реалий конкретной ситуации.</span>

<span style="font-weight: 400;">Например, если разработчикам веб-сайта затруднительно внести изменения в базу данных и код веб-сайта, вы можете принять решение хранить ID пользователя сайта у себя в боте, а разработчикам веб-сайта предложить API для отправки сообщений пользователям, используя User Id веб-сайта.</span>

#### <span style="font-weight: 400;">Разница между ID персоны и ID лида</span>

<span style="font-weight: 400;">В терминах Metabot **лид (lead)** — это подписчик на ваш чат-бот (можно сказать bot user), который подключен к конкретному мессенджеру. Лид создается на платформе автоматически в тот момент, когда человек поздоровался с вашим чат-ботом т.е. послал первое сообщение.</span>

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2022-07/scaled-1680-/0PMimage.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-07/0PMimage.png)

<span style="font-weight: 400;">**Персона (Person)** — это запись о конкретном человеке, которая создается вручную разработчиком чат-бота во время регистрации или авторизации в чат-боте. У персоны теоретически может быть несколько лидов т.е. когда один и тот же человек написал в один и тот же чат-бот, подключенный к разным мессенджерам, но такие проекты не так часто встречается. Обычно у людей есть предпочтительный мессенджер, через который они общаются с компанией.</span>

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2022-07/scaled-1680-/lnEimage.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-07/lnEimage.png)

<span style="font-weight: 400;">М</span><span style="font-weight: 400;">ы обычно всегда рекомендуем во время регистрации и авторизации в чат-боте создавать в Metabot персону, привязывать к этой персоне лид и использовать ID персоны для связки с веб-сайтом, потому что это правильно. У вашего приложения должна быть реляционная структура данных, которая независима от того в каких мессенджерах кто предпочитает общается. </span>

<span style="font-weight: 400;">Но если проект простой и не надо сильно заморачиваться, то можете сделать очень просто: храните ID лида на веб-сайте и используйте ID лида для идентификации API запросов. В таком подходе есть свои плюсы. В Metabot вызов триггеров и API завязан на Lead ID, что означает код на стороне чат-бота существенно упрощается — вам не нужно будет писать прослойку, которая будет по ID персоны в боте или ID пользователя сайта будет искать ID лида, чтобы в этот лид отправить сообщение – вам достаточно вызвать API для отправки сообщения, указав конкретный лид.</span>

#### Таблица соответствия

<span style="font-weight: 400;">Для хранения данных соответствия ID в двух системах мы рекомендуем создать кастомную таблицу</span><span style="font-weight: 400;">. Назовите эту таблицу например, **web\_users** (веб-пользователи).</span>

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2022-07/scaled-1680-/oABimage.png)](https://docs.metabot24.ru/uploads/images/gallery/2022-07/oABimage.png)

<span style="font-weight: 400;">Ниже описан технический процесс организации совместной работы веб-сайта и мобильного приложения, которым является мессенджер, с помощью чат-бота:</span>

1. <span style="font-weight: 400;">В таблицу добавляем поле с хэшом ID персоны, чтобы не передавать ID персоны в явном виде в ссылках (для безопасности).</span>
2. <span style="font-weight: 400;">Также в таблицу добавляем поле PIN код, которое будем формировать случайным образом в чат-боте и затем просить ввести PIN на сайте для подтверждения идентификации.</span>

#### <span style="font-weight: 400;">Ссылка в боте для перехода на сайт</span>

<span style="font-weight: 400;">Для авторизации пользователя на сайте через чат-бот, формируйте временный PIN код и присылайте его в чат-бот с инструкциями для пользователя о том, что нужно перейти на сайт по ссылке и ввести PIN.</span>

<span style="font-weight: 400;">Сразу же присылайте ссылку на сайт, добавляя в нее GET параметр с хэшом персоны. Хэш персоны позволит сайту идентифицировать пришедшего пользователя из бота, без необходимости спрашивать логин и пароль, но нужно только проверить, что пользователь ввел именно тот PIN, который получил в чат-боте.</span>

<span style="font-weight: 400;">После формирования значений, сохраните данные в таблицу соответствия web\_users.</span>

<span style="font-weight: 400;">Cсылка для перехода на сайт может выглядеть, например, следующим образом: </span>[<span style="font-weight: 400;">https://site.com?buid=ZRvJxYsn6Vr2sQVQ</span>](https://site.com?buid=ZRvJxYsn6Vr2sQVQ)<span style="font-weight: 400;">, где BUID — акроним от Bot User ID.</span>

#### <span style="font-weight: 400;">Подтверждение PIN-кода </span>

<span style="font-weight: 400;">В роутере разработчик сайта добавляет код, который при наличии параметра BUID загружает страницу для ввода PIN кода. После ввода, сайт на бэке по REST API проверяет валидность PIN, отправляя в бот три параметра:</span>

- <span style="font-weight: 400;">**BUID** — хэш ID персоны в чат-боте;</span>
- <span style="font-weight: 400;">**PIN** — введённый пользователем код;</span>
- <span style="font-weight: 400;">**ID** — ID пользователя сайта, если пользователь в текущий момент уже авторизован на сайте.</span>

<span style="font-weight: 400;">Чтобы обработать API запрос на валидацию PIN-кода со стороны чат-бота, в чат-боте создайте внутренний API Endpoint. Metabot поддерживает создание двух видов эндпоинтов: внутренних и внешних. В</span><span style="font-weight: 400;">нутренние предназначены для обращения внешних систем к вашему боту, а внешние, наоборот, для обращения из вашего ботом к внешним системам.</span>

<span style="font-weight: 400;"> Назовите эндпоинт, например, **authorize** (авторизация). Напишите код, который в таблице web\_users будет искать запись с нужным нам BUID и проверит PIN на правильность. Если запись найдена, то сообщаем сайту об успехе, или в противном случае о провале.</span>

<span style="font-weight: 400;">Рассмотрим вероятные сценарии, представленные ранее на упрощенной схеме и дополненные новыми:</span>

- **PIN не верный**: 
    - <span style="font-weight: 400;">Это означает перед нами либо пользователь, который ошибся в воде кода, либо злоумышленник, пытавшийся взломать чужой аккаунт, либо неосторожный пользователь, который по тем или иным причинам переслал страницу ввода PIN кода другому человеку;</span>
    - <span style="font-weight: 400;">В этом случае, на сайте нужно обработать ответ от бота, например, показав соответствующие сообщения об ошибке (например, что PIN истек) и предложить выслать новый PIN в мессенджер;</span>
    - <span style="font-weight: 400;">Или же можете создать новый PIN на лету и выслать его пользователю в чат-бот;</span>
- **user\_id есть в web\_users, но нет в запросе**: 
    - <span style="font-weight: 400;">Это означает, что пользователь веб-сайта привязан к чат-боту. Возвращаем user\_id в ответе, чтобы веб-сайт авторизовал пользователя;</span>
- <span style="font-weight: 400;">**user\_id есть в web\_users и есть в запросе**:</span>
    - <span style="font-weight: 400;">Если user\_id совпадают, то это означает, пользователь уже авторизован на сайте и бот привязан к его аккаунте. Предлагаем вернуться на сайт;</span>
    - <span style="font-weight: 400;">Если user\_id отличаются, то скорее всего пользователь пытается привязать свой новый аккаунт на сайте к боту, а тот уже привязан к другому аккаунте на сайте. Решите как хотите обработать эту исключительную ситуацию, например, предложите пользователю варианты на выбор: отвязать старый аккаунт и привязать новый, оставить привязку к другому аккаунту;</span>
- **user\_id нет в web\_users**: 
    - Если в запросе нет user\_id, то это означает пользователь входит на сайте через бота и скорее всего аккаунта на сайте у него тоже нет, но это не точно;
    - В идеале нужно поискать наличие аккаунта, например, запросив регистрационные данные и выполнив поиск по API;
    - В самом простом сценарии, мы полагаем, что пользователь входит на сайт через чат-бот и одновременно регистрирует аккаунт на сайте.

#### Авторизация без ввода PIN

Для простых случаев, например, когда нам нужно показать форму ввода, принять значения, закрыть ее и вернуться в бота, мы можем не спрашивать PIN кода при переходе на сайт. Сайт может доверять хэш токену, который получили в GET, идентифицируя по нему пользователя без проверки PIN кода.

Это менее безопасный вариант, в котором есть риск, что Алиса свою ссылку со своим хэшом может переслать другому пользователю Боту, который откроет ее и будет идентифицирован на сайте под Алисой. Это допустимо в некоторых не критичных случаях, например, вы можете использовать ссылку для ввода данных, которая живет не более 1 часа.

#### Повышение безопасности авторизации

<span style="font-weight: 400;">Опционально, вы можете улучшить безопасность, добавив дополнительные проверки, например, время жизни PIN-кода или сделав одноразовый ввод кода. Обработайте нужные вам ситуации и верните сайту ответ о результате проверки.</span>

### <span style="font-weight: 400;">Что дальше?</span>

<span style="font-weight: 400;">А дальше все зависит от ваших конкретных задач и проблем. Теперь когда у вас в таблице соответствия есть взаимно-однозначная связь между ID персоны в боте и ID пользователя на сайте, вы можете как работать с сервисами веб-сайта через чат-бот от имени пользователя сайта, так и со стороны сайта инициировать в чат-боте те или иные действия для пользователя. </span>

<span style="font-weight: 400;">Также, мы рекомендуем разместить в боте функцию выхода из аккаунта, а на сайте опции для отвязки и привязки бота заново.</span>

# Deep Messaging Integration (DMI): методология

## Методология глубокой интеграции мессенджеров в бизнес-процессы

## Аннотация

Методология описывает системный подход к внедрению **диалоговых интерфейсов и мессенджеров** в бизнес-процессы предприятия. Она раскрывает архитектуру **коммуникационного и операционного слоя Metabot**, объясняет, как проектировать **карты коммуникаций**, **точки интеграции**, **синхронизацию данных** и **сквозную идентификацию пользователей** между системами. Документ предназначен для архитекторов, аналитиков и интеграторов, создающих инфраструктуру цифровых коммуникаций, и не включает когнитивный слой и AI-компоненты.

## Мир, который заговорил

### От интерфейсов к диалогу

Последние десять лет цифровой мир пережил смену парадигмы. Раньше человек взаимодействовал с системой через **формы**, **кнопки**, **интерфейсы**. Теперь он взаимодействует **словами**.

Пользователь больше не заходит на сайты, он пишет. Не ищет телефон поддержки — задаёт вопрос. Не устанавливает приложение — просто открывает мессенджер.

Коммуникация перестала быть «каналом». Она стала **операционной средой** — местом, где совершаются сделки, принимаются решения, рождаются данные.

---

### Бизнес как диалог

Для компаний это значит одно: **диалог — новая форма организации процессов.**

Там, где раньше был отдел поддержки, теперь — чат-центр. Где была CRM — интерактивный интерфейс общения. Где был лендинг — теперь сценарий диалога, персонализированный под конкретного пользователя.

Бизнес учится **разговаривать** в цифровом пространстве, и этот разговор должен быть связан с его системами, данными и людьми. Иначе он не станет частью цепочки создания ценности.

---

### Мессенджеры против приложений

Мессенджеры победили не потому, что удобнее. А потому что они — **естественнее**.

Им не нужен онбординг, не требуется обновление, они работают на привычном языке пользователя.

Для бизнеса это открыло возможность создавать сервисы, которые живут прямо внутри Telegram, WhatsApp, VK или веб-чата.

**Чат-бот = мобильное приложение без приложения.** Он может продавать, консультировать, принимать заказы, уведомлять, обучать. И самое важное — он подключается к ядру систем предприятия.

---

### От канала к инфраструктуре

Но просто «запустить бота» — недостаточно. Настоящая ценность появляется, когда диалог **встраивается в архитектуру бизнеса**.

Когда CRM, ERP, Helpdesk и маркетинг-платформа связаны с мессенджерами в единый контур, в котором данные и события двигаются двусторонне.

Так рождается новая инженерная логика — **ComOps**, *Communication Operations* — операционная система коммуникаций. И на её первом уровне лежит **методология Deep Messaging Integration (DMI)**.

---

## Архитектура глубокой интеграции

### Определение DMI

**Deep Messaging Integration (DMI)** — это способ соединить мессенджеры и внутренние системы так, чтобы диалог стал частью бизнес-процесса.

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

---

### Три слоя интеграции

DMI строится на трёх взаимосвязанных уровнях:

<table id="bkmrk-%D0%A1%D0%BB%D0%BE%D0%B9-%D0%9D%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%A7%D1%82%D0%BE-"><thead><tr><th>Слой</th><th>Назначение</th><th>Что происходит</th></tr></thead><tbody><tr><td>**Communicative Layer**</td><td>Взаимодействие с пользователем</td><td>Диалоги, уведомления, сценарии, формы</td></tr><tr><td>**Operational Layer**</td><td>Исполнение операций и логики</td><td>Запуск сценариев, плагины, таблицы, автоматизация</td></tr><tr><td>**Integration (API) Layer**</td><td>Соединение с ИТ-системами</td><td>REST эндпоинты, идентификация, обмен данными</td></tr></tbody></table>

Эти три слоя соединяются в единый поток — **Dialog Bus**. Он работает так же, как нервная система: получает сигнал, обрабатывает его, отправляет реакцию.

---

### Как работает цикл интеграции

```
[Пользователь]
   ↓  (Сообщение)
[Communicative Layer / Metabot]
   ↓  (Намерение, контекст)
[Operational Layer]
   ↓  (API-вызов)
[Основная система / CRM, ERP]
   ↑  (Данные, события)
[Metabot / Диалог]
   ↑  (Ответ, уведомление)
→ Новый контекст и память

```

Каждый цикл завершён: диалог порождает действие, действие порождает данные, данные порождают новое взаимодействие. Так создаётся **живая связь между коммуникацией и операцией**.

---

### Коммуникационный слой в Metabot

На платформе Metabot коммуникации реализуются через **low-code сценарии**. Каждый сценарий — это исполняемая программа диалога с условиями, переменными и переходами.

Типы сценариев:

- приветственные, онбординг;
- сервисные уведомления;
- интерактивные опросы и формы;
- транзакционные диалоги (заказы, оплаты);
- персонализированные бот-ассистенты.

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

---

### Операционный и интеграционный слои

- **Operational Layer** исполняет команды в реальном времени: JS-плагины, таблицы, Service Blueprints, event bus.
- **Integration Layer** предоставляет REST эндпоинты, через которые бизнес-системы вызывают коммуникации.

Например:

```
POST /bots/{botId}/call/users/update  
POST /bots/{botId}/call/order/thank-you  

```

Каждый эндпоинт имеет alias, тело запроса (`script_request_params`), и результат (`success: true`).

---

### Коммутационная логика DMI

1. Событие в системе → вызов эндпоинта Metabot.
2. Metabot запускает нужную коммуникацию в боте.
3. Бот обрабатывает ответ пользователя и через API возвращает данные в систему.
4. Контекст и атрибуты сохраняются в памяти.

Результат — **замкнутый цикл «событие ↔ коммуникация ↔ действие ↔ контекст»**, который становится частью операционного цикла компании.

---

### Почему это важно

Глубокая интеграция меняет роль коммуникаций: из канала — в инфраструктуру, из маркетинга — в операции, из поддержки — в интеллект.

---

## Стратегическое планирование: Customer Journey и Service Blueprint

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

1. **Customer Journey Map (CJM)** — путь клиента, описывающий внешний опыт и точки контакта.
2. **Service Blueprint** — карта внутренних процессов и систем, обеспечивающих этот опыт.

Именно между ними и находится зона ответственности **Deep Messaging Integration (DMI)**:  
он соединяет *внешний пользовательский опыт* (CJM) с *внутренней инфраструктурой компании* (Service Blueprint),  
превращая коммуникации в операционный слой.

### Customer Journey Map (CJM): путь клиента

**Customer Journey Map (CJM)** — это визуализация пути, который проходит ваш клиент при взаимодействии с продуктом или компанией:  
от первого знакомства с брендом до повторных покупок и рекомендаций.

Создание CJM помогает понять, **на каких этапах клиенту нужна коммуникация** и где можно повысить ценность за счёт автоматизации диалогов.

---

#### Как использовать CJM в контексте Metabot

1. **Определите персону и цель.**  
    Для кого вы проектируете путь: клиент, партнёр, монтажник, дилер и т.д.  
    Сформулируйте цель: регистрация, покупка, обучение, поддержка.
2. **Разбейте путь на этапы.**  
    Пример:  
    `Осведомлённость → Регистрация → Первая покупка → Доставка → Обратная связь → Повторный заказ`.
3. **Определите точки контакта.**  
    Где и через что клиент взаимодействует: сайт, Telegram, email, офлайн-встречи, бот-диалоги.  
    Эти точки станут **будущими узлами коммуникаций** в Metabot.
4. **Опишите эмоции и потребности.**  
    Что клиент чувствует на каждом этапе?  
    Где он теряется, раздражается, радуется?  
    Это помогает выбрать тональность сценариев и время коммуникации.
5. **Найдите возможности для улучшения.**  
    Отметьте, где коммуникация может убрать трение, ускорить шаг, добавить ценность.  
    Например: напоминание о вебинаре, автоматический статус доставки, подсказка при регистрации.

---

#### Связь CJM и карт коммуникаций

CJM показывает **путь клиента на стратегическом уровне**.  
Когда вы видите полный маршрут, можно сделать **zoom-in** на конкретные участки —  
и превратить их в **карты коммуникаций Metabot**, где описываются конкретные сообщения, участники и API-вызовы.

> 💡 Таким образом, **карта коммуникаций — это локализованный фрагмент CJM**,  
> реализованный в виде сценариев и автоматизаций внутри Metabot.

---

#### Шаблон таблицы Customer Journey (для самостоятельного заполнения)

<table id="bkmrk-%D0%AD%D1%82%D0%B0%D0%BF-%D0%BF%D1%83%D1%82%D0%B8-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D0%B0-%D0%A6%D0%B5"><thead><tr><th>Этап пути клиента</th><th>Цель клиента / зачем он это делает</th><th>Действия клиента</th><th>Эмоции 😊😐😞</th><th>Потребности и боли</th><th>Точки контакта</th><th>Коммуникация (сценарий / сообщение)</th><th>Интеграции / Системы</th><th>Возможности для улучшения</th><th>Ответственный</th></tr></thead><tbody><tr><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td></tr></tbody></table>

*Подсказка:*

- Колонки можно расширять в Miro, Notion или Google Sheets.
- Эмодзи помогают быстро видеть эмоциональные пики.
- Последние две колонки (“Возможности” и “Ответственный”) — это backstage из Service Blueprint.

---

#### Пример заполнения (кейc: “Регистрация и онбординг в Telegram-боте”)

<table id="bkmrk-%D0%AD%D1%82%D0%B0%D0%BF-%D0%BF%D1%83%D1%82%D0%B8-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D0%B0-%D0%A6%D0%B5-0"><thead><tr><th>Этап пути клиента</th><th>Цель клиента / зачем он это делает</th><th>Действия клиента</th><th>Эмоции 😊😐😞</th><th>Потребности и боли</th><th>Точки контакта</th><th>Коммуникация (сценарий / сообщение)</th><th>Интеграции / Системы</th><th>Возможности для улучшения</th><th>Ответственный</th></tr></thead><tbody><tr><td>**Осведомлённость**</td><td>Узнать о сервисе</td><td>Читает пост / получает ссылку от друга</td><td>🙂</td><td>Не хочет тратить время на установку приложений</td><td>Соцсети, лендинг</td><td>Сообщение бота «Привет! Расскажу, как всё работает без регистрации»</td><td>Tilda, UTM-метки</td><td>Добавить CTA с быстрым переходом в бот</td><td>Маркетолог</td></tr><tr><td>**Регистрация**</td><td>Создать профиль</td><td>Пишет в бот, вводит номер</td><td>😐</td><td>Беспокоится о безопасности данных</td><td>Telegram</td><td>Сценарий `registration_flow` — запрос контакта</td><td>CRM / API `/users/connect-bot`</td><td>Сократить шагов регистрации</td><td>Архитектор ComOps</td></tr><tr><td>**Первое использование**</td><td>Проверить, как работает</td><td>Проходит интро-опрос</td><td>😊</td><td>Хочет быстро понять ценность</td><td>Telegram бот</td><td>Сценарий `welcome_tour` — мини-онбординг</td><td>Metabot / CMS</td><td>Добавить короткое видео-демо</td><td>Продакт</td></tr><tr><td>**Обратная связь**</td><td>Поделиться впечатлением</td><td>Оценивает опыт 👍</td><td>🙂</td><td>Хочет, чтобы отзыв был учтён</td><td>Telegram</td><td>Сценарий `feedback_form` — опрос NPS</td><td>BI / Webhook `/feedback/received`</td><td>Добавить благодарственное сообщение</td><td>Аналитик</td></tr><tr><td>**Повторное взаимодействие**</td><td>Получить пользу повторно</td><td>Возвращается по напоминанию</td><td>😊</td><td>Хочет регулярных советов</td><td>Telegram, Email</td><td>Сценарий `retention_tips` — серия полезных сообщений</td><td>CRM, Mailer</td><td>Тестировать контент-пуши</td><td>Маркетолог</td></tr></tbody></table>

Как использовать

1. Скопируй таблицу и заполни для своего продукта.
2. Этапы можно брать из CJM (Discovery → Registration → Onboarding → Usage → Feedback → Retention).
3. Колонки *Коммуникация* и *Интеграции* — это твоя **ComOps-зона**, где создаются карты коммуникаций и точки интеграции.
4. Когда заполните таблицу — можно визуализировать как **ComOps Loop**: клиентский шаг → сообщение → действие системы → обратная связь.

> **📘 Где найти шаблоны**. Примеры и готовые шаблоны для создания CJM и Service Blueprint можно найти в открытых библиотеках Miro, Figma или FigJam.

---

### Service Blueprint: карта внутренних процессов

Если CJM отражает внешний опыт клиента, то **Service Blueprint** показывает, что происходит внутри компании, чтобы этот опыт случился.  
Это визуальная модель всех компонентов и систем, участвующих в предоставлении услуги, и их взаимодействий.

---

#### Зачем нужен Service Blueprint в контексте Metabot

- Позволяет понять, какие **внутренние процессы и системы** обеспечивают каждый этап пути клиента.
- Помогает определить, где необходимо создать **точки интеграции (API, Webhook, Data Sync)**.
- Выявляет узкие места в инфраструктуре, которые мешают бесшовному диалоговому опыту.

---

#### Классическая структура Service Blueprint

<table id="bkmrk-%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C-%D0%A7%D1%82%D0%BE-%D0%BE%D0%BF%D0%B8%D1%81%D1%8B%D0%B2%D0%B0%D0%B5"><thead><tr><th align="left">Уровень</th><th align="left">Что описывает</th><th align="left">Пример в контексте Metabot</th></tr></thead><tbody><tr><td align="left">**Customer Actions**</td><td align="left">Действия клиента</td><td align="left">Отправил сообщение в бот, подтвердил заказ</td></tr><tr><td align="left">**Front Stage Interactions**</td><td align="left">Видимые взаимодействия</td><td align="left">Оператор ответил в чате, бот отправил сценарий</td></tr><tr><td align="left">**Back Stage Interactions**</td><td align="left">Невидимые процессы</td><td align="left">CRM обновила статус, скрипт создал тикет</td></tr><tr><td align="left">**Support Processes**</td><td align="left">Поддерживающие системы и данные</td><td align="left">База данных, API, автоматизация в Metabot</td></tr></tbody></table>

---

#### Как создавать Service Blueprint для интеграции

1. **Определите цель и персону.**  
    Для кого и зачем вы анализируете процесс (например, онбординг клиента или обработка заказа).
2. **Опишите этапы взаимодействия.**  
    Разбейте процесс на шаги: заявка → обработка → доставка → отзыв.
3. **Отметьте все точки контакта.**  
    Где клиент взаимодействует с компанией и через какие каналы (бот, сайт, email).
4. **Разделите на уровни.**  
    Front stage — что видит клиент.  
    Back stage — что делают сотрудники и боты.  
    Support processes — какие системы обеспечивают работу.
5. **Добавьте интеграции.**  
    Отметьте, где необходимы API или события для обмена данными между системами.

---

#### Blueprint → DMI → Интеграции

Когда Service Blueprint готов, вы видите, **в каких точках процесс можно связать с диалогами в мессенджерах**.  
Именно эти точки становятся **эндпоинтами Metabot и точками интеграции DMI**, описанными в следующем разделе.

> 💡 Service Blueprint — это операционный слой,  
> а **Deep Messaging Integration** делает его живым, соединяя системные события и реальные диалоги в ComOps-архитектуре.

---

#### Шаблон Service Blueprint (для самостоятельного заполнения)

<table id="bkmrk-%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C-%2F-%D0%AD%D1%82%D0%B0%D0%BF-aware"><thead><tr><th>Уровень / Этап</th><th>Awareness</th><th>Ordering</th><th>Purchasing</th><th>Receiving</th><th>Using / Onboarding</th><th>Feedback</th></tr></thead><tbody><tr><td>**Customer Actions**</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td></tr><tr><td>**Front Stage Interactions**</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td></tr><tr><td>**Back Stage Interactions**</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td></tr><tr><td>**Support Processes / Systems**</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td><td>  
</td></tr></tbody></table>

*Как заполнять:*

- Верхний ряд (Customer Actions) — то, что делает клиент.
- Далее вниз: кто и что происходит внутри компании.
- Можно добавлять стрелки, зависимости или примечания, если делаете в Miro, FigJam или Notion.

---

#### Пример заполнения (кейc: «Онбординг нового клиента в сервисе»)

<table id="bkmrk-%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C-%2F-%D0%AD%D1%82%D0%B0%D0%BF-aware-0"><thead><tr><th>Уровень / Этап</th><th>Awareness</th><th>Registration</th><th>First Use</th><th>Support</th><th>Feedback</th><th>Renewal</th></tr></thead><tbody><tr><td>**Customer Actions**</td><td>Видит пост в Telegram и переходит в бот</td><td>Вводит номер, получает приветствие</td><td>Проходит мини-инструкцию</td><td>Задает вопрос в чате</td><td>Оценивает опыт 👍</td><td>Получает напоминание о продлении</td></tr><tr><td>**Front Stage Interactions**</td><td>Сообщение от маркетолога, ссылка на бот</td><td>Бот: сценарий `registration_flow`</td><td>Бот: сценарий `welcome_tour`</td><td>Оператор отвечает вручную</td><td>Бот: `feedback_form`</td><td>Email или бот: `renewal_offer`</td></tr><tr><td>**Back Stage Interactions**</td><td>CRM создаёт лид по ссылке UTM</td><td>Сервис Metabot создаёт запись `leadId ↔ userId`</td><td>Система Metabot обновляет атрибуты</td><td>Support CRM создаёт тикет</td><td>BI фиксирует NPS-ответ</td><td>CRM обновляет статус подписки</td></tr><tr><td>**Support Processes / Systems**</td><td>Telegram Ads, Analytics</td><td>CRM, API `/users/connect-bot`</td><td>Metabot Runtime, JS scripts</td><td>Helpdesk, Knowledge Base</td><td>BI, PostgreSQL, DataLens</td><td>CRM + Mailer</td></tr></tbody></table>

> **📘 Где найти шаблоны**. Примеры и готовые шаблоны для создания CJM и Service Blueprint можно найти в открытых библиотеках Miro, Figma или FigJam.

---

### ComOps Loop: как соединяются CJM и Service Blueprint

Customer Journey показывает **внешний опыт клиента** — путь, эмоции, точки контакта.  
Service Blueprint описывает **внутренние процессы и системы**, которые этот опыт обеспечивают.  
А между ними находится **ComOps Loop** — петля, которая связывает эти два мира через:

- **Communication Map** — карта диалогов и сценариев (как система говорит с пользователем);
- **Integration Points Map** — карта точек интеграции (как системы говорят между собой).

---

#### 🔁 Визуальная схема ComOps Loop

```
    ┌──────────────────────────────┐
    │       CJM: Путь клиента      │
    │   (опыт, эмоции, контакт)    │
    └──────────────────────────────┘
                   ▲
                   │
                   ▼
    ┌──────────────────────────────────────────┐
    │      COMOPS: СВЯЗУЮЩИЙ УЗЕЛ              │
    │  Communication Map ↔ Integration Points  │
    │   (диалоги ↔ API, сценарии ↔ процессы)   │
    └──────────────────────────────────────────┘
                   ▲
                   │
                   ▼
    ┌─────────────────────────────────────┐
    │ Service Blueprint: Процессы         │
    │ (системы, API, внутренние действия) │
    └─────────────────────────────────────┘
          🔄 Цикл обратной связи

```

> 💡 **ComOps — это связующий контур между опытом и операцией.**  
> Он превращает шаги клиента из CJM в действия систем из Service Blueprint,  
> а ответы систем — обратно в диалоги, создавая непрерывную коммуникационную петлю.

---

## Проектирование коммуникаций

### Карта коммуникаций — сердце интеграции

Каждый процесс начинается не с API и не с бота — а с **карты коммуникаций**.

Карта коммуникаций — это документ, который связывает **события бизнеса** с **коммуникациями, ролями и действиями**.

Она отвечает на простой вопрос:

> Кто, когда и зачем должен что-то сказать пользователю?

Карта строится по принципу **петли коммуникации**:

```
Событие → Коммуникация → Участники → Действия → Результат → Новое событие

```

---

### Структура карты коммуникаций

Вот базовая структура таблицы:

<table id="bkmrk-%E2%84%96-%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B5-%D0%B2-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B5-"><thead><tr><th>№</th><th>Событие в системе</th><th>Коммуникация / сценарий</th><th>Участники</th><th>Канал</th><th>Действие пользователя</th><th>Ответ / результат</th><th>API / триггер</th></tr></thead><tbody><tr><td>1</td><td>Новый заказ</td><td>“Спасибо за заказ”</td><td>Клиент</td><td>Telegram</td><td>—</td><td>Подтверждение оплаты</td><td>`/bots/{id}/call/order/thank-you`</td></tr><tr><td>2</td><td>Статус заказа изменён</td><td>“Ваш заказ отправлен”</td><td>Клиент</td><td>Telegram, Email</td><td>—</td><td>Уточняет адрес</td><td>`/bots/{id}/call/order/status`</td></tr><tr><td>3</td><td>Новый тикет</td><td>“Заявка создана”</td><td>Клиент, оператор</td><td>Web, Bot</td><td>Может ответить</td><td>`/bots/{id}/call/ticket/new`</td><td>  
</td></tr><tr><td>4</td><td>Ответ оператора</td><td>“Ваш вопрос решён?”</td><td>Клиент</td><td>Telegram</td><td>Может оценить</td><td>`/bots/{id}/call/ticket/feedback`</td><td>  
</td></tr></tbody></table>

Эта таблица — **живая карта**, по которой проектировщик видит, что происходит между системой и пользователем.

---

### Пример: коммуникационная карта регистрации пользователя

<table id="bkmrk-%E2%84%96-%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B5-%D0%9A%D0%BE%D0%BC%D0%BC%D1%83%D0%BD%D0%B8%D0%BA%D0%B0%D1%86"><thead><tr><th>№</th><th>Событие</th><th>Коммуникация</th><th>Канал</th><th>Действие пользователя</th><th>Сценарий</th><th>API</th></tr></thead><tbody><tr><td>1</td><td>Пользователь зарегистрировался</td><td>Приветствие + сбор данных</td><td>Telegram</td><td>Ввести имя, город</td><td>`registration_flow`</td><td>`/bots/123/call/user/register`</td></tr><tr><td>2</td><td>Email не подтверждён</td><td>Напоминание о подтверждении</td><td>Telegram</td><td>Нажать кнопку “Подтвердить”</td><td>`email_confirm`</td><td>`/bots/123/call/user/email`</td></tr><tr><td>3</td><td>Профиль заполнен</td><td>Спасибо + стартовая инструкция</td><td>Telegram</td><td>—</td><td>`welcome_final`</td><td>`/bots/123/call/user/complete`</td></tr></tbody></table>

Таким образом, коммуникация становится **частью пользовательского пути (CJM)**, а карта — инструментом согласования между бизнесом, разработкой и интегратором.

---

### Пример из кейса Fmlst (семейный сайт)

<table id="bkmrk-%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B5-%D0%9A%D0%BE%D0%BC%D0%BC%D1%83%D0%BD%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F"><thead><tr><th>Событие</th><th>Коммуникация</th><th>Участники</th><th>Канал</th><th>Результат</th></tr></thead><tbody><tr><td>Создана новая публикация</td><td>“В семье появилось новое событие!”</td><td>Все участники семьи</td><td>Telegram</td><td>Получили уведомление и ссылку</td></tr><tr><td>Добавлен комментарий</td><td>“Кто-то прокомментировал ваш пост”</td><td>Автор публикации</td><td>Telegram</td><td>Переход в диалог</td></tr><tr><td>Обновлена анкета</td><td>“Новые данные в профиле семьи”</td><td>Владельцы профиля</td><td>Telegram</td><td>Подтверждение изменений</td></tr></tbody></table>

📘 Здесь каждая коммуникация — это часть **“живой ленты событий”**. Платформа не просто уведомляет — она связывает людей и действия, формируя цифровую ткань семьи.

---

### Коммуникационная карта как инструмент проектирования

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

👉 Таким образом, карта становится **переходным звеном** между бизнесом и кодом.

---

## Точки интеграции и API

### Что такое точка интеграции

**Integration Endpoint** — это место, где система и бот встречаются.

Бизнес-система (CRM, сайт, ERP) вызывает Metabot, а Metabot — сценарий коммуникации.

Пример:

```
POST https://app.metabot24.com/bots/123/call/order/thank-you
Authorization: Bearer {token}
Content-Type: application/json

{
  "order_id": 9821,
  "user_id": "54321",
  "amount": 3500,
  "status": "paid"
}

```

В ответ:

```json
{
  "success": true,
  "message": "Communication sent",
  "trace_id": "e9fa-234c-118a"
}

```

---

### Как проектировать точки интеграции

Каждая точка должна быть описана в документации:

<table id="bkmrk-%D0%9F%D0%BE%D0%BB%D0%B5-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-alias-"><thead><tr><th>Поле</th><th>Описание</th></tr></thead><tbody><tr><td>**Alias**</td><td>Уникальный код сценария</td></tr><tr><td>**URL**</td><td>`/bots/{botId}/call/{alias}`</td></tr><tr><td>**Method**</td><td>`POST`</td></tr><tr><td>**Auth**</td><td>`Bearer {token}`</td></tr><tr><td>**Request**</td><td>JSON с данными</td></tr><tr><td>**Response**</td><td>JSON с результатом</td></tr><tr><td>**Owner**</td><td>Владелец сценария</td></tr></tbody></table>

Пример описания:

```
Alias: order_thankyou
Purpose: отправка благодарности за заказ
Owner: ecommerce-team

```

---

### Классификация интеграций

<table id="bkmrk-%D0%A2%D0%B8%D0%BF-%D0%9E%D1%82%D0%BA%D1%83%D0%B4%D0%B0-%D0%9A%D1%83%D0%B4%D0%B0-%D0%9F%D1%80%D0%B8%D0%BC"><thead><tr><th>Тип</th><th>Откуда</th><th>Куда</th><th>Пример</th></tr></thead><tbody><tr><td>**Входящая (Inbound)**</td><td>Из системы → Metabot</td><td>CRM вызывает бот</td><td>“Новый заказ — отправь уведомление клиенту”</td></tr><tr><td>**Исходящая (Outbound)**</td><td>Из Metabot → систему</td><td>Бот вызывает API</td><td>“Пользователь подтвердил оплату — обнови заказ”</td></tr><tr><td>**Двусторонняя (Bidirectional)**</td><td>Обе стороны</td><td>Полный цикл событий</td><td>“Создан заказ → бот уведомил → клиент ответил → система изменила статус”</td></tr></tbody></table>

---

### Пример схемы интеграции

```
 ┌────────────────────┐
 │  Основная система  │
 │ (CRM / ERP / сайт) │
 └────────┬───────────┘
          │ REST API (POST /call/{alias})
          ▼
 ┌────────────────────┐
 │     Metabot API    │
 │  Scenario Engine   │
 └────────┬───────────┘
          │
          ▼
 ┌────────────────────┐
 │  Messenger / User  │
 └────────────────────┘

```

Каждая стрелка — это **реальный webhook или вызов**, который формирует коммуникационный цикл.

---

### Авторизация и безопасность

- Все вызовы защищены **Bearer Token**, привязанным к конкретному проекту.
- Для каждого партнёра/интеграции можно выдать отдельный токен с ограничениями.
- В логах Metabot сохраняется `trace_id` — полный путь запроса.
- Данные проходят через HTTPS, а история событий доступна в панели администратора.

---

### Отладка и документация

Metabot предоставляет встроенный **Swagger-интерфейс**: `https://app.metabot24.com/docs/{botId}` где можно тестировать запросы и видеть ответы в реальном времени.

Для интеграторов предусмотрен “Dry Run Mode” — отправка тестовых событий без запуска реальной коммуникации.

---

### Логика вызова API внутри сценария

Иногда коммуникация сама вызывает систему обратно. Например, после ответа пользователя:

```javascript
callApi({
  url: "https://crm.example.com/api/order/update",
  method: "POST",
  body: {
    user_id: ctx.user.id,
    order_id: ctx.data.order.id,
    action: "confirm_payment"
  }
})

```

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

---

## Сквозная идентификация и синхронизация данных

### Зачем нужна сквозная идентификация

Чтобы диалог стал частью бизнес-процесса, система должна **знать, кто с ней говорит**.

Пока мы просто пишем пользователю в Telegram — это коммуникация. Когда мы понимаем, **к какому клиенту CRM она относится** — это уже интеграция. А когда событие в CRM способно **вызвать персональную коммуникацию** в мессенджере — это и есть **сквозная идентификация**.

---

### Базовая модель идентификации

Каждая система имеет свои идентификаторы:

<table id="bkmrk-%D0%A1%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0-%D0%98%D0%B4%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE"><thead><tr><th>Система</th><th>Идентификатор</th><th>Пример</th></tr></thead><tbody><tr><td>CRM / ERP</td><td>`userId`</td><td>125</td></tr><tr><td>Metabot</td><td>`leadId` или `personId`</td><td>`TG-9072612`</td></tr><tr><td>Messenger (Telegram / VK)</td><td>`chatId`</td><td>540278913</td></tr></tbody></table>

Чтобы соединить эти миры, мы создаём **таблицу соответствий ID** — она хранится в базе Metabot.

Пример записи:

```json
{
  "userId": 125,
  "leadId": "TG-9072612",
  "chatId": 540278913,
  "isActive": true,
  "source": "telegram",
  "connected_at": "2025-10-15T11:24:52Z"
}

```

---

### Как устанавливается связь

#### Шаг 1. Пользователь инициирует авторизацию

Через чат-бот:

```
Здравствуйте! Чтобы продолжить, авторизуйтесь.
Введите ваш телефон или email.

```

#### Шаг 2. Бот ищет пользователя в основной системе

```json
GET /user
{
  "phone": "79187777777"
}

```

Если пользователь найден — возвращается `userId`. Если нет — создаётся новый пользователь (`POST /user`).

#### Шаг 3. Бот сообщает системе, что пользователь подключил бота

```json
POST /users/connect-bot
{
  "userId": 125
}

```

Теперь система знает, что этот пользователь имеет активный бот в Telegram.

#### Шаг 4. Таблица связей пополняется

Metabot создаёт запись `userId ↔ leadId ↔ chatId`.

---

### Авторизация: альтернативные сценарии

- **Telegram Login:** подтверждение через `tg://resolve?domain=...` Сравнивается телефон Telegram с телефоном в CRM.
- **SMS-код:** если нужно двухфакторное подтверждение.
- **OAuth / SSO:** при интеграции с корпоративными порталами.

---

### Двусторонняя связь

Теперь, когда связь установлена:

- Система может вызвать коммуникацию по `userId`. Metabot сам найдёт `leadId` и доставит сообщение пользователю.
- Чат-бот может изменить данные пользователя в CRM. Через эндпоинт `/api/user/update` он отправит запрос обратно.

Пример:

```json
{
  "userId": 125,
  "email": "new@domain.com",
  "city": "Москва"
}

```

---

### Синхронизация данных: два подхода

#### Pull-модель (по запросу)

Чат-бот получает только `ID` ресурса (например, заказа) и **сам подгружает данные** по API.

```json
{
  "script_request_params": {
    "orderId": 9821,
    "userId": 125
  }
}

```

Бот вызывает API:

```
GET /orders/9821

```

и получает всё, что нужно для коммуникации.

- 📌 *Плюсы:* гибкость, меньше изменений при расширении данных.
- 📉 *Минусы:* требует доступных API и быстрых ответов.

---

#### Push-модель (полный пакет данных)

Система передаёт **всю информацию** о событии прямо в запросе к боту.

```json
{
  "script_request_params": {
    "userId": 125,
    "order": {
      "id": 9821,
      "status": "shipped",
      "amount": 3500
    }
  }
}

```

- 📌 *Плюсы:* не требуется дополнительный API-запрос.
- 📉 *Минусы:* больше нагрузка и объём данных, менее гибко при изменениях схемы.

---

### Комбинированная модель

На практике часто используется гибрид:

- Система передаёт основные ID (userId, orderId).
- Бот при необходимости делает `pull`-запросы за контекстом.

```json
"script_request_params": {
  "userId": 125,
  "orderId": 9821
}

```

Затем бот:

```
GET /orders/9821/details
GET /users/125/profile

```

---

### Архитектура обмена событиями

```
 ┌────────────────────┐
 │     Основная       │
 │     система        │
 └────────┬───────────┘
          │ Webhook / API
          ▼
 ┌────────────────────┐
 │     Metabot        │
 │  (Integration Bus) │
 └────────┬───────────┘
          │ Script Engine
          ▼
 ┌────────────────────┐
 │   Мессенджер /     │
 │   Пользователь     │
 └────────────────────┘
          ▲
          │ Ответ пользователя
          │ API / Callback
          ▼
 ┌────────────────────┐
 │     Основная       │
 │     система        │
 └────────────────────┘

```

Этот цикл может повторяться многократно в одном процессе — создавая **живой операционный контур коммуникаций**.

---

### Обработка ошибок и логирование

Metabot возвращает стандартные коды и сообщения:

<table id="bkmrk-%D0%9A%D0%BE%D0%B4-%D0%A1%D0%BC%D1%8B%D1%81%D0%BB-%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80-200"><thead><tr><th>Код</th><th>Смысл</th><th>Пример</th></tr></thead><tbody><tr><td>`200`</td><td>OK</td><td>`{ "success": true }`</td></tr><tr><td>`401`</td><td>Ошибка авторизации</td><td>`{ "message": "Invalid token" }`</td></tr><tr><td>`404`</td><td>Эндпоинт не найден</td><td>`{ "message": "Endpoint not found" }`</td></tr><tr><td>`500`</td><td>Внутренняя ошибка</td><td>`{ "message": "Script error at line 23" }`</td></tr></tbody></table>

Все события логируются с `trace_id`, что позволяет восстанавливать цепочку:

```
CRM event → Metabot endpoint → scenario → messenger → user → callback → CRM update

```

---

### Пример полного цикла “Регистрация нового пользователя”

**Событие:** Пользователь заполнил форму на сайте  
**Система:** CRM создаёт `userId = 125`  
**Интеграция:**  
→ CRM вызывает `/bots/{botId}/call/users/connect-bot`.  
→ Metabot приветствует пользователя в Telegram  
→ Пользователь подтверждает номер  
→ Metabot вызывает `/api/user/confirm` в CRM  
→ CRM активирует профиль  
→ Metabot отправляет финальное сообщение:

> “Добро пожаловать, {имя}! Ваш личный кабинет активирован.”

📊 Всё: одна петля, один контур, одна точка истины.

---

### Ключевой принцип DMI

> **Коммуникация = операция + контекст + идентификация.**

Без связи между ID — бот остаётся «игрушкой». Без связи с системой — коммуникация бессмысленна. Только в комбинации трёх уровней возникает **живая цифровая экосистема**.

---

## Архитектура взаимодействия

### Общая схема цифрового диалога

```
 ┌──────────────────────────┐
 │        Пользователь      │
 │  (Telegram / WhatsApp)   │
 └───────────┬──────────────┘
             │
             ▼
 ┌──────────────────────────┐
 │ Коммуникативный слой     │
 │ (Metabot: сценарии, UI)  │
 └───────────┬──────────────┘
             │
             ▼
 ┌──────────────────────────┐
 │  Операционный слой       │
 │  (Low-code runtime, JS)  │
 └───────────┬──────────────┘
             │
             ▼
 ┌──────────────────────────┐
 │ Интеграционный слой      │
 │ (REST API, Webhooks)     │
 └───────────┬──────────────┘
             │
             ▼
 ┌──────────────────────────────┐
 │ Основная система             │
 │ (CRM / ERP / CMS / Helpdesk) │
 └──────────────────────────────┘

```

📘 **Логика простая:**

1. Событие возникает в основной системе (например, заказ оформлен).
2. Через API вызывается соответствующая коммуникация Metabot.
3. Бот связывается с пользователем в мессенджере, отправляет сообщение или запускает диалог.
4. Ответ пользователя возвращается в систему через обратный вызов API.
5. Система обновляет данные и при необходимости инициирует новый цикл.

---

### Принцип двустороннего обмена

Deep Messaging Integration строится на **двух потоках** данных:

<table id="bkmrk-%D0%9F%D0%BE%D1%82%D0%BE%D0%BA-%D0%9D%D0%B0%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D0%A1%D1%86"><thead><tr><th>Поток</th><th>Направление</th><th>Сценарий</th></tr></thead><tbody><tr><td>**Outbound (система → бот)**</td><td>событие вызывает коммуникацию</td><td>“Новый заказ”, “Изменился статус”</td></tr><tr><td>**Inbound (бот → система)**</td><td>действие пользователя вызывает событие</td><td>“Пользователь подтвердил оплату”, “Оставил отзыв”</td></tr></tbody></table>

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

---

### Контур обратной связи

```
CRM → Metabot → Messenger → Пользователь → Metabot → CRM

```

Этот цикл — **нервный импульс организации**. Он связывает людей, процессы и данные в реальном времени.

Именно из таких петель строится **Communication Operating System (ComOps)**, в которой коммуникация становится инфраструктурой.

---

### Управление состоянием и контекстом

Внутри Metabot каждое взаимодействие сохраняется в памяти:

- `lead_id` — идентификатор пользователя,
- `session_id` — уникальная сессия диалога,
- `context` — набор переменных (профиль, предыдущие шаги, ответы),
- `attributes` — параметры, сохраняемые между сценариями.

Благодаря этому:

- Бот “помнит”, на каком этапе остановился пользователь.
- Можно персонализировать коммуникации.
- Возможна аналитика CJM и сегментация по атрибутам.

---

### Пример архитектуры для крупной компании

#### Сценарий: коммуникации REHAU с монтажниками

```
[Монтажник / Telegram]
      ⇅
[Metabot Bot / Сценарий "Регистрация + ЛК"]
      ⇅
[REHAU Portal]
      ⇅
[CRM + Webinar + BI]

```

📍 Здесь Metabot выступает **прослойкой-коммутатором**:

- Из портала в Metabot приходят события (регистрация, вебинар, заказ).
- Metabot сообщает монтажнику: “У вас новый заказ”, “Вебинар сегодня в 10:00”, “Оцените качество”.
- Ответ монтажника отправляется обратно в CRM и BI-систему.

---

### Коммуникационная карта для REHAU

<table id="bkmrk-%E2%84%96-%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B5-%D0%9A%D0%BE%D0%BC%D0%BC%D1%83%D0%BD%D0%B8%D0%BA%D0%B0%D1%86-0"><thead><tr><th>№</th><th>Событие</th><th>Коммуникация</th><th>Участник</th><th>Канал</th><th>API / Endpoint</th></tr></thead><tbody><tr><td>1</td><td>Монтажник зарегистрировался на портале</td><td>“Добро пожаловать!”</td><td>Монтажник</td><td>Telegram</td><td>`/users/connect-bot`</td></tr><tr><td>2</td><td>Назначен новый вебинар</td><td>“Вы приглашены на обучение”</td><td>Монтажник</td><td>Telegram</td><td>`/events/webinar-invite`</td></tr><tr><td>3</td><td>Вебинар завершён</td><td>“Оцените качество обучения”</td><td>Монтажник</td><td>Telegram</td><td>`/events/webinar-feedback`</td></tr><tr><td>4</td><td>Отзыв отправлен</td><td>“Спасибо за обратную связь”</td><td>Монтажник</td><td>Telegram</td><td>`/feedback/received`</td></tr></tbody></table>

📊 Каждый шаг — событие в бизнес-системе, каждая коммуникация — сценарий в Metabot, каждое действие — новая строка в аналитике BI.

---

### Пример карты интеграций для eCommerce

<table id="bkmrk-%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B5-%D0%A2%D0%BE%D1%87%D0%BA%D0%B0-%D0%B8%D0%BD%D1%82%D0%B5%D0%B3%D1%80"><thead><tr><th>Событие</th><th>Точка интеграции</th><th>Описание</th><th>Коммуникация</th></tr></thead><tbody><tr><td>Новый заказ</td><td>`/order/thank-you`</td><td>Отправляем благодарность и детали заказа</td><td>“Спасибо за покупку!”</td></tr><tr><td>Статус заказа изменён</td><td>`/order/status`</td><td>Сообщаем об отправке</td><td>“Ваш заказ отправлен!”</td></tr><tr><td>Доставка завершена</td><td>`/order/delivered`</td><td>Просим оставить отзыв</td><td>“Оцените доставку”</td></tr><tr><td>Новый отзыв</td><td>`/order/review`</td><td>Отправляем бонус</td><td>“Спасибо за отзыв!”</td></tr></tbody></table>

---

### Пример: семейный сервис **Fmlst**

#### Архитектура:

```
Fmlst CMS → Metabot → Telegram → Пользователи семьи

```

#### Коммуникационная карта:

<table id="bkmrk-%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B5-%D0%9A%D0%BE%D0%BC%D0%BC%D1%83%D0%BD%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-0"><thead><tr><th>Событие</th><th>Коммуникация</th><th>Участники</th><th>API</th></tr></thead><tbody><tr><td>Новая публикация</td><td>“В семье новое событие!”</td><td>Все члены семьи</td><td>`/post/new`</td></tr><tr><td>Новый комментарий</td><td>“Кто-то прокомментировал пост”</td><td>Автор публикации</td><td>`/comment/new`</td></tr><tr><td>Новый участник семьи</td><td>“Добро пожаловать в семью!”</td><td>Все пользователи</td><td>`/users/new`</td></tr></tbody></table>

Бот превращает семейный сайт в **живой диалог** — обновления, обсуждения и эмоции происходят прямо в мессенджере.

---

### Пример Helpdesk-интеграции

#### Архитектура:

```
Helpdesk ⇄ Metabot ⇄ Telegram / Webchat

```

<table id="bkmrk-%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B5-%D0%9A%D0%BE%D0%BC%D0%BC%D1%83%D0%BD%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-1"><thead><tr><th>Событие</th><th>Коммуникация</th><th>Канал</th><th>API</th></tr></thead><tbody><tr><td>Новый тикет</td><td>“Ваша заявка создана”</td><td>Telegram</td><td>`/ticket/new`</td></tr><tr><td>Ответ оператора</td><td>“Ваш вопрос решён?”</td><td>Telegram</td><td>`/ticket/reply`</td></tr><tr><td>Оценка обслуживания</td><td>“Пожалуйста, оцените качество”</td><td>Telegram</td><td>`/ticket/feedback`</td></tr></tbody></table>

🎯 Результат:

- Клиент получает ответы мгновенно.
- Поддержка видит ответы и оценки в CRM.
- Система автоматически закрывает тикеты при подтверждении.

---

### Аналитика и управление

Каждая коммуникация генерирует **лог событий**, который можно собирать и визуализировать в BI:

<table id="bkmrk-%D0%9C%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B0-%D0%98%D1%81%D1%82%D0%BE%D1%87%D0%BD%D0%B8%D0%BA-%D0%9F%D1%80%D0%B8"><thead><tr><th>Метрика</th><th>Источник</th><th>Пример</th></tr></thead><tbody><tr><td>Вовлечённость</td><td>Логи Metabot</td><td>82% пользователей ответили на сообщение</td></tr><tr><td>Среднее время реакции</td><td>BI</td><td>1,7 мин</td></tr><tr><td>Ошибки интеграции</td><td>Log Trace</td><td>0,3%</td></tr><tr><td>Конверсия → Цель</td><td>CJM Map</td><td>+27% по цепочке обучения</td></tr></tbody></table>

---

## Кейс REHAU × Metabot

### Как бизнес-процессы ожили в мессенджерах

---

### Контекст

Компания **REHAU** — крупный производитель строительных систем и решений. Её аудитория — **монтажники, дилеры, проектировщики**, распределённые по регионам и сегментам.

Основная проблема:

- коммуникация была разрознена,
- вебинары, порталы, CRM — не связаны,
- пользователи терялись между системами.

---

### Решение

Metabot внедрил **коммуникационный слой**, который объединил все точки взаимодействия в единый диалог.

Теперь монтажник получает всё в одном месте — **в Telegram-боте**:

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

---

### Технологическая архитектура REHAU Integration Bus

```
[REHAU Portal] → [Metabot API / Webhooks]
       ⇅
[Metabot Scenario Engine / JS Scripts]
       ⇅
[Telegram Bot Interface]
       ⇅
[User / Installer]

```

Ключевые принципы:

- Каждое событие на портале вызывает webhook в Metabot.
- Metabot управляет сценарием, контекстом и памятью.
- Все ответы пользователей логируются и синхронизируются обратно.

---

### Результаты

📈 **Внедрение Deep Messaging Integration дало:**

- рост вовлечённости монтажников ×5,
- сокращение ручных рассылок на 90%,
- оперативную аналитику по активности,
- снижение нагрузки на call-центр,
- создание персональных digital-профилей.

---

### Из интервью на конференции

> “Мы смогли объединить всё: портал, Telegram и CRM — теперь коммуникации не висят отдельно, они стали частью нашей инфраструктуры.” — *Команда REHAU, проект Metabot Connect.*

---

## 💡 Заключение

**От интеграции к операционной системе коммуникаций**

Глубокая интеграция — это не просто API или бот. Это **новый уровень зрелости бизнеса**, где общение, процессы и данные работают как единое целое.

> “Диалог — это новый интерфейс, коммуникация — новая инфраструктура, а Metabot — операционная система, которая объединяет их в живой интеллект предприятия.”

---

## Управление, аналитика и развитие

### Управление интеграциями

После запуска Deep Messaging Integration, проект должен **жить и развиваться**.  
Это не одноразовая настройка — это новая **коммуникационная инфраструктура** компании.

Основные роли:

<table id="bkmrk-%D0%A0%D0%BE%D0%BB%D1%8C-%D0%9E%D1%82%D0%B2%D0%B5%D1%82%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D1%8C"><thead><tr><th>Роль</th><th>Ответственность</th></tr></thead><tbody><tr><td>**ComOps-архитектор**</td><td>проектирует коммуникационные петли, карты, API</td></tr><tr><td>**Интегратор / разработчик**</td><td>реализует эндпоинты и сценарии</td></tr><tr><td>**Менеджер коммуникаций**</td><td>управляет контентом и рассылками</td></tr><tr><td>**Аналитик / BI-специалист**</td><td>анализирует метрики и воронки</td></tr><tr><td>**Оператор / бот-менеджер**</td><td>следит за логами, отвечает вручную при необходимости</td></tr></tbody></table>

🧭  
Методология DMI предлагает постоянный цикл управления:

> **Design → Integrate → Measure → Improve**

---

### Мониторинг и логирование

Каждое событие, коммуникация и ошибка должны фиксироваться в логах.  
Metabot предоставляет системный журнал:

<table id="bkmrk-%D0%9F%D0%BE%D0%BB%D0%B5-%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-trace_"><thead><tr><th>Поле</th><th>Описание</th></tr></thead><tbody><tr><td>`trace_id`</td><td>уникальный идентификатор цепочки</td></tr><tr><td>`source_system`</td><td>CRM, ERP, Portal и т.д.</td></tr><tr><td>`endpoint`</td><td>alias точки интеграции</td></tr><tr><td>`userId / leadId`</td><td>участник коммуникации</td></tr><tr><td>`status`</td><td>success / fail</td></tr><tr><td>`latency_ms`</td><td>время отклика</td></tr><tr><td>`timestamp`</td><td>дата и время события</td></tr></tbody></table>

📊  
Все логи можно экспортировать в BI и строить визуальные отчёты.

---

### Метрики коммуникаций

Коммуникации измеряются по тем же принципам, что и процессы:

<table id="bkmrk-%D0%9C%D0%B5%D1%82%D1%80%D0%B8%D0%BA%D0%B0-%D0%97%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%9F%D1%80%D0%B8"><thead><tr><th>Метрика</th><th>Значение</th><th>Пример</th></tr></thead><tbody><tr><td>**Delivery Rate**</td><td>процент доставленных сообщений</td><td>98%</td></tr><tr><td>**Engagement Rate**</td><td>процент пользователей, ответивших на сообщение</td><td>76%</td></tr><tr><td>**Response Time**</td><td>среднее время реакции</td><td>1.8 минуты</td></tr><tr><td>**Conversion Rate**</td><td>переход из коммуникации в действие</td><td>22%</td></tr><tr><td>**Satisfaction Index (CSAT)**</td><td>оценка удовлетворённости</td><td>4.7/5</td></tr><tr><td>**Error Rate**</td><td>процент неуспешных вызовов API</td><td>0.4%</td></tr></tbody></table>

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

---

### Коммуникационные BI-дашборды

В BI можно построить визуальную аналитику:

**Примеры отчётов:**

- Динамика вовлечённости по неделям
- Среднее время ответа
- Количество событий на пользователя
- Воронка: Событие → Коммуникация → Ответ → Действие
- Тепловая карта сценариев

📈  
Таким образом, коммуникации становятся **измеримыми и управляемыми процессами**.

---

### Управление качеством и версиями

Каждая коммуникационная карта и интеграция должна иметь версионность:

<table id="bkmrk-%D0%92%D0%B5%D1%80%D1%81%D0%B8%D1%8F-%D0%98%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5-%D0%9E%D1%82%D0%B2"><thead><tr><th>Версия</th><th>Изменение</th><th>Ответственный</th><th>Дата</th></tr></thead><tbody><tr><td>1.0</td><td>Базовая регистрация</td><td>Арх. Алёна</td><td>01.02</td></tr><tr><td>1.1</td><td>Добавлен сбор email</td><td>Арх. Алёна</td><td>15.02</td></tr><tr><td>1.2</td><td>Улучшен UX</td><td>Маркетинг</td><td>01.03</td></tr></tbody></table>

Metabot поддерживает экспорт и хранение карт коммуникаций в JSON,  
а также историю изменений, чтобы можно было откатить или сравнить версии.

---

### Безопасность и доступы

DMI управляет не только коммуникациями, но и **доступом к данным**:

- все вызовы через HTTPS;
- токены разграничены по ролям;
- события журналируются;
- личные данные пользователей (PII) не передаются без шифрования.

Для критичных процессов создаются **изолированные эндпоинты** с отдельными ключами,  
например для платежей, медицинских данных или HR-информации.

---

### Этапы внедрения DMI

<table id="bkmrk-%D0%AD%D1%82%D0%B0%D0%BF-%D0%94%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D0%B5-%D0%A0%D0%B5%D0%B7%D1%83%D0%BB%D1%8C"><thead><tr><th>Этап</th><th>Действие</th><th>Результат</th></tr></thead><tbody><tr><td>**1. Анализ процессов**</td><td>выбираем ключевые сценарии (регистрация, заказ, поддержка)</td><td>выявлены 3–5 процессов</td></tr><tr><td>**2. Построение карт коммуникаций**</td><td>документируем все события и роли</td><td>готов набор карт</td></tr><tr><td>**3. Определение точек интеграции**</td><td>проектируем эндпоинты, тело запроса, ответ</td><td>API-документация согласована</td></tr><tr><td>**4. Реализация и тестирование**</td><td>создаём сценарии, интеграции, авторизацию</td><td>рабочий MVP</td></tr><tr><td>**5. Мониторинг и аналитика**</td><td>подключаем BI, собираем метрики</td><td>контроль эффективности</td></tr><tr><td>**6. Масштабирование**</td><td>добавляем новые процессы</td><td>зрелая коммуникационная инфраструктура</td></tr></tbody></table>

---

### Роли и организационная модель

DMI внедряется в компании как **сквозная функция между ИТ и бизнесом**.

```
                ┌──────────────┐
                │ Руководство  │
                └──────┬───────┘
                       │
          ┌────────────┴────────────┐
          │ Коммуникационный офис   │
          └────────────┬────────────┘
                       │
 ┌──────────────┬─────────────┬─────────────┐
 │ Архитектор   │ Разработчик │ Аналитик BI │
 └──────────────┴─────────────┴─────────────┘

```

Так рождается **ComOps Unit** — подразделение,  
которое отвечает за коммуникации как за инфраструктуру.

---

## Практические шаблоны и инструменты

### Шаблон карты коммуникаций

<table id="bkmrk-%E2%84%96-%D0%A1%D0%BE%D0%B1%D1%8B%D1%82%D0%B8%D0%B5-%D0%9A%D0%BE%D0%BC%D0%BC%D1%83%D0%BD%D0%B8%D0%BA%D0%B0%D1%86-1"><thead><tr><th>№</th><th>Событие</th><th>Коммуникация</th><th>Канал</th><th>Участники</th><th>Действия</th><th>API</th></tr></thead><tbody><tr><td>1</td><td>Новый заказ</td><td>“Спасибо за заказ”</td><td>Telegram</td><td>Клиент</td><td>—</td><td>`/order/thank-you`</td></tr><tr><td>2</td><td>Изменился статус заказа</td><td>“Ваш заказ отправлен”</td><td>Telegram</td><td>Клиент</td><td>Подтверждение доставки</td><td>`/order/status`</td></tr><tr><td>3</td><td>Заказ доставлен</td><td>“Пожалуйста, оставьте отзыв”</td><td>Telegram</td><td>Клиент</td><td>Ответить оценкой</td><td>`/order/feedback`</td></tr></tbody></table>

📘 Используется как рабочая таблица при проектировании DMI.

---

### Шаблон таблицы точек интеграции

<table id="bkmrk-endpoint-alias-metho"><thead><tr><th>Endpoint Alias</th><th>Method</th><th>URL</th><th>Описание</th><th>Request Params</th><th>Response</th></tr></thead><tbody><tr><td>`users/connect-bot`</td><td>POST</td><td>`/bots/{botId}/call/users/connect-bot`</td><td>Привязка пользователя к боту</td><td>`{ userId }`</td><td>`{ success: true }`</td></tr><tr><td>`order/thank-you`</td><td>POST</td><td>`/bots/{botId}/call/order/thank-you`</td><td>Благодарность за заказ</td><td>`{ orderId, userId }`</td><td>`{ success: true }`</td></tr><tr><td>`comment/new`</td><td>POST</td><td>`/bots/{botId}/call/comment/new`</td><td>Новый комментарий</td><td>`{ postId, authorId, userIds }`</td><td>`{ success: true }`</td></tr></tbody></table>

---

### Шаблон технического задания (TЗ) на DMI-проект

1. **Цель:** интеграция мессенджеров в бизнес-процесс X
2. **Системы:** CRM, сайт, ERP, Metabot
3. **Каналы:** Telegram, WhatsApp
4. **Коммуникационные сценарии:**
    - Регистрация
    - Подтверждение
    - Уведомления
    - Обратная связь
5. **API и события:** описать все эндпоинты
6. **Идентификация пользователей:** `userId ↔ leadId`
7. **Метрики:** вовлечённость, конверсия, удовлетворённость
8. **Безопасность:** авторизация, шифрование, логирование
9. **Артефакты:** карты коммуникаций, таблица эндпоинтов, JSON-сценарии
10. **Сроки и роли.**

---

### Рекомендации по масштабированию

- Начинайте с **одного сценария**, но стройте так, чтобы можно было развивать.
- Внедряйте **единую таблицу идентификаторов** для всех систем.
- Логику коммуникаций оформляйте в виде **карты + эндпоинты + сценарий**.
- Интеграции — через REST API или Webhook Proxy, чтобы не менять ядро CRM.
- Добавляйте аналитику сразу, с первого дня.

---

## Заключение: от Deep Messaging Integration к Communication Operating System

В этой работе мы рассмотрели **первый уровень архитектуры Metabot — Deep Messaging Integration (DMI)**. Мы показали, как **коммуникационный** и **операционный слои** соединяются с бизнес-системами, создавая живую ткань диалогов и событий. Мы **осознанно не касались когнитивного слоя (Cognitive Layer)** — памяти, понимания и интеллекта — он будет раскрыт в отдельной части серии.

Если вы только начинаете внедрение, мы рекомендуем **стартовать с коммуникационного слоя**:

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

Это даст **быстрый бизнес-результат** и позволит увидеть реальную ценность коммуникаций.

Когда потребуется больший эффект — переходите к полноценной интеграции, создавая **end-to-end-сервисы**, где всё работает бесшовно: от CRM до мессенджера. Теперь вы знаете, **как это делать**.

Желаем вам успеха в построении собственной коммуникационной инфраструктуры!

---

💬

> “Когда коммуникации становятся инфраструктурой,  
> предприятие начинает думать и действовать как живой организм.”

# Обработка ошибок API

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

Использование конструкций try..catch не поддерживается платформой на данный момент. Вы, конечно, можете так оборачивать код, но это ни к чему не приведет. Платформа сама, на системном уровне, обеспечивает безопасное выполнение кода и обработку исключительных ситуаций. Мы позаботились об этом: "под капотом" все безопасно, обернуто try..catch. Не нужно беспокоится, что код упадет по непонятным вам причинам.

Ошибки в чат-боте будут только там, где они должны возникать (например, ошибка в коде, синтаксисе, в обработке данных). Для всех случаев платформа Metabot вернет вызывающей стороне 500 ошибку.

При разработке прикладной бизнес-логики вы можете сами возвращать нужную ошибку, когда вам будет необходимо. Например, когда нужно сообщить о проблемах с валидацией или не валидности запроса. В этом случае платформа вернет 200 ответ, а в теле JSON ответа нам нужно добавить информацию об ошибке. Если не уверены, как лучше сформировать тело ответа, можете воспользоваться нашим рекомендованным стандартом, которые приведен ниже.

##### Все возможные коды ответа сервера

<table id="bkmrk-%D0%9A%D0%BE%D0%B4-%D0%BE%D1%82%D0%B2%D0%B5%D1%82%D0%B0-http-%D0%9F%D1%80%D0%B8%D1%87" style="border-collapse: collapse; width: 100%; height: 322.87px; border-style: solid;"><thead><tr style="background-color: #c2e0f4; height: 79.9537px;"><td style="width: 10.6302%; height: 79.9537px; border-style: solid;">Код ответа HTTP

</td><td style="width: 71.3309%; height: 79.9537px; border-style: solid;">Причина

</td><td style="width: 18.037%; height: 79.9537px; border-style: solid;">Возможны ли доп. поле в тела ответа

</td></tr></thead><tbody><tr style="height: 35.1389px;"><td style="width: 10.6302%; height: 35.1389px; border-style: solid;">200

</td><td style="width: 71.3309%; height: 35.1389px; border-style: solid;">Все хорошо. В теле запроса возможны дополнительные ответы.

</td><td style="width: 18.037%; height: 35.1389px; border-style: solid;">Да

</td></tr><tr style="height: 35.1389px;"><td style="width: 10.6302%; height: 35.1389px; border-style: solid;">401

</td><td style="width: 71.3309%; height: 35.1389px; border-style: solid;">Отсутствуют данные для авторизации или не верный токен авторизации.

</td><td style="width: 18.037%; height: 35.1389px; border-style: solid;">Нет

</td></tr><tr style="height: 57.5463px;"><td style="width: 10.6302%; height: 57.5463px; border-style: solid;">403

</td><td style="width: 71.3309%; height: 57.5463px; border-style: solid;">Нет прав для выполнения запроса. Например, у пользователя API, для которого выдан токен, нет прав доступа к чат-боту.

</td><td style="width: 18.037%; height: 57.5463px; border-style: solid;">Нет

</td></tr><tr style="height: 79.9537px;"><td style="width: 10.6302%; height: 79.9537px; border-style: solid;">404

</td><td style="width: 71.3309%; height: 79.9537px; border-style: solid;">Неправильный URL запроса. Возникает, когда точки интеграции нет или URL совсем не верный. Если URL верный, то значит кастомный внутренний эндпоинт не найден по алиасу.

</td><td style="width: 18.037%; height: 79.9537px; border-style: solid;">Нет

</td></tr><tr style="height: 35.1389px;"><td style="width: 10.6302%; height: 35.1389px; border-style: solid;">500

</td><td style="width: 71.3309%; height: 35.1389px; border-style: solid;">Внутренняя ошибка. Например, ошибка в JavaScript коде чат-бота.

</td><td style="width: 18.037%; height: 35.1389px; border-style: solid;">Нет

</td></tr></tbody></table>

##### Тело ответа для 200 ответа

В случае успеха, чат-бот возвращает код ответа **200 OK**, а в теле запроса, содержится информация об успешном выполнении, например:

```JSON
{ 
  "success": true
}
```

<div class="code-block  css-iwznuw" id="bkmrk-%D0%95%D1%81%D0%BB%D0%B8-%D0%B5%D1%81%D1%82%D1%8C-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B0%2C-%D1%82%D0%BE"><div><div role="presentation"><div>Если есть ошибка, то также возвращается **200 ОК** и дополнительно возвращается текст ошибки в поле **message**, например:</div></div></div></div><div id="bkmrk--0">  
</div>```JSON
{ 
  "success": false,
  "message": "Сообщение об ошибке"
}
```

<div id="bkmrk--1"></div>В случае, если необходимо возвращать код ошибки, будет добавлен код ошибки, например:

```JavaScript
{ 
  "success": false,
  "errorCode": 422,
  "message": "Ошибка валидации"
}
```

# Типовые проблемы

В этом разделе вы можете найти решение типовых проблем, с которыми вы можете столкнуться в ходе разработки API интеграции.

1\. Некоторые популярные продукты, такие как Mindbox или Airtable, отказываются авторизовывать запросы, если параметр Authorization в заголовке запроса записан с большой буквы. Странно, но факт.

# Метабот: Тотализатор

<p class="callout info align-left">Конфигурация находится в бизнесе [КОНФИГУРАЦИЯ - Тотализатор](https://app.metabot24.com/custom-tables/1217/fields)</p>

<p class="callout info align-left">Бот Telegram @totalKonfigbot</p>

<span style="font-weight: 400;">Этот бот выполняет функцию тотализатора. </span><span style="font-weight: 400;">Он позволяет сделать ставки, например, на исход боевых состязаний в день шоу.</span>

<span style="font-weight: 400;">Перед началом игры участники должны нажать кнопку **Принять участие**, чтобы записаться в таблицу участников, которым будут приходить уведомления Тотализатора.</span>

<span style="font-weight: 400;">После нажатия кнопки, они фиксируются в таблицу с балансом и фиксацией ставок.</span>

<p class="callout info"><span style="font-weight: 400;">Бот так же адаптирован под ВК</span></p>

### Таблицы

#### Программы тотализатора

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/nnY2T3jfY7l5ihBe-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/nnY2T3jfY7l5ihBe-image.png)

Таблица **programs** содержит программы тотализатора и их статусы.

Описание параметров:

- **Код для ставки** - должен состоять из следующих символов p{номер\_программы}f{номер\_события}, например p3f1 = программа 3, событие 1. Для тестовой программы используйте код p0f1.
- **Номер программы и Номер события** - в таблице записи идут по событиям, а не по программам. То есть на каждое событие каждой программы есть запись. Номер программы в таблице повторяется столько записей, сколько событий у этой программы. По каждой программе кроме тестовой должно быть 3 события.

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/ZeIFdGobUMANpfez-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/ZeIFdGobUMANpfez-image.png)

- **Коэффициент** - на него будут умножаться очки при выигрыше ставки.
- **Случилось?** - показатель сыграло ли событие. 1 - Сыграло/0 - Не сыграло.
- **Статус программы** - не запущено - draft / запущено - start / сыграно - finished.

#### Тотализатор - участники

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/xkwlansN2w6k0WL8-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/xkwlansN2w6k0WL8-image.png)

Таблица **participants** содержит регистрации участников и их ставки.

Описание параметров:

- **Активен?** - статус активности участника. 1 - активен на текущем мероприятии / 0 - неактивен на текущем мероприятии / 2 - неактивен в боте.
- **Баланс** - количество очков. По ним высчитывается победитель.
- **Победитель** - статусы победителей. 1 - победитель / 0 - не победитель / 2 - не участвовал в обязательных программах.
- **Тест** - ставка в тестовой программе.
- **П1:Ф1...Пn:Ф3** - события программ. Для каждого события из таблицы **programs** должен быть свой параметр Пn:Фn и соответствовать коду для ставки из той же таблицы. В этот параметр будет заноситься ставка пользователя по событию.

### Тотализатор - организаторам

**Меню организатора**

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/aR27Cs2pvMMlynvO-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/aR27Cs2pvMMlynvO-image.png)

Из меню организатору доступны следующие действия:

- **Начать игру - тестовая ставка** - запуск тестовой программы.
- **Программы ставок** - слайдер программ.
- **Завершить игру** - завершение всей игры.
- **Посмотреть победителей** - вывод списка победителей.

**Программы ставок**

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/qo7hVf7qJLwRup3k-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/qo7hVf7qJLwRup3k-image.png)

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

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

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/pplWejobmIrbnqe7-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/pplWejobmIrbnqe7-image.png)

При завершении программы зарегистрированным на мероприятие из таблицы рассылается сообщение о закрытии приема ставок.

Далее организатор может выбрать какие события сыграли.

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/UgZUhJ2PMPTzyAqw-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/UgZUhJ2PMPTzyAqw-image.png)

Выбор осуществляется по кнопкам. Выбранные события отображаются в сообщении <span style="font-weight: 400;">(можно одно, несколько или все)</span>. После выбора событий их можно подтвердить по кнопке **Отправить ответ**.

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

**Завершить игру**

После завершения игры зарегистрированным на мероприятие из таблицы рассылается сообщение об этом.

**Посмотреть победителей**

По результатам в таблице высчитываются победители. Победителя может быть максимум 3. Вычисление происходит по количеству баллов.

Если в игре есть программы обязательные к участию для победы, их можно проставить в атрибуте programsX. В нем выставляются номера программ без разделителей, например: 362 - обязательны 2, 3 и 6 программы, если участник не делал в них ставки, то он не может стать победителем.

После расчетов победителей можно отправить участникам рассылкой.

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/7NPMjIpUyifUkgQd-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/7NPMjIpUyifUkgQd-image.png)

<p class="callout warning">После завершения игры, таблица программ должна быть приведена к изначальному состоянию.</p>

### Тотализатор - участникам

#### Тестовая программа

После запуска тестовой программы организатором, участникам отправляется следующее сообщение:

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/sGJpzVn8Fgmmhutn-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/sGJpzVn8Fgmmhutn-image.png)

По кнопке Поставить ставку участник может поставить баллы на событие не превышающие его баланс.

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/pWGzwqyjsuZMMoqN-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/pWGzwqyjsuZMMoqN-image.png)

После завершения тестовой ставки участникам приходит следующее сообщение:

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/PN9UpVZ4YLoe1oBC-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/PN9UpVZ4YLoe1oBC-image.png)

<span class="hljs-number">Подсчет происходит по формуле : Коэффициент</span> \* Ставка + Балланс

#### Основные программы

Основные программы работают по тому же принципу.

При запуске одной из основных программ участникам приходит сообщение:

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/oFuxiZTD2ICjLCvp-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/oFuxiZTD2ICjLCvp-image.png)

По нескольким или одной программе участник может поставить ставку. <span style="font-weight: 400;">Можно бесконечно менять ставки, пока организатор не закрыл их прием по программе.</span>

<span style="font-weight: 400;">После закрытия приема ставок участники получают следующее сообщение:</span>

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/hJr8G83HkKD6P3pd-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/hJr8G83HkKD6P3pd-image.png)

После выбора организатором сыгранных событий они высылаются участникам:

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/U35DpWlLUYdmUkFV-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/U35DpWlLUYdmUkFV-image.png)

Если баланс участника опустился до нуля, он отмечается в таблице как неактивный в данной игре и ему больше не высылаются сообщения о приеме ставок. При подсчете победителей такой участник все-равно учитывается.

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

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/Wr8EG6hBIJxOzbs4-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/Wr8EG6hBIJxOzbs4-image.png)

Победителям и другим участникам отсылается разный текст в зависимости от их статуса.

После завершения участники текущей игры отмечаются в таблице как неактивные в боте.

# Справочники в Pyrus

Из Метабот можно передавать справочники в Pyrus. Для этого необходимо сделать интеграцию с PyrusApi.

### Настройка таблиц

Для работы интеграции в боте необходимо создать таблицу pyrus\_task\_bindings:

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/YGJisN1ZUff9ivxn-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/YGJisN1ZUff9ivxn-image.png)

В плагине для интеграции будут использоваться поля pyrus\_task\_id и channel\_id.

### Настройка интеграции

Шаги подключения интеграции:

- Добавьте в ваш бизнес плагин Business.Integrations.PyrusApi со следующим кодом:

<details id="bkmrk-%7B-_apibase%3A-%27https%3A%2F"><summary></summary>

```JavaScript
{
    _apiBase: 'https://api.pyrus.com/v4',
    _authUrl: 'https://accounts.pyrus.com/api/v4/auth',
    set apiBase(value) {
      this._apiBase = value
    },
    get apiBase() {
      return this._apiBase
    },
    set authUrl(value) {
      this._authUrl = value
    },
    get authUrl() {
      return this._authUrl
    },
  
    /**
     * HTTP-запрос к Pyrus API с Bearer-токеном.
     * @param {string} method - GET, POST, etc.
     * @param {string} uri - полный URI или путь относительно API_BASE
     * @param {Object|string|null} [body=null] - тело запроса (объект будет JSON.stringify)
     * @returns {Object|null} - разобранный JSON ответ или null при ошибке
     */
    request: function(method, uri, body = null) {
      const url = uri.startsWith('http') ? uri : this._apiBase + (uri.startsWith('/') ? uri : '/' + uri)
      const token = this.getToken()
      if (!token) return null
      const headers = {
        'Authorization': 'Bearer ' + token,
        'Content-Type': 'application/json'
      }
      
      try {
        
        api.request(method, url, [], [], null, body, headers)
        const code = api.getLastResponseCode()
        if (code === 200) {
          const content = api.getLastResponseContent()
          return content ? JSON.parse(content) : null
        }

        return false
      } catch (e) {
        debug(e.stack)
        return null
      }
    },
  
    /**
     * Получает токен из атрибутов бота (при необходимости можно вызвать refreshToken).
     * @returns {string|null}
     */
    getToken: function() {
      return bot.getAttr('pyrus_api_token') || null
    },
  
    /**
     * Обновляет токен через POST /api/v4/auth, сохраняет в bot.setAttr('pyrus_api_token', ...).
     * @returns {boolean} - успех
     */
    refreshToken: function() {
      const login = bot.getAttr('pyrus_api_login')
      const securityKey = bot.getAttr('pyrus_api_security_key')
      if (!login || !securityKey) {
        debug("Нет токенов")
        return false
      }
      const headers = { 'Content-Type': 'application/json' }
      try {
        api.request('POST', this._authUrl, [], [], null, { login: login, security_key: securityKey }, headers)
        if (api.getLastResponseCode() !== 200) return false
        const content = api.getLastResponseContent()
        const data = content ? JSON.parse(content) : null
        const token = data?.access_token || data?.token
        if (token) {
          bot.setAttr('pyrus_api_token', token)
          return true
        }
        return false
      } catch (e) {
        
        debug(e.stack)
        return false
      }
    },
  
    /**
     * Ищет task_id в таблице pyrus_task_bindings по channel_id.
     * @param {string} channelId
     * @returns {number|null} - pyrus_task_id или null
     */
    getTaskIdByChannelId: function(channelId) {
      if (!channelId) return null
      const rows = table.find('pyrus_task_bindings', [], [
        ['channel_id', '=', channelId]
      ])
      const first = rows?.[0]
      const id = first?.pyrus_task_id
      return id != null ? Number(id) : null
    },

    /**
     * Достаёт lead id из маппинга полей (поле MetabotLeadId).
     * @param {Array} mappings - массив { code, value }
     * @returns {number|null}
     */
    getLeadIdByMapFields: function(mappings) {
      if (!Array.isArray(mappings)) return null
      const item = mappings.find(m => m?.code === 'MetabotLeadId')
      if (!item || item.value == null) return null
      const raw = String(item.value).split(',')[0].trim()
      const id = parseInt(raw, 10)
      return Number.isNaN(id) ? null : id
    },

    /**
     * Определяет lead id по channel_id (формат "lead_<id>_dialog_...") или из маппинга.
     * @param {string} channelIdStr - строка channel_id
     * @param {Array} [mappingsFallback] - маппинг полей для fallback (getLeadIdByMapFields)
     * @returns {number|null}
     */
    getLeadIdByChannelId: function(channelIdStr, mappingsFallback) {
      if (channelIdStr && typeof channelIdStr === 'string') {
        const parts = channelIdStr.split('_')
        if (parts.length >= 2) {
          const id = parseInt(parts[1], 10)
          if (!Number.isNaN(id)) return id
        }
      }
      return this.getLeadIdByMapFields(mappingsFallback || [])
    },

    /**
     * GET /v4/tasks/{taskId}
     * @param {number} taskId
     * @returns {Object|null} - задача с form_id и т.д.
     */
    getTask: function(taskId) {
      return this.request('GET', '/tasks/' + taskId)
    },
  
    /**
     * GET /v4/forms/{formId}
     * @param {number} formId
     * @returns {Object|null} - форма с полями (fields)
     */
    getForm: function(formId) {
      return this.request('GET', '/forms/' + formId)
    },
  
    /**
     * GET /v4/catalogs/{catalogId}
     * @param {number} catalogId
     * @returns {Object|null} - справочник с items
     */
    getCatalog: function(catalogId) {
      return this.request('GET', '/catalogs/' + catalogId)
    },
  
    /**
     * Рекурсивный поиск поля по коду (info.code) или имени (name) в структуре формы.
     * @param {Array|Object} fields - массив полей или объект с полем fields
     * @param {string} fieldName - код поля (info.code) или название (name)
     * @returns {Object|null} - поле с id, name, type, info.catalog_id
     */
    getFieldByName: function(fields, fieldName) {
      if (!fields || !fieldName) return null
      const list = Array.isArray(fields) ? fields : (fields.fields || fields.items || [])
      for (let i = 0; i < list.length; i++) {
        const f = list[i]
        if (f?.info?.code === fieldName || f?.name === fieldName) return f
        if (f?.type === 'approval' && f?.steps) {
          const inSteps = this.getFieldByName(f.steps, fieldName)
          if (inSteps) return inSteps
        }
        if (f?.fields?.length) {
          const nested = this.getFieldByName(f.fields, fieldName)
          if (nested) return nested
        }
      }
      return null
    },
  
    /**
     * Ищет item_id в справочнике по значению в указанном столбце.
     * @param {number} catalogId
     * @param {string} value - искомое значение
     * @param {string} [columnName] - имя столбца для сравнения (например "Name", "Наименование"). Если не задано, ищем по первому текстовому столбцу.
     * @returns {number|null} - item_id
     */
    getCatalogItemId: function(catalogId, value, columnName) {
      if (value == null || value === '') return null
      const catalog = this.getCatalog(catalogId)
      const items = catalog?.items || catalog?.catalog?.items
      if (!Array.isArray(items) || items.length === 0) return null
      const columns = catalog?.columns || catalog?.catalog?.columns || []
      const colName = columnName || (columns[0]?.name)
      const valueStr = String(value).trim().toLowerCase()
      for (let i = 0; i < items.length; i++) {
        const item = items[i]
        const itemId = item?.item_id ?? item?.id
        const cells = item?.cells || item?.values || []
        for (let c = 0; c < columns.length; c++) {
          const col = columns[c]
          if (colName && col?.name !== colName) continue
          const cell = cells[c] ?? cells[col?.id]
          const cellVal = (cell?.value != null ? cell.value : cell)
          if (cellVal != null && String(cellVal).trim().toLowerCase() === valueStr) {
            return itemId != null ? Number(itemId) : null
          }
        }
        if (!colName && cells?.length) {
          const firstVal = cells[0]?.value != null ? cells[0].value : cells[0]
          if (firstVal != null && String(firstVal).trim().toLowerCase() === valueStr) {
            return itemId != null ? Number(itemId) : null
          }
        }
      }
      return null
    },
  
    /**
     * POST /v4/tasks/{taskId}/comments с field_updates.
     * @param {number} taskId
     * @param {string} text - текст комментария
     * @param {Array} fieldUpdates - [{ id, value }, ...], value для справочника: { item_id: number }
     * @returns {Object|null}
     */
    updateTaskFields: function(taskId, text, fieldUpdates) {
      
      return this.request('POST', '/tasks/' + taskId + '/comments', {
        text: text || '',
        field_updates: Array.isArray(fieldUpdates) ? fieldUpdates : []
      })
    },
  
    /**
     * Строит массив field_updates по маппингу полей формы.
     * catalogMappings: [{ field_name|code, value, catalog_column? }, ...]
     * Для полей-справочников ищет item_id по value в каталоге, для остальных подставляет value как есть.
     * @param {Object|number} formOrFormId - объект формы с полем fields или id формы
     * @param {Array} catalogMappings
     * @returns {Array} - field_updates для updateTaskFields
     */
    buildFieldUpdates: function(formOrFormId, catalogMappings) {
      if (!Array.isArray(catalogMappings) || !catalogMappings.length) return []
      const isFormObject = formOrFormId != null && typeof formOrFormId === 'object' && Array.isArray(formOrFormId.fields)
      const formFields = isFormObject ? formOrFormId.fields : (() => {
        const form = this.getForm(formOrFormId)
        return form?.fields || form?.form?.fields || []
      })()
      const updates = []
      for (const m of catalogMappings) {
        const fieldName = m?.field_name || m?.code
        const value = m?.value
        if (fieldName == null || value == null) continue
        const field = this.getFieldByName(formFields, fieldName)
        if (!field?.id) continue
        const fieldType = (field.type || '').toLowerCase()
        const catalogId = field.info?.catalog_id ?? field.catalog_id
        if (catalogId && ['catalog', 'choice', 'lookup'].includes(fieldType)) {
          const col = m?.catalog_column
          if (Array.isArray(value)) {
            const itemIds = value
              .map(v => this.getCatalogItemId(catalogId, v, col))
              .filter(id => id != null)
            if (itemIds.length) updates.push({ id: field.id, value: { item_ids: itemIds } })
          } else {
            const itemId = this.getCatalogItemId(catalogId, value, col)
            if (itemId != null) updates.push({ id: field.id, value: { item_id: itemId } })
          }
        } else {
          updates.push({ id: field.id, value: value })
        }
      }
      return updates
    }
  }
```

</details>- В Атрибуты бота добавьте следующие системные переменные: 
    - **pyrus\_api\_login** - логин аккаунта Pyrus
    - **pyrus\_api\_security\_key** - ключ доступа к АПИ
    - **pyrus\_api\_token** - токен авторизации АПИ
    - **refreshTokenTime** - время для обновления pyrus\_api\_token (по-умолчанию поставьте 0)

[![image.png](https://docs.metabot24.ru/uploads/images/gallery/2026-04/scaled-1680-/zZvHxEg5R3DuUlKb-image.png)](https://docs.metabot24.ru/uploads/images/gallery/2026-04/zZvHxEg5R3DuUlKb-image.png)

- В место где хотите передавать справочник добавьте код обновления заявки:

```JavaScript
let pyrusApi = snippet("Business.Integrations.PyrusApi")
let task_id = pyrusApi.getTaskIdByChannelId(channelId)

let mappings = [{
              "code": "CustomCatalog1",
              "value": [lead.getAttr('Подотдел'), lead.getAttr('Структура')]
           }]

let now = new Date();
let refreshTokenTime = now.getTime() + (1000*60*60*24);

if (task_id) {
  if(bot.getIntAttr('refreshTokenTime') <= now.getTime()){
    bot.setAttr('refreshTokenTime', refreshTokenTime)
    pyrusApi.refreshToken()
  }
  let task = pyrusApi.getTask(task_id)
  let formId = task?.task?.form_id
  
  if (formId) {
    let form = pyrusApi.getForm(formId)
    // Получаем под капотом все данные полей и самостоятельно маппим
    let fieldUpdates = pyrusApi.buildFieldUpdates(form, mappings)
    if (fieldUpdates?.length) {
      pyrusApi.updateTaskFields(task_id, "Поля формы обновлены", fieldUpdates)
    }
  }
}
```

Разберем код:

- В первой строке обращаемся к плагину PyrusApi.
- Во второй забираем из таблицы заявок id заявки по id канала.
- Объявляем передаваемые параметры в **mappings**. Поле **code** должно соответствовать коду поля справочника в форме в Pyrus, а **value** данным из справочника.

<p class="callout info">Второй способ передачи справочников:</p>

```JavaScript
{
  "code": "Тарифы", - По названию
  "value": "Стартовый" - Единичный выбор
}
```

- Далее вычисляем пришло ли время обновления токена, если да, то обновляем и записываем новые данные в атрибуты бота.
- В 17 строке находим задачу в Pyrus через АПИ.
- В 21 находим форму в Pyrus через АПИ.
- В 23-25 обновляем поля задачи.

<p class="callout info">Данный функционал работает для передачи любых полей формы</p>