Metabot API

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

«API — это продукт. API — это также то, как вы разрабатываете, продаете и доставляете цифровые и все чаще физические продукты своим клиентам»
— Кин Лейн, главный евангелист Postman


Коммуникационная low-code платформа Metabot обладает встроенным конструктором API для организации взаимодействия с внешними системами по REST в соответствии со стандартом OpenAPI 3.

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

API состоит из точек интеграции, называемых эндпоинтами (endpoints) или конечными точками (точками доступа, точками связи и т.п.). Настройка точек интеграции происходит в разделах Внутреннее и Внешнее API доступное из меню Настроек бота.

Снимок экрана 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

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

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

Поле Описание
Флаг активности Если убрать флаг, то при обращению через API к данному endpoint будет возвращена ошибка.
Алиас

Дополнительный уникальный идентификатор. Используется как часть URL-адреса для обращения к конечной точке через API, а также для вызова в JavaScript функциях.


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


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

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

 

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

JavaScript для вычисления API ответа (Response Body)

JavaScript для вычисления содержимого API ответа. Данный JS код будет выполнен при обращении к внутреннему API (по алиасу), результат выполнения кода будет являться телом ответа на API запрос.


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


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

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

Пример:


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.

Комментарий

Любой текст. Доступно указание любых HTML-тэгов.

На данный момент доступен вызов кастомного внутреннего API только с методом POST и в формате JSON. Методы GET, PUT, PATCH, DELETE не поддерживаются.

2.png

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

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

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

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

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

Внимание! При работе в Swagger платформы будут выполняться реальные API запросы, а не эмуляция API.

3.png

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

4.png

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

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

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

{
  "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"
    }
  }
}

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

Поле Обязательность заполнения Описание

lead_id

-

В JS будет подготовлен и доступен полноценный объект lead, если у лида есть персона, то также будет доступен объект person.

ticket_id

-

В JS будет подготовлен и доступен полноценный объект ticket.

trigger_id или trigger_code

-

В JS будут доступны переменные triggerId, triggerName.

script_request_params

-

В JS будет подготовлены и доступны полноценные объекты request и last_request.
Авторизация запросов API

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

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

authorization: Bearer <Access Token>
Host: https://app.metabot24.com
Генерация токена доступа к API

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

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

16.png

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

17.png

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

18.png

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

19.png

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

20.png

Если вдруг не найдете опцию создания API токена в вашем аккаунте, запросите токен в поддержке.

Внешнее API

5.png

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

6.png

7.png

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

Метод для вызова внешнего API из 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
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

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

Поле Описание
Флаг активности Если убрать флаг, то вызов данного Endpoint не будет выполняться и метод api.callEndpoint(...) вернет null.
Код

Дополнительный уникальный идентификатор. Используется для указания объекта, например, в JavaScript функциях. В этом случае Код, используется как первый аргумент ($externalApiEndpointCode) метода api.callEndpoint(...).

 

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

URL конечной точки (Endpoint URL) Допустимо использование макропеременных.
JavaScript для вычисления API запроса (Request Body)

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


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


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

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

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


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.

Метод(тип) HTTP запроса

POST / GET / PATCH / и т.д.

Формат HTTP запроса

JSON / TEXT

Заголовки HTTP запроса (HTTP Headers)

Заголовки, которые будут переданы в HTTP запросе. В данном поле указывается JSON объект или массив. Допустимо использование макропеременных.


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

Пример 1 для HTTP Headers8.png

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

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

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

{{ &$$my_headers }}

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

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

11.png


JavaScript:

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

Headers:

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

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

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

12.png


JavaScript:                        

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

Headers:

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

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

Параметры HTTP запроса (HTTP Request Options)

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

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

 

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

Также доступна установка параметров HTTP запроса помощью переменной бота sys_api_request_options.

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

13.png

JavaScript:

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

HTTP Request Options:

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

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

14.png

 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 }}
Конфиг HTTP клиента (HTTP Client Config)

Параметры HTTP клиента.

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

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


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

Также доступна установка конфига HTTP клиента с помощью переменной бота sys_api_http_client_config.


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


15.png

Настройки прокси (Proxy URL)

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

 

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

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

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

Комментарий

Любой текст. Доступно указание любых HTML-тэгов.

9.png

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

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

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

Пример:

10.png

С API так же можно работать с помощью JS методов. Все методы и их описание вы можете посмотреть в Справочнике по функциям JS

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

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

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

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

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

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

Код ответа HTTP

Причина

Возможны ли доп. поле в тела ответа

200

Все хорошо. В теле запроса возможны дополнительные ответы.

Да

401

Отсутствуют данные для авторизации или не верный токен авторизации.

Нет

403

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

Нет

404

Неправильный URL запроса. Возникает, когда точки интеграции нет или URL совсем не верный. Если URL верный, то значит кастомный внутренний эндпоинт не найден по алиасу.

Нет

500

Внутренняя ошибка. Например, ошибка в JavaScript коде чат-бота.

Нет

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

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

{ 
  "success": true
}
Если есть ошибка, то также возвращается 200 ОК и дополнительно возвращается текст ошибки в поле message, например:

{ 
  "success": false,
  "message": "Сообщение об ошибке"
}

В случае, если необходимо возвращать код ошибки, будет добавлен код ошибки, например:

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