Подключение CRM с помощью шаблона
MonoPbx подключается к CRM без написания кода. Вы передаёте АТС шаблон: краткое описание HTTP API CRM в формате YAML или JSON с учётными данными, которые назван в шаблоне. Механизм шаблонов затем использует его для четырёх задач:
| Что | Когда это происходит |
|---|---|
| Lookup: поиск контакта по номеру телефона | Всплывающая карточка и имена звонящих |
| Search: поиск контактов по введённому тексту | Поиск контактов |
| Create contact: создание контакта в CRM | По запросу пользователя или API |
| Journal: запись каждого завершённого звонка в CRM | Автоматически, для каждого завершённого внешнего звонка, с повторными попытками |
| Click to call: преобразование телефонных номеров из CRM в номера для набора | Когда пользователь набирает контакт |
Это руководство описывает полную интеграцию с примерной CRM под названием sample-crm. Замените значения данными вашей CRM.
Перед началом
Вам понадобятся:
- Базовый адрес API вашей CRM. Он должен быть
httpsи публичным, без строки запроса и без учётных данных в адресе. - Ключ API или токен для CRM с правом читать и создавать контакты и записывать записи о звонках.
- Право
integrations:writeв MonoPbx.
1. Изучите шаблон
Шаблон имеет фиксированную структуру. Вот шаблон с lookup, journal и click-to-call:
schema: mpbx.crm-template/v1 # required, exactly this value
id: sample-crm # lowercase letters, digits, - and _
name: Sample CRM
base_url: https://crm.example.com/api/v1
secrets: [api_token] # credentials the admin enters, write-only
operations:
lookup:
request:
method: GET
path: "/contacts/lookup?phone={{phone|digits}}"
headers:
Authorization: "Bearer {{secret.api_token}}"
response:
contacts: "$.data[*]" # where the list of contacts is
fields:
id: "$.id"
name: "$.full_name" # required for lookup and search
company: "$.account.name"
email: "$.email"
phones: "$.phones[*]"
url: "$.web_url"
not_found_status: [404] # "no such contact", not an error
timeout_ms: 3000
journal:
request:
method: POST
path: "/calls"
headers:
Authorization: "Bearer {{secret.api_token}}"
body:
json:
direction: "{{direction}}"
number: "{{number|digits}}"
started_at: "{{started_at}}"
duration_secs: "{{duration_secs|num}}"
disposition: "{{disposition}}"
note: "Call {{call_id}}"
click_to_call:
default_country_code: "+52" # added to numbers written nationally
national_prefix: "01" # removed from numbers written nationally
Что важно знать:
- Шаблон — это данные, а не код. Он может использовать только заполнители
{{name}}, перечисленные для каждой операции,{{secret.<name>}}для объявленного учётного данного и фильтры|digitsи|num. Условий, циклов и скриптов нет. - Заключайте в кавычки каждое значение, содержащее
{{, в YAML; иначе YAML прочитает его как отображение. - Адрес остаётся на хосте шаблона. Сформированный запрос, который выходит за пределы хоста, указанного в
base_url, отклоняется. - JSON тоже поддерживается. Документ, который начинается с
{, читается как JSON. - Размер шаблона не более 64 КиБ. Якоря, псевдонимы и теги YAML не принимаются.
Точный список заполнителей каждой операции см. в GET /api/v1/integrations/crm/reference. Там перечислены ограничения, переменные для каждой операции и полный пример шаблона.
2. Проверьте шаблон
Проверка охватывает весь шаблон и сообщает о каждой проблеме с её местом в документе, например operations.lookup.request.path. Сетевой запрос не выполняется, поэтому проверку можно запустить до получения учётных данных.
Отправьте шаблон на POST /api/v1/integrations/crm/validate (право integrations:write). Точное тело запроса есть в документе OpenAPI по адресу /api/v1/openapi.json. Исправьте каждую указанную проблему и проверьте снова. Создание или изменение интеграции выполняет те же проверки.
3. Создайте интеграцию с учётными данными
Создайте интеграцию через POST /api/v1/integrations/crm. Отправьте шаблон и значения учётных данных для каждого имени, перечисленного в secrets. Нужно право integrations:write.
- Учётные данные доступны только для записи. При сохранении они зашифровываются ключом вашей компании, никакой маршрут их не возвращает, и они никогда не попадают в журналы или журнал аудита. При чтении выводятся только имена учётных данных и признак того, задано ли каждое из них.
- Чтобы изменить учётные данные позже, отправьте все их снова через
PUT /api/v1/integrations/crm/{id}/credentials. - Если при изменении шаблон переносится на другой адрес (схема, хост или порт
base_url), сохранённые учётные данные удаляются, а интеграция выключается, чтобы значения могли уходить только на адрес, который одобрил их владелец.
Запомните id интеграции: он понадобится на следующих шагах.
4. Запустите консоль тестирования
Консоль тестирования выполняет одну операцию с переданными вами переменными и показывает, что произошло.
POST /api/v1/integrations/crm/{id}/test выполняет операцию. Начните с dry_run: true: запрос формируется и показывается, а учётные данные отображаются как <name>, но ничего не отправляется. Это самый безопасный способ проверить заполнители.
Затем выполните операцию по-настоящему, например lookup для известного номера телефона. Ответ показывает запрос, код состояния CRM, задержку и контакты, которые прочитал шаблон.
:::caution Консоль тестирования обращается к настоящей CRM
Запуск create_contact создаёт контакт, а запуск journal записывает запись. Используйте тестовый контакт или тестовую учётную запись в CRM. Консоль разрешает не более 20 запусков на компанию в минуту.
:::
5. Включите интеграцию
Включите интеграцию (PATCH /api/v1/integrations/crm/{id}). Включённая интеграция используется для поиска, поиска контактов и журналирования.
Проверьте её состояние через GET /api/v1/integrations/crm. Каждая интеграция показывает одно из следующих состояний:
| Состояние | Значение |
|---|---|
disabled | Выключена. |
needs_credentials | Учётному данному, указанному в шаблоне, не задано значение. |
unknown | Включена, но ещё не вызывалась. |
healthy | Последний вызов выполнен успешно. |
degraded | Один или два вызова подряд завершились ошибкой. |
failing | Три и более вызовов подряд завершились ошибкой. |
Вызов, который не покинул АТС, например ошибка шаблона или отсутствующих учётных данных, не влияет на состояние CRM.
6. Как работает журналирование
Каждый завершённый внешний звонок (входящий или исходящий, с номером телефона) становится одним заданием журналирования для каждой включённой интеграции, в шаблоне которой есть операция journal. Задание отправляется АТС в фоновом режиме:
- Задание, которое завершилось ошибкой по временной причине (проблемы сети, тайм-аут, ответ
408,425,429или5xx), повторяется через 30 секунд, 2 минуты, 10 минут, 1 час и 4 часа. После шести попыток оно считается недоставленным. - Задание, которое CRM отклоняет (любой другой
4xx, заблокированный адрес, шаблон, который не может сформировать запрос, или отсутствующие учётные данные), сразу считается недоставленным. - Недоставленное задание можно повторить через
POST /api/v1/integrations/crm/jobs/{id}/retry. Недоставленные задания хранятся 30 дней. - Выключенная интеграция держит свои задания в ожидании, пока её снова не включат.
Если операция journal использует contact_id, а в шаблоне есть также lookup, АТС сначала ищет номер, чтобы получить идентификатор контакта в CRM.
Для журнала ошибок используйте GET /api/v1/integrations/crm/{id}/log?filter=outcome:eq:error. Журнал хранит машинный код ошибки, код статуса HTTP и задержку, а также номер или текст, замаскированные, кроме последних четырёх символов. Тело ответа, URL и учётные данные он никогда не хранит.
Права доступа
| Действие | Право |
|---|---|
| Просмотр интеграций, журнала и состояния | integrations:read |
| Создание, изменение, проверка, тестирование и повтор | integrations:write |
| Поиск контактов по номеру и тексту | contacts:read |
Чего шаблон пока не умеет
- Потоки обновления OAuth. Шаблон проходит аутентификацию с учётными данными, которые он указывает: ключи API, bearer-токены в заголовке или в строке запроса, либо HTTP Basic. Для HTTP Basic введите уже закодированные в Base64
user:passwordкак учётное данное и напишите в шаблонеAuthorization: "Basic {{secret.basic}}". - Готовые коннекторы для конкретных CRM планируются на том же механизме. До их появления напишите шаблон для вашей CRM.