Вебхук: формат и подпись
Вебхук — POST на ваш адрес на каждое новое событие источника, на который
он подписан. Как настроить — Получать события вебхуком.
{ "id": 512, "type": "event.received", "created_at": "2026-10-19T13:30:05Z", "source": {"id": 14, "name": "Заявки с лендинга"}, "data": {"id": 512, "source": {"id": 14, "name": "Заявки с лендинга"}, "channel": "webhook", "received_at": "2026-10-19T13:30:00Z", "payload": {"name": "Анна"}, "repeat_of": null, "history": false, "deleted_at": null}}id— номер доставки;type—event.received; проверка связи кнопкой «Тест» шлёт{"type": "ping"};data— то же событие, что отдаёт лентаGET /api/v1/events(API: правила).
Запросов не шлют: повторная отправка, пустое событие, удалённое событие, загрузка файла, первый запуск опроса и события, принятые до подписки.
Заголовки
Заголовок раздела «Заголовки»| Заголовок | Что в нём |
|---|---|
X-Goodwink-Event |
тип: event.received или ping |
X-Goodwink-Delivery |
номер доставки |
X-Goodwink-Signature |
t=<unix-время>,v1=<hex> |
Подпись
Заголовок раздела «Подпись»v1 = HMAC-SHA256(секрет, t + "." + тело как есть), в шестнадцатеричном
виде. Секрет — в карточке вебхука на вкладке «Интеграции», кнопка «Показать».
Проверяйте подпись по сырым байтам тела до разбора JSON и отбрасывайте
запросы, у которых t старше нескольких минут.
import hashlibimport hmac
def signed(body: bytes, header: str, secret: str) -> bool: parts = dict(p.split("=", 1) for p in header.split(",")) want = hmac.new(secret.encode(), f"{parts['t']}.".encode() + body, hashlib.sha256).hexdigest() return hmac.compare_digest(want, parts["v1"])Доставка
Заголовок раздела «Доставка»- Ответ
2xx— доставлено. Любой другой ответ или нет ответа — повтор с растущим интервалом: 30 секунд, минута, две… до суток. - Гарантия — «хотя бы раз»: доставка с тем же
idможет прийти повторно, приём должен это пережить. - Адрес — только публичный
http(s); он проверяется при сохранении и перед каждой отправкой, запрос идёт ровно на проверенный адрес. - Журнал попыток — в карточке вебхука.