Вебхуки
Вебхук сам присылает событие на адрес вашей системы, когда лиду ушло первое сообщение или лид ответил. Опрашивать ленту не нужно: достаточно принять запрос, проверить подпись и ответить 2xx.
#Вебхуки или лента
Вебхуки и лента событий передают одни и те же факты: lead.first_message_sent и lead.replied. Разница в том, кто начинает обмен.
| Вебхуки | Лента GET /v1/events | |
|---|---|---|
| Как приходят события | Meliora отправляет POST на ваш адрес | Ваша система опрашивает API |
| Что нужно с вашей стороны | Публичный адрес https | Ключ API с правом events:read |
| Где настраивается | В кабинете | В коде интеграции |
| Если получатель недоступен | Повторы около 3 суток, затем событие нужно повторить вручную | События ждут в ленте 30 дней |
| Текст первого сообщения | Не передается | include_text=true |
Проверка record_id | Нет, поле приходит как загружено | record_id_status |
Выбирайте вебхуки, если нужна быстрая реакция без постоянного опроса и у вас есть сервер или сервис автоматизации с публичным адресом. Выбирайте ленту, если входящие запросы к вашей системе закрыты или важно забрать все события после долгого простоя.
Их можно использовать вместе: вебхук как быстрый сигнал, лента как страховка. У одного факта одинаковый id в вебхуке и в ленте, поэтому дедупликация по id не даст применить событие дважды.
#Как это работает
- В кабинете случается факт: лиду ушло первое сообщение или пришел засчитанный ответ.
- Meliora собирает событие и отправляет
POSTс JSON на каждый подходящий адрес. - Ваша система проверяет подпись, сохраняет событие и отвечает кодом 2xx за 10 секунд.
- Если ответа 2xx нет, Meliora повторяет отправку по расписанию с тем же
id.
Адрес получает события, собранные после того, как его сохранили. Прошлые события на новый адрес не отправляются: историю заберите из ленты или обходом лидов.
#Настройка в кабинете
Вебхуками управляет владелец или администратор кабинета с доступом ко всем пространствам и кампаниям. Остальные участники видят раздел только для просмотра. Ключ API для вебхуков не нужен.
- Откройте Настройки › Интеграции, блок Вебхук событий, и нажмите «Добавить адрес».
- В поле «Адрес получателя» вставьте адрес вашей системы. «Описание (видно только в кабинете)» помогает отличать адреса.
- В блоке «События» отметьте «Отправлено первое сообщение» (
lead.first_message_sent), «Получен ответ» (lead.replied) или оба. - В блоке «Кампании» оставьте «Все кампании», чтобы получать события и новых кампаний, или выберите «Выбранные». Если в кабинете несколько пространств, так же выберите пространства.
- Если нужен текст ответа лида, включите «Передавать текст ответа».
- Если получатель проверяет ключ в заголовке запроса, добавьте его в «Дополнительные заголовки».
- Нажмите «Добавить» и скопируйте ключ подписи из блока «Адрес добавлен. Ключ подписи».
- Нажмите «Проверить» и откройте «Журнал»: там появится тестовое событие и ответ вашего адреса.
Ключ подписи можно посмотреть снова в любой момент кнопкой «Ключ подписи» на карточке адреса. В кабинете может быть до 10 адресов. В демонстрационном кабинете вебхуки недоступны.
#Требования к адресу
- Только
https://и порт 443. Адрес с другим портом не сохранится. - Имя сервера, а не IP-адрес.
- Без логина и пароля в адресе. Для доступа по ключу используйте «Дополнительные заголовки».
- Действующий сертификат TLS для этого имени от публичного центра сертификации. Самоподписанный сертификат не подойдет.
- Имя должно указывать только на публичные адреса в интернете. Если хотя бы один адрес ведет во внутреннюю сеть, отправка запрещена.
- У имени должна быть запись A (IPv4): доставка только по IPv6 сейчас не гарантируется.
- Переадресации не выполняются: ответ 3xx считается ошибкой. Укажите окончательный адрес.
- Параметры после
?сохраняются и передаются как есть. Длина адреса до 2048 знаков.
Запросы приходят с серверов Meliora. Их адреса не публикуются и могут меняться, поэтому не фильтруйте запросы по IP: проверяйте подпись.
Адрес может содержать секретный путь, поэтому после сохранения кабинет показывает только его начало и последние знаки. Чтобы сменить адрес, нажмите «Изменить» и вставьте новый. Пустое поле оставляет прежний адрес.
#Дополнительные заголовки
Если ваш сервис принимает запросы только с ключом в заголовке, добавьте до 5 заголовков. Имя начинается с x-, например x-api-key, или равно Authorization. Значение до 1024 знаков. После сохранения значения не показываются, их можно только заменить кнопкой «Заменить заголовки». Заголовки подписи и служебные заголовки запроса переопределить нельзя.
#Запрос
Каждое событие приходит отдельным запросом POST с телом JSON в UTF-8. Тело компактное, без отступов, символы кириллицы не экранируются. Размер тела до 256 КиБ.
POST /meliora/webhook HTTP/1.1
Host: crm.example.com
Content-Type: application/json
User-Agent: Meliora-Webhooks/1
webhook-id: evt_aab3db461d0542ff88c3124491aa2cc4
webhook-timestamp: 1793092509
webhook-signature: v1,kt8BoIJwYXnW8z5nUWwQitssRUMxKam8Dv+TgAhDV0s=
{"id":"evt_aab3db461d0542ff88c3124491aa2cc4","type":"lead.replied",...}| Заголовок | Значение |
|---|---|
webhook-id | Идентификатор события evt_ и 32 шестнадцатеричных знака. Одинаковый во всех повторах, совпадает с полем id в теле. |
webhook-timestamp | Время отправки этой попытки, секунды Unix. У каждого повтора свое. |
webhook-signature | Подпись v1,<base64>. Во время смены ключа две подписи через пробел. |
Content-Type | application/json |
User-Agent | Meliora-Webhooks/1 |
Кроме них приходят ваши «Дополнительные заголовки», если они заданы. Имена заголовков в HTTP не зависят от регистра: читайте их без учета регистра.
#Тело
| Поле | Описание |
|---|---|
id | Идентификатор события, ключ дедупликации. Тот же, что у события в ленте. |
type | lead.first_message_sent, lead.replied или webhook.test у тестового события. |
api_version | Версия формата события, сейчас 2026-10-18. Подробнее в руководстве Версии API. |
timestamp | Когда произошел факт. Это не время отправки: повтор приходит с тем же timestamp. |
test | true только у тестового события. |
data | Данные события. |
Общие поля data описаны в справочнике событий: пространство, кампания, лид, аккаунт отправителя, время первого сообщения и ответ. Ниже примеры и отличия вебхука от ленты.
{
"id": "evt_61017785512246cdb0f3fafecba197a2",
"type": "lead.first_message_sent",
"api_version": "2026-10-18",
"timestamp": "2026-10-27T09:02:11.204518+00:00",
"test": false,
"data": {
"event_id": "evt_61017785512246cdb0f3fafecba197a2",
"organization_id": "594b5bf4-aef7-480d-86b4-393390132326",
"workspace": { "id": "3512de95-fcaa-4f57-b692-5caee3217b3e", "name": "Продажи" },
"campaign": { "id": "5cad4b4d-356f-4043-ba37-a42f51fc8a87", "name": "Осенняя кампания" },
"lead": {
"id": "083f7a84-6cb7-49e1-9b1e-3a6ee783f70e",
"username": "ivan_p",
"username_at": "@ivan_p",
"telegram_url": "https://t.me/ivan_p",
"username_variants": [
"ivan_p", "@ivan_p", "t.me/ivan_p", "https://t.me/ivan_p", "http://t.me/ivan_p",
"https://t.me/ivan_p/", "telegram.me/ivan_p", "https://telegram.me/ivan_p"
],
"telegram_user_id": 5012345678,
"status": "contacted",
"fields": { "record_id": "crm-10482", "first_name": "Иван", "company": "ООО Пример" }
},
"account": { "id": "aaa3f0d2-63a1-44df-b091-410ebc606e8e", "username": "anna_sales", "name": "Анна" },
"first_message_sent_at": "2026-10-27T09:02:11.204518+00:00"
}
}{
"id": "evt_aab3db461d0542ff88c3124491aa2cc4",
"type": "lead.replied",
"api_version": "2026-10-18",
"timestamp": "2026-10-27T09:15:02.481233+00:00",
"test": false,
"data": {
"event_id": "evt_aab3db461d0542ff88c3124491aa2cc4",
"organization_id": "594b5bf4-aef7-480d-86b4-393390132326",
"workspace": { "id": "3512de95-fcaa-4f57-b692-5caee3217b3e", "name": "Продажи" },
"campaign": { "id": "5cad4b4d-356f-4043-ba37-a42f51fc8a87", "name": "Осенняя кампания" },
"lead": {
"id": "083f7a84-6cb7-49e1-9b1e-3a6ee783f70e",
"username": "ivan_p",
"username_at": "@ivan_p",
"telegram_url": "https://t.me/ivan_p",
"username_variants": [
"ivan_p", "@ivan_p", "t.me/ivan_p", "https://t.me/ivan_p", "http://t.me/ivan_p",
"https://t.me/ivan_p/", "telegram.me/ivan_p", "https://telegram.me/ivan_p"
],
"telegram_user_id": 5012345678,
"status": "replied",
"fields": { "record_id": "crm-10482", "first_name": "Иван", "company": "ООО Пример" }
},
"account": { "id": "aaa3f0d2-63a1-44df-b091-410ebc606e8e", "username": "anna_sales", "name": "Анна" },
"first_message_sent_at": "2026-10-27T09:02:11.204518+00:00",
"reply": {
"id": "d3c448da-10fe-4493-ad22-55e1eb36478a",
"replied_at": "2026-10-27T09:15:02.481233+00:00",
"text": "Здравствуйте! Интересно, расскажите подробнее"
}
}
}Порядок ключей в JSON не гарантируется. Незнакомые поля пропускайте, а на событие незнакомого типа отвечайте 2xx, иначе оно будет повторяться. Подробнее в руководстве Версии API.
#Отличия от ленты
| Поле | Вебхук | Лента GET /v1/events |
|---|---|---|
object | Нет | "event" |
data.event_id | Равен id | Нет |
data.lead.username_at, telegram_url, telegram_user_id | Есть | Нет |
data.lead.username_variants | Восемь частых видов записи ника | Нет |
data.lead.fields | Все колонки, загруженные с лидом, кроме телефона. Снимок на момент события | Только перечисленные в руководстве Связь с CRM ключи, record_id из текущей карточки |
data.lead.record_id_status | Нет | valid, missing, conflict или unknown |
data.lead.status | Статус лида на момент сбора события | Одно из значений справочника, иначе unknown |
data.reply.text | Если включено «Передавать текст ответа» | С include_text=true |
| Текст первого сообщения | Не передается | data.first_message с include_text=true |
data.reply.automation_stopped | Нет | Всегда null |
| Запись времени | ISO 8601 UTC со смещением +00:00, до микросекунд | ISO 8601 UTC с Z и миллисекундами |
Что важно знать о данных вебхука:
data.lead.fieldsсодержит колонки файла, загруженного при импорте или при создании кампании. Имена латиницей в нижнем регистре, пробел заменяется на_: колонкаLead Sourceпридет какlead_source. Телефон и служебные поля не передаются.data.lead.fields.record_idприходит, если вы загрузили такую колонку. Проверкиrecord_id_statusв вебхуке нет: если значения нет или оно вызывает сомнение, сверьте лида запросомGET /v1/leads/{id}.data.lead.statusпоказывает статус в момент сбора события. Набор значений не зафиксирован: решения принимайте поtype, а не по этому полю.data.lead.usernameприходит в нижнем регистре, без@. Если ника нет,usernameи связанные поля равныnull.data.accountравенnull, если аккаунт отправителя не найден, например удален.data.first_message_sent_atу события ответа берется из карточки лида и может бытьnull.
Текст ответа. Без «Передавать текст ответа» поля data.reply.text нет. С ним text содержит текст ответа. Если текст прочитать не удалось, text равен null, а text_unavailable равен true.
Размер. Если тело больше 256 КиБ, сначала убирается текст ответа (text равен null, text_truncated равен true), затем поля лида (fields пустой, fields_truncated равен true). Если и так много, событие не отправляется, а в журнале появляется «Событие слишком большое».
#Проверка подписи
Адрес вебхука может узнать посторонний и прислать на него поддельное событие. Подпись доказывает, что запрос отправила Meliora и тело не меняли. Подпись соответствует стандарту Standard Webhooks, поэтому подойдут и готовые библиотеки этого стандарта.
Ключ подписи имеет вид whsec_ и 44 знака base64. Храните его как секрет, например в переменной окружения, и не публикуйте в коде.
Как проверить:
- Возьмите сырое тело запроса, байты до разбора JSON.
- Соберите строку для подписи: значение
webhook-id, точка, значениеwebhook-timestamp, точка, тело. - Ключ HMAC: часть ключа после
whsec_, раскодированная из base64. - Посчитайте HMAC-SHA256 от строки и закодируйте результат в base64.
- Заголовок
webhook-signatureсодержит одну или несколько подписей через пробел, каждая видаv1,<base64>. Событие подлинное, если ваш результат совпал хотя бы с одной подписьюv1. Сравнивайте за постоянное время, а не обычным==. - Проверьте
webhook-timestamp: стандарт рекомендует отклонять запросы, время которых отличается от вашего больше чем на 5 минут. Так перехваченный запрос нельзя прислать повторно позже. Часы сервера держите синхронизированными.
import crypto from 'node:crypto';
import express from 'express';
const TOLERANCE_SECONDS = 5 * 60;
// Текущий ключ; на время смены ключа можно перечислить два через запятую
const SECRETS = process.env.MELIORA_WEBHOOK_SECRETS.split(',');
export function verifyWebhook(rawBody, headers, secrets) {
const id = headers['webhook-id'];
const timestamp = headers['webhook-timestamp'];
const signatures = headers['webhook-signature'];
if (!id || !timestamp || !signatures) throw new Error('missing headers');
const sentAt = Number(timestamp);
if (!Number.isInteger(sentAt) || Math.abs(Date.now() / 1000 - sentAt) > TOLERANCE_SECONDS) {
throw new Error('timestamp outside tolerance');
}
const signed = Buffer.concat([Buffer.from(`${id}.${timestamp}.`), rawBody]);
const expected = secrets.map((secret) => {
const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');
return Buffer.from(crypto.createHmac('sha256', key).update(signed).digest('base64'));
});
for (const part of signatures.split(' ')) {
const [version, value = ''] = part.split(',');
if (version !== 'v1') continue;
const received = Buffer.from(value);
if (expected.some((e) => e.length === received.length && crypto.timingSafeEqual(e, received))) {
return JSON.parse(rawBody.toString('utf8'));
}
}
throw new Error('no matching signature');
}
const app = express();
app.post('/meliora/webhook', express.raw({ type: 'application/json', limit: '1mb' }), async (req, res) => {
let event;
try {
event = verifyWebhook(req.body, req.headers, SECRETS);
} catch {
return res.status(400).end();
}
await saveEvent(event); // запись с уникальным event.id; повтор просто пропускается
res.status(200).end(); // обработка в CRM идет после ответа, отдельной задачей
});import base64
import hashlib
import hmac
import json
import os
import time
from fastapi import FastAPI, Request, Response
TOLERANCE_SECONDS = 5 * 60
# Текущий ключ; на время смены ключа можно перечислить два через запятую
SECRETS = os.environ["MELIORA_WEBHOOK_SECRETS"].split(",")
class InvalidWebhook(Exception):
pass
def verify_webhook(raw_body: bytes, headers, secrets: list[str]) -> dict:
msg_id = headers.get("webhook-id")
timestamp = headers.get("webhook-timestamp")
signatures = headers.get("webhook-signature")
if not msg_id or not timestamp or not signatures:
raise InvalidWebhook("missing headers")
try:
sent_at = int(timestamp)
except ValueError:
raise InvalidWebhook("bad timestamp")
if abs(time.time() - sent_at) > TOLERANCE_SECONDS:
raise InvalidWebhook("timestamp outside tolerance")
signed = f"{msg_id}.{timestamp}.".encode() + raw_body
expected = []
for secret in secrets:
key = base64.b64decode(secret.removeprefix("whsec_"))
digest = hmac.new(key, signed, hashlib.sha256).digest()
expected.append(base64.b64encode(digest))
for part in signatures.split(" "):
version, _, value = part.partition(",")
if version != "v1":
continue
if any(hmac.compare_digest(value.encode(), e) for e in expected):
return json.loads(raw_body)
raise InvalidWebhook("no matching signature")
app = FastAPI()
@app.post("/meliora/webhook")
async def meliora_webhook(request: Request):
raw_body = await request.body()
try:
event = verify_webhook(raw_body, request.headers, SECRETS)
except InvalidWebhook:
return Response(status_code=400)
save_event(event) # запись с уникальным event["id"]; повтор просто пропускается
return Response(status_code=200) # обработка в CRM идет после ответаsaveEvent и save_event замените своими: например, вставкой в таблицу с уникальным ключом по id и отдельным обработчиком, который применяет события к CRM.
#Проверьте свою реализацию
Посчитайте подпись для этих данных. Проверку времени для этого примера отключите: метка в прошлом.
| Значение | |
|---|---|
| Ключ | whsec_AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8= |
webhook-id | evt_aab3db461d0542ff88c3124491aa2cc4 |
webhook-timestamp | 1793092509 |
| Тело, без перевода строки в конце | {"id":"evt_aab3db461d0542ff88c3124491aa2cc4","type":"lead.replied","test":false} |
| Ожидаемая подпись | v1,kt8BoIJwYXnW8z5nUWwQitssRUMxKam8Dv+TgAhDV0s= |
Тело в примере укорочено, для проверки алгоритма этого достаточно.
#Ответ на запрос
Ответьте кодом 2xx в течение 10 секунд, тогда событие считается доставленным. Тело ответа не нужно, Meliora его не сохраняет.
Все остальное считается неудачной попыткой:
- коды 3xx, 4xx и 5xx; переадресации не выполняются;
- нет ответа за 10 секунд;
- соединение и рукопожатие TLS не установились за 5 секунд;
- ошибка DNS, соединения или сертификата.
Общий срок одной попытки 30 секунд. Ответьте сразу после того, как сохранили событие, а запись в CRM и другую долгую работу выполняйте после ответа.
Особые ответы:
| Ответ | Что делает Meliora |
|---|---|
410 Gone | Больше не повторяет это событие и сразу выключает адрес. Отвечайте 410, только если адрес действительно больше не нужен. |
413 Payload Too Large | Больше не повторяет это событие. Адрес продолжает работать. |
429 или 503 с Retry-After | Пауза до следующей попытки равна большему из двух значений: паузе по расписанию и Retry-After в секундах. Значение больше часа считается за час. Дата в Retry-After не поддерживается, тогда действует расписание. |
#Повторы
Если попытка не удалась, Meliora повторяет ее с тем же webhook-id и тем же телом. Всего до 10 попыток примерно за 3 суток. Паузы между попытками случайно отличаются от расписания до 10% в обе стороны.
| Попытка | Пауза после предыдущей | Примерно от первой попытки |
|---|---|---|
| 1 | Сразу после сбора события | |
| 2 | 5 секунд | 5 секунд |
| 3 | 5 минут | 5 минут |
| 4 | 30 минут | 35 минут |
| 5 | 2 часа | 2 ч 35 мин |
| 6 | 5 часов | 7 ч 35 мин |
| 7 | 10 часов | 17 ч 35 мин |
| 8 | 14 часов | 31 ч 35 мин |
| 9 | 20 часов | 51 ч 35 мин |
| 10 | 24 часа | 75 ч 35 мин |
После 10 неудачных попыток событие получает статус «Не доставлено». Его можно отправить снова в «Журнале» адреса: кнопка «Повторить» у события или «Повторить неудачные за 7 дней». Повтор начинает новый цикл из 10 попыток с тем же id.
Событие, которое не удалось доставить за 7 суток с момента появления, например пока адрес на паузе, отменяется со статусом «Не доставлено за 7 суток». Такое событие тоже можно повторить из журнала. Журнал хранит доставки 30 дней.
#Автоматическое выключение адреса
Пока адрес не принимает события, карточка показывает «Есть ошибки». Адрес выключается автоматически:
- сразу после ответа
410; - если ошибки идут больше 3 суток подряд и за это время было не меньше 10 неудачных попыток подряд. Любой ответ 2xx сбрасывает счетчик.
Выключенный адрес получает статус «Выключен». Новые события для него не копятся и не будут доставлены. Исправьте получателя и нажмите «Включить». События за время отключения заберите из ленты или сверкой лидов.
#Гарантии доставки
- Не реже одного раза. Одно событие может прийти несколько раз, например если ваш ответ потерялся в сети. Дедуплицируйте по
id(он жеwebhook-id) и на повтор отвечайте 2xx. - Без гарантии порядка.
lead.repliedможет прийти раньшеlead.first_message_sent. Ориентируйтесь наtimestampи обновляйте статусы в CRM только вперед, как описано в руководстве Связь с CRM. - Без гарантии срока. События собираются раз в несколько секунд и отправляются сразу после сбора. Часть событий находится позже, при сверке, и приходит с опозданием и с более ранним
timestamp. - Сейчас на один адрес уходит не больше одного запроса одновременно. Не полагайтесь на это для порядка: повторы идут вперемешку с новыми событиями.
#Ротация ключа
Смените ключ, если он мог попасть к посторонним, или по своему графику.
- На карточке адреса нажмите «Ключ подписи», затем «Сменить ключ». Скопируйте новый ключ.
- Прежний ключ действует еще сутки. Все это время каждый запрос несет две подписи: новым и прежним ключом. Получатель с прежним ключом продолжает работать.
- В течение суток замените ключ в своей системе. Чтобы переход прошел без единой ошибки, на это время можно принимать оба ключа: код выше принимает список.
Сменить ключ снова можно сразу. Тогда самый старый ключ перестает действовать немедленно, прежним становится текущий, а сутки начинаются заново. Одновременно действуют не больше двух ключей.
#Тестовое событие
Кнопка «Проверить» на карточке активного адреса отправляет тестовое событие. Нажимать ее можно не чаще раза в 10 секунд. Результат появляется в «Журнале».
Тестовое событие подписывается и повторяется так же, как настоящее. Отличия:
typeравенwebhook.test,testравенtrue;dataустроен как уlead.replied, аdata.example_ofравен"lead.replied";- идентификаторы в
dataслучайные, никexample_lead; - в
data.lead.fieldsприходят имена колонок ваших недавних лидов со значением"пример"; настоящие значения не передаются; data.reply.textс примером текста приходит, только если включено «Передавать текст ответа».
По тестовому событию удобно настроить разбор полей, например в сервисе автоматизации. В рабочей обработке события с test: true пропускайте.
#Пауза, изменение и удаление
- Пауза. Кнопка «Пауза» останавливает отправку. Новые события для адреса копятся, а после «Продолжить» уходят. Событие, которое ждет дольше 7 суток, отменяется, его можно повторить из журнала.
- Изменение. Кнопка «Изменить» меняет адрес, события, охват, передачу текста и заголовки. Если вы сузили события или охват, ждущие отправки события, которые больше не подходят, отменяются со статусом «Адрес больше не принимает это событие».
- Удаление. «Изменить», затем «Удалить адрес» и подтверждение «Удалить». Ждущие события не уйдут, ключи подписи удаляются.
#Журнал
Карточка адреса показывает, сколько событий доставлено и сколько ошибок за сутки, сколько ждут отправки и чем закончилась последняя отправка. Кнопка «Журнал» открывает список доставок со статусами «Ждет отправки», «Отправляется», «Доставлено», «Не доставлено» и «Отменено», кодом ответа, номером попытки и временем следующей. Фильтр «Ошибки и ожидание» оставляет только проблемные доставки.
Код 2xx в журнале значит, что ваш адрес принял запрос. Что с событием было дальше, видно только в журнале вашей системы.
#Частые ошибки
| В журнале | Причина и что делать |
|---|---|
| «Адрес не подходит» | Адрес не https, другой порт или IP вместо имени. Исправьте адрес. |
| «Сервер не найден по имени» | Имя не разрешается в DNS. Проверьте записи домена. |
| «Адрес ведет во внутреннюю сеть» | Имя указывает на частный или служебный адрес. Нужен публичный адрес. |
| «Сервер не принял соединение» | Порт 443 закрыт или запросы режет межсетевой экран. Откройте порт: адреса серверов Meliora не публикуются, разрешить их списком нельзя. |
| «Ошибка защищенного соединения» | Сертификат истек, самоподписанный, выдан на другое имя или цепочка неполная. |
| «Сервер не ответил вовремя» | Ответ дольше 10 секунд. Отвечайте сразу после сохранения события. |
| «Сервер ответил ошибкой» с кодом 3xx | Переадресация, например с http на https или на адрес со слешем в конце. Укажите окончательный адрес. |
| «Сервер ответил ошибкой» с кодом 401 или 403 | Ваш сервис не принял ключ. Проверьте «Дополнительные заголовки». |
| «Сервер ответил ошибкой» с кодом 400 | Часто это ваша проверка подписи. Смотрите строку ниже. |
| «Событие слишком большое» | Тело больше 256 КиБ даже без текста и полей лида. Напишите в поддержку. |
Если подпись не сходится, проверьте по порядку: подпись считается от сырого тела, а не от заново собранного JSON; используется ключ этого адреса и вся часть после whsec_ раскодирована из base64; ключ не меняли кнопкой «Сменить ключ»; часы вашего сервера идут верно. Сверьте свой код с примером.
Если журнал пуст, хотя отправки и ответы идут: адрес создан позже этих фактов, не отмечен нужный тип события, кампания не входит в охват адреса или адрес на паузе или выключен.