Перейти до вмісту
На сайт

Як надійно отримувати вебхуки Twilio

Тут ідеться про інформаційні вебхуки Twilio, як-от status callbacks повідомлень. Twilio надсилає їх на джерело Railhook, а воно перевіряє підпис, зберігає кожен таким, яким той надійшов, і пересилає у ваш сервіс із повторними спробами.

Чому вебхукам Twilio потрібен буфер

Section titled “Чому вебхукам Twilio потрібен буфер”

Типово Twilio чекає 5 секунд на з’єднання й 15 секунд на відповідь і повторює вебхук лише один раз, і тільки тоді, коли не вдалося встановити саме з’єднання. Після 5xx від вашого застосунку чи повільної відповіді повторної спроби не буде, якщо не додати до URL параметри connection overrides. (Twilio: Webhooks connection overrides)

Status callback, що надійшов під час перезапуску застосунку, зазвичай губиться, і ваші дані про доставку розходяться з даними Twilio. Коли попереду стоїть Railhook:

  • Railhook відповідає Twilio, щойно збереже callback.
  • Ваш сервіс отримує до 5 спроб на кожне пересилання з інтервалами від 1 хвилини до 1 години, а те, що так і не вдалося доставити, потрапляє в «Недоставлені пересилання».
  • На callback з I-Twilio-Idempotency-Token, який Railhook уже зберіг, він відповідає збереженою копією і вдруге його не пересилає.

Знадобляться проєкт Railhook і API-ключ. Ті самі кроки є в панелі керування, у розділі «Вхідні».

Terminal window
export RAILHOOK_URL=https://railhook.io # or your own instance
export RAILHOOK_API_KEY=...
export PROJECT_ID=...
  1. Створіть джерело з вашим Auth Token із Twilio Console. Саме ним Twilio підписує свої запити:

    Terminal window
    curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources" \
    -H "X-API-Key: $RAILHOOK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"name":"Twilio","providerType":"TWILIO","verificationMode":"PROVIDER","hmacSecret":"'"$TWILIO_AUTH_TOKEN"'"}'

    Збережіть id і ingressUrl із відповіді.

  2. Додайте призначення, URL вашого сервісу:

    Terminal window
    curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-sources/$SOURCE_ID/destinations" \
    -H "X-API-Key: $RAILHOOK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"url":"https://api.example.com/webhooks/twilio","authType":"BEARER","authConfig":"{\"token\":\"...\"}","enabled":true}'
  3. Передайте URL у Twilio. Указуйте ingressUrl точно в тому вигляді, в якому його показує джерело, скрізь, де Twilio приймає URL для status callback, наприклад у параметрі StatusCallback під час надсилання повідомлення. Метод залиште POST: інших ingress не приймає.

  4. Надішліть повідомлення. Його status callbacks з’являться в розділі «Вхідні» → «Отримані» з одним пересиланням на кожне призначення.

Як перевіряється підпис

Section titled “Як перевіряється підпис”

X-Twilio-Signature є HMAC-SHA1 у Base64, обчисленим з Auth Token. Для запиту у форматі form-encoded підписано URL, а за ним усі параметри, відсортовані за назвою; для інших запитів лише URL, а параметр рядка запиту bodySHA256 має відповідати тілу. На запит, що не збігається, Railhook відповідає 401 і не зберігає його.

Тіло точно таке, яким його надіслав Twilio, байт у байт, з оригінальним form-encoded Content-Type, тож ваш сервіс розбирає його так само, як callback напряму від Twilio. X-Twilio-Signature не пересилається (з вашим URL він однаково не пройшов би перевірку): натомість ваш сервіс автентифікує Railhook за обліковими даними призначення. Див. Призначення.

  1. Встановіть CLI й увійдіть, як описано в CLI, а потім відкрийте тунель до порту вашого застосунку:

    Terminal window
    railhook listen 3000
  2. Додайте джерелу друге призначення: публічну адресу, яку вивела команда, з вашим маршрутом у кінці, наприклад https://<host>/tunnel/<slug>/webhooks/twilio. Запит потрапить на http://localhost:3000/webhooks/twilio.

  3. Надішліть тестове повідомлення, указавши ingress-адресу як status callback, і кожен callback надійде у ваш локальний застосунок. Коли закриєте тунель, вимкніть це призначення.

Відтворення після збою

Section titled “Відтворення після збою”

Кожен відтворений callback піде на кожне призначення джерела як нове пересилання:

Terminal window
curl -X POST "$RAILHOOK_URL/api/v1/projects/$PROJECT_ID/incoming-events/bulk-replay" \
-H "X-API-Key: $RAILHOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sourceId":"'"$SOURCE_ID"'","from":"2026-09-18T10:00:00Z","to":"2026-09-18T14:00:00Z","verified":true}'

Відтворити можна все, що ще зберігається: 7 днів у Railhook Cloud і скільки налаштуєте на власному сервері. Status callback описує стан, тож переконайтеся, що обробник може застосувати той самий callback двічі без шкоди. Див. Відтворення.