Webhooks
OPORA принимает incoming webhook’и через единый endpoint
https://app.opora.example/webhook/<uuid> — uuid выдаётся для
каждой trigger-ноды при publish’е workflow’а. Зависит от типа
trigger-ноды, как именно OPORA валидирует запрос.
Варианты валидации
Section titled “Варианты валидации”| Trigger-нода | Схема валидации |
|---|---|
webhook.trigger (generic) | Опциональный HMAC по preset’у (см. ниже) |
telegram.webhook.trigger | X-Telegram-Bot-Api-Secret-Token header echo |
bitrix24.webhook.trigger | application_token body-field echo |
amocrm.webhook.trigger | query-param ?token=<...> match |
yookassa.webhook.trigger | query-param ?<token> match + IP-whitelist (on your side) |
tbank.webhook.trigger | Token-based SHA-256 over sorted fields + password |
zadarma.webhook.trigger | MD5-signature в query |
vk.webhook.trigger | body secret field echo + Callback API confirmation-handshake |
stripe.webhook.trigger | HMAC-SHA256 over raw body + Stripe-Signature header |
github.webhook.trigger | HMAC-SHA256 + X-Hub-Signature-256 |
shopify.webhook.trigger | HMAC-SHA256 + X-Shopify-Hmac-Sha256 |
aws.sns.webhook.trigger | Message signature verification (RSA + X.509 cert) |
В каждом случае OPORA отклоняет запросы с неверной подписью до того, как они дойдут до workflow’а — 401 Unauthorized уходит обратно провайдеру.
Generic webhook.trigger
Section titled “Generic webhook.trigger”Для провайдеров без dedicated-ноды (Tilda, custom webhooks, кастомные HTTP-клиенты). Настройки ноды:
validation:none/hmac/token- Если
hmac:algorithm:sha256/sha1secretRef: ссылка на secret с ключом подписиheaderName: как вендор называет signature header (X-Hub- Signature-256у GitHub,X-Hmac-Signatureу custom)
- Если
token:paramName:token(default)secretRef: ожидаемое значение
Raw body capture
Section titled “Raw body capture”HMAC-валидация требует байт-эксактно тех байтов, что прислал
вендор — после JSON.parse() + JSON.stringify() у вас уже не
те байты (другой whitespace, ordering ключей). OPORA запускается с
rawBody: true, Nest/Express сохраняют req.rawBody для HMAC-
check’а, parsing body для workflow’а идёт параллельно.
Это прозрачно — вам ничего конфигурировать не нужно.
Idempotency
Section titled “Idempotency”Повторный webhook от провайдера (provider не получил 200 OK и ретраит) приводит к одному run’у, не двум:
- Ключ дедупа зависит от trigger-ноды (см. Runs & Traces — Idempotency)
- Window кэша — 5 минут в Redis
- Повторный запрос получает 200 OK, но
X-Opora-Idempotent: trueheader в response’е, run не создаётся
IP-whitelisting (опционально)
Section titled “IP-whitelisting (опционально)”Некоторые провайдеры (ЮKassa, T-Kassa) публикуют список своих IP’ов, с которых шлют webhook’и. Для hardening’а вы можете:
- Настроить firewall / Caddy на VM’е пропускать
/webhook/*только с этих IP’ов - Или на уровне network-security-group VK Cloud’а (менее гибко, но проще)
OPORA в коде IP-whitelisting не делает — считаем это infrastructure-level concern’ом.
Rate limiting
Section titled “Rate limiting”Public endpoint /webhook/* защищён rate-limit’ом 60 запросов /
минуту / IP. При превышении — 429 Too Many Requests с Retry- After header’ом.
Этот лимит достаточен для legit-провайдеров (Telegram шлёт raz в 1-2 секунды на бота, CRM’ы реже). Атаки / runaway loops блокируются.
Если у вас редкий случай legit-traffic’а > 60/min (massive-rollout marketing-кампания через webhook-URL), пишите в поддержку — поднимем лимит для этого space’а.
Error responses
Section titled “Error responses”OPORA возвращает:
200 OK— webhook принят, run создан (или dedupe’нут)400 Bad Request— payload не JSON / не parseable401 Unauthorized— signature не сошлась404 Not Found— uuid webhook’а не существует (trigger-нода удалена или не publish’нута)429 Too Many Requests— rate-limit5xx— internal error OPORA, провайдер должен retry’ить. В Sentry уходит alert (если настроен).
Outbound webhook’и
Section titled “Outbound webhook’и”OPORA сама шлёт webhook’и наружу через ноду external.http с POST
- custom headers. Для HMAC-signing (вам надо подписать payload для
receiving-сервиса) используйте
auth.preset = "hmac"на ноде + secret с ключом.
Связанное
Section titled “Связанное”- Webhook Trigger в providers matrix — какие preset’ы есть
- Runs & Traces → Idempotency — как дедуп работает внутри
- Cookbook → inbound webhook to CRM — практический пример