MACRO

Кастомные каналы уведомлений

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

Канал подходит, когда уведомления нужно получать там, с чем MACRO не интегрирована напрямую: в корпоративном мессенджере внутри периметра компании, в собственном боте, в системе заявок. Уведомление при этом остаётся и в самой MACRO: канал его дублирует, а не заменяет.

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

  1. Администратор компании заводит канал: адрес приёмника и секрет для подписи запросов.
  2. Сотрудник в своём профиле отмечает, какие уведомления получать в этот канал.
  3. Когда в MACRO возникает уведомление для сотрудника, система отправляет на адрес канала POST-запрос с уведомлением, подписанный секретом канала.
  4. Приёмник отвечает кодом 2xx — уведомление доставлено. Если приёмник недоступен или ответил ошибкой сервера, MACRO повторяет отправку около суток.

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

#Как добавить канал

Управлять каналами могут сотрудники с правом редактирования компании.

  1. Откройте Компания → Интеграции → Каналы уведомлений.

  1. Нажмите Добавить канал и заполните форму:

ПолеЧто указать
НазваниеЕго сотрудники видят в настройках оповещений. Оно же уходит приёмнику в теле запроса
Адрес приёмникаАдрес вашего сервиса, только https://
Подпись поля идентификатора сотрудникаНеобязательно. Например, «Логин в мессенджере». Если заполнить, каждый сотрудник сможет указать в профиле свой логин, и он будет приходить в запросе. Оставьте пустым, если приёмник узнаёт сотрудника по почте или идентификатору MACRO
Канал включёнВыключенный канал ничего не отправляет
Секрет подписиСтрока, которой MACRO подписывает каждый запрос, а приёмник проверяет подпись. Обязателен для включённого канала
Дополнительные заголовкиНеобязательно. Например, Authorization: Bearer …, если приёмник требует свой токен
  1. Нажмите Сохранить. Канал появится в списке, а адрес приёмника будет проверен сразу при сохранении.

#Как проверить канал

Нажмите Проверить в строке канала. MACRO сразу отправит на адрес канала пробный запрос и покажет код ответа приёмника, время ответа и тело ответа:

Пробный запрос никому не адресован — это только проверка настройки. Приёмник должен ответить кодом 2xx и ничего не отправлять сотрудникам. Отличить пробу от настоящего уведомления можно по заголовку X-Macro-Event: notification.test или по полю "test": true в теле.

Проба уходит сразу, мимо очереди: в колонке «Последняя доставка» она не отражается и не повторяется при ошибке. У выключенного канала проба не отправляется.

#Как сотрудник подписывается на канал

  1. Сотрудник открывает свой профиль → Оповещения.
  2. В таблице появляется колонка с названием канала. Сотрудник включает те группы уведомлений, которые хочет получать в этот канал:

  1. Если в настройках канала задана подпись поля идентификатора, ниже появляется блок «Идентификаторы в каналах компании». Сотрудник указывает там свой логин — он будет приходить в запросе как recipient.externalUserName:

  1. Сотрудник нажимает Сохранить.

Колонка показывается только для включённых каналов. Уволенным сотрудникам уведомления в канал не отправляются.

#Где смотреть результат доставки

В колонке «Последняя доставка» раздела Каналы уведомлений показан исход последней отправки по каналу:

СостояниеЧто значит
«Попыток доставки ещё не было»В канал ещё ничего не отправлялось. Проверьте, что сотрудники подписаны на канал
«Доставлено»Приёмник ответил кодом 2xx
«Повторяется»Приёмник недоступен, не ответил за 15 секунд или ответил 5xx / 429. MACRO повторит отправку сама. Под состоянием — число попыток, код и начало ответа
«Доставка прекращена»Приёмник отклонил запрос (4xx) или сутки повторов не помогли. Под состоянием — код и начало ответа приёмника
«Отменено»Уведомление подошло к отправке, пока канал был выключен

Уведомления в состоянии «Доставка прекращена» и «Отменено» сами больше не отправляются. Если их нужно доставить повторно, обратитесь в службу сопровождения в течение 30 дней.

#Изменение секрета и заголовков

Откройте канал кнопкой Настроить:

  • Секрет. Чтобы сменить секрет, введите новый и сохраните. Пустое поле означает «оставить прежний». Новый секрет действует сразу для всех запросов, в том числе для повторов уже стоящих в очереди уведомлений, поэтому на время смены приёмнику лучше принимать подпись обоими секретами.
  • Заголовки. Значения заголовков не показываются, поэтому изменить один заголовок нельзя. Отметьте «Задать заголовки заново» и укажите весь набор — он заменит прежний целиком. «Удалить заголовки» убирает их все.
  • Заголовок Content-Type задать нельзя: тело всегда JSON. Нельзя также переопределить заголовки User-Agent и X-Macro-* — их выставляет MACRO.

#Выключение и удаление канала

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

#Для разработчиков приёмника

#Требования к приёмнику

  • Адрес — https:// на стандартном порту 443, с действительным сертификатом, TLS 1.2 и выше.
  • В адресе — имя сервера, а не IP-адрес. Имя должно указывать на публичный адрес в интернете и не должно содержать домен, на котором работает MACRO вашей компании.
  • Логин и пароль в адресе не допускаются. Для авторизации используйте подпись или дополнительный заголовок канала.
  • Приёмник отвечает за 15 секунд. Если обработка дольше — примите запрос, ответьте 2xx и обработайте уведомление у себя асинхронно.
  • Приёмник проверяет подпись запроса, отбрасывает повторы по ключу идемпотентности и принимает пробные запросы.

#Запрос

POST <адрес приёмника>
Content-Type: application/json; charset=utf-8
User-Agent: MacroCRM-Webhook/1.0
X-Macro-Event: notification.created
X-Macro-Delivery: 3f6c0a9e-2b71-4c58-9e0d-8b4f2a1c7d35
X-Macro-Timestamp: 1791261667
X-Macro-Idempotency-Key: 500.12.987654
X-Macro-Signature: sha256=07b3de7fcb9d092243a8d45ed4fb5367b5077649110a4ea7a589ecb3603d3b45

Плюс дополнительные заголовки из настроек канала.

ЗаголовокЗначение
X-Macro-Eventnotification.created — уведомление, notification.test — проба
X-Macro-DeliveryИдентификатор попытки. У каждого повтора новый
X-Macro-TimestampВремя отправки этой попытки, Unix-время в секундах
X-Macro-Idempotency-KeyКлюч уведомления: одинаков у всех повторов одного уведомления в один канал
X-Macro-SignatureПодпись запроса

#Пример уведомления

Сотруднику назначили задачу:

{
  "deliveryId": "3f6c0a9e-2b71-4c58-9e0d-8b4f2a1c7d35",
  "sentAt": "2026-10-06T04:41:07+00:00",
  "schemaVersion": "1.0",
  "event": "notification.created",
  "channel": {
    "id": 12,
    "name": "Корпоративный мессенджер"
  },
  "company": {
    "macroId": 500,
    "name": "Пример Девелопмент",
    "host": "crm.example.ru"
  },
  "recipient": {
    "macroUserId": 12345,
    "fullName": "Иванов Иван Иванович",
    "email": "i.ivanov@example.ru",
    "phone": "+7 (900) 000-00-00",
    "externalUserName": "i.ivanov"
  },
  "notification": {
    "macroId": 987654,
    "type": "tasks_assigned",
    "group": "common",
    "priority": 0,
    "createdAt": "2026-10-06T09:41:06+05:00",
    "subject": "Вы назначены исполнителем по задаче",
    "text": "Позвонить клиенту\n🙂 Петров Пётр\n🗓 06.10.2026, 18:00",
    "html": "<a href=\"https://crm.example.ru/account/tasks/view/1001/\">Позвонить клиенту</a><br /><br />🙂 Петров Пётр<br />🗓 06.10.2026, 18:00",
    "entity": {
      "type": "tasks",
      "id": 1001
    },
    "sender": {
      "macroUserId": 42,
      "fullName": "Петров Пётр"
    },
    "data": {
      "task_id": 1001,
      "task_title": "Позвонить клиенту",
      "role": "manager",
      "date_finish": "2026-10-06 18:00:00",
      "date_finish_time": "18:00"
    }
  }
}

Пробный запрос (X-Macro-Event: notification.test) содержит только данные канала:

{
  "deliveryId": "8c2e5d14-6a90-4b3f-a1d7-0e9f4b6c2a58",
  "sentAt": "2026-10-06T04:41:17+00:00",
  "test": true,
  "channel": {
    "id": 12,
    "name": "Корпоративный мессенджер"
  }
}

Разбирайте тело как JSON-объект: порядок полей не гарантируется. В реальном запросе символ / в строках экранирован (https:\/\/crm.example.ru\/...) — это то же значение JSON.

#Поля уведомления

ПолеОписание
channel.idИдентификатор канала в MACRO. Не меняется, по нему приёмник различает каналы
channel.nameНазвание канала. Может меняться
company.macroId, company.name, company.hostКомпания и домен MACRO, из которого собираются ссылки
recipient.macroUserIdИдентификатор сотрудника в MACRO. Есть всегда и не меняется
recipient.email, recipient.phone, recipient.fullNameДанные из карточки сотрудника. Почта и телефон — если заполнены
recipient.externalUserNameЛогин, который сотрудник указал в профиле. Есть, только если у канала задана подпись поля и сотрудник его заполнил
notification.macroIdИдентификатор уведомления
notification.typeТочное событие, например tasks_assigned
notification.groupГруппа уведомлений, на которую подписан сотрудник, например common — «Основные»
notification.createdAtКогда возникло уведомление
notification.subjectЗаголовок уведомления, до 255 символов
notification.textТекст уведомления без разметки, переносы строк — \n, до 1000 символов. Его можно сразу отправить в мессенджер
notification.htmlТекст уведомления в том виде, как его показывает MACRO, со ссылкой на карточку, до 1000 символов
notification.actionUrlСсылка на карточку в MACRO. Приходит не у всех типов уведомлений; ссылка также есть в html
notification.entityОбъект, к которому относится уведомление: type и id
notification.senderСотрудник, который совершил действие. Может отсутствовать
notification.dataИсходные данные события. Состав зависит от типа — пригодится, если приёмник собирает собственный текст сообщения

Длинные subject, text и html обрезаются, последний символ обрезанного значения — …. В тексте сохраняются эмодзи, которыми MACRO помечает поля уведомления: «👤» — контакт, «🗓» — срок, «🙂» — инициатор, «📎» — файл, «💬» — сообщение.

Сотрудника приёмник может узнать по любому полю recipient: по логину из профиля, по почте или по идентификатору MACRO.

#Группы уведомлений

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

notification.groupСтрока в настройках оповещений
commonОсновные
docs_agreement_requiredДокументы: Необходимо выполнить процесс
docs_approve_cancel_notifyДокументы: Отмена завершения процесса/Возврат на редактирование
docs_add_delete_approversДокументы: Добавление или удаление участников в документе
docs_new_messagesДокументы: Новые комментарии к договору
finances_income_incompleteФинансы: Не поступил платеж по графику
finances_transaction_paidФинансы: Ваша финансовая операция оплачена
finances_transaction_acceptedФинансы: Ваша финансовая операция акцептована к оплате
finances_need_approve_acceptФинансы: Необходимо согласовать/акцептовать операцию
finances_new_messagesФинансы: Новые комментарии к финансовой операции
estate_transfer_out_requestПередача объектов: Новый запрос на передачу объекта клиенту
contacts_new_messageКонтакты: Новое входящее сообщение от контакта
calls_incoming_callЗвонки: Входящий звонок
tasks_auto_messageЗадачи: Автоматические сообщения
documents_approve_taskЗадачи: Согласование документа
im_new_messageЧат: Новое сообщение

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

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

Подпись считается от времени из заголовка X-Macro-Timestamp и «сырого» тела запроса — ровно тех байтов, которые пришли:

X-Macro-Signature = "sha256=" + hex(hmac_sha256(секрет, X-Macro-Timestamp + "." + тело))

Не разбирайте и не собирайте JSON заново перед проверкой — получатся другие байты и другая подпись. Рекомендуем также отклонять запросы, у которых X-Macro-Timestamp отличается от текущего времени больше чем на 5 минут.

Python:

import hashlib
import hmac
import time


def is_valid(raw_body: bytes, timestamp: str, signature: str, secret: str) -> bool:
    if abs(time.time() - int(timestamp)) > 300:
        return False
    expected = 'sha256=' + hmac.new(secret.encode(), timestamp.encode() + b'.' + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)

PHP:

$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_MACRO_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_MACRO_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);

if (!hash_equals($expected, $signature) || abs(time() - (int) $timestamp) > 300) {
    http_response_code(401);
    exit;
}

Node.js (тело нужно получить буфером, до разбора JSON):

const crypto = require('crypto');

function isValid(rawBody, timestamp, signature, secret) {
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
    return false;
  }
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(timestamp + '.').update(rawBody).digest('hex');
  return expected.length === signature.length
    && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

#Ответ приёмника и повторы

Ответ приёмникаЧто делает MACRO
2xxУведомление доставлено
4xx, кроме 429Не повторяет. В разделе — «Доставка прекращена» с кодом и началом ответа
3xxНе идёт по перенаправлению и не повторяет
429, 5xx, нет ответа за 15 секунд, ошибка соединенияПовторяет по расписанию

Повторы идут с нарастающими паузами: 30 секунд, 1, 2, 5, 15 и 30 минут, 1, 2, 4, 6 и 8 часов — всего 12 попыток примерно за 22 часа. Если приёмник ответил 429 или 503 с заголовком Retry-After, следующая попытка будет не раньше указанного времени (не дольше часа).

Тело ответа MACRO не разбирает, важен только код. Начало тела ответа с ошибкой показывается администратору в разделе — поэтому в ответе с ошибкой полезно коротко написать причину.

#Повторы и порядок

  • Доставка гарантируется по принципу «не менее одного раза»: одно и то же уведомление может прийти повторно, например если ответ приёмника не дошёл до MACRO. У повторов одинаковый X-Macro-Idempotency-Key — храните обработанные ключи и отбрасывайте дубли.
  • Порядок доставки не гарантирован: при повторах более позднее уведомление может прийти раньше. Ориентируйтесь на notification.createdAt.

#Если уведомления не приходят

  1. Нажмите Проверить у канала. Если запрос не отправлен — проверьте, что канал включён. Если приёмник ответил ошибкой — передайте код и тело ответа разработчику приёмника.
  2. Посмотрите колонку «Последняя доставка»: код и начало ответа приёмника подскажут причину.
  3. Проверьте, что сотрудник включил нужную группу уведомлений в колонке канала в профиле → Оповещения.
  4. Если адрес не сохраняется — проверьте требования к адресу в разделе «Требования к приёмнику».

Если не получается разобраться, обратитесь в службу сопровождения и приложите название канала, время уведомления и, если есть, запись запроса на стороне приёмника.