Вебхуки
Когда задача заканчивается, на ваш адрес приходит POST по
Standard Webhooks. Адрес — поле callback_url запроса;
адрес по умолчанию для всех запросов можно задать в кабинете (раздел «Роутинг и вебхуки»)
или PATCH /v1/settings.
Адрес
https:// на публичный хост, без логина и пароля в адресе, до 2048 символов, порт —
стандартный (без порта или :443). Частные адреса, localhost и внутренние имена
(.local, .internal) не принимаются. Поле webhook.error задачи говорит, почему
последняя попытка не засчитана: receiver answered <код>, receiver did not respond,
адрес отвергнут или сбой на нашей стороне (доставка повторится).
Событие
Тело — {"type": "job.completed" | "job.failed", "timestamp", "data": <задача>} (схема
WebhookEvent), подпись — в заголовках:
| Заголовок | Значение |
|---|---|
webhook-id | id доставки — один у всех её повторов; по нему отбрасывайте дубли |
webhook-timestamp | unix-секунды отправки; старые доставки отбрасывайте |
webhook-signature | v1,<base64 HMAC-SHA256> от <webhook-id>.<webhook-timestamp>.<тело> |
Ответ и повторы
Первая попытка уходит сразу, как задача закончилась. Ответьте 2xx за 10 секунд — до
того, как начнёте обрабатывать. Иначе повтор через
30 секунд, 2 минуты, 10 минут и 1 час; после пятой неудачи доставка — failed (поле
webhook задачи).
Проверка подписи
Секрет — GET /v1/webhooks/secret (whsec_…), один на аккаунт;
POST /v1/webhooks/secret/rotate выпускает новый. Обе ручки — ключом управления с ролью
разработчика или выше; секрет есть и в кабинете. Проверяйте готовой библиотекой Standard
Webhooks по сырому телу запроса:
from standardwebhooks.webhooks import Webhook
payload = Webhook(secret).verify(raw_body, request.headers) # исключение — подпись не сошласьimport { Webhook } from "standardwebhooks";
const event = new Webhook(secret).verify(rawBody, headers); // бросает, если подпись не сошлась