Webhooks

Отримуйте події своїх сесій у власному бекенді: кожна доставка підписана HMAC-SHA256, повторюється з експоненційним відкладанням і має унікальний ідентифікатор, щоб Ваш приймач був ідемпотентним.

Коли варто використовувати webhooks

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

Каталог подій

Віддається через API за адресою /public/v1/limits — ця сторінка не тримає копії.

  • presentation.import.completed
  • presentation.import.failed
  • question.activated
  • question.closed
  • question.results.finalized
  • report.ready
  • session.ended
  • session.paused
  • session.resumed
  • session.started

Заголовки в кожній доставці

  • X-Votinova-EventТип події — точно так, як він записаний у каталозі.
  • X-Votinova-Delivery-IdУнікальний для кожної доставки — Ваш ключ дедуплікації.
  • X-Votinova-TimestampСекунди від епохи; частина підписаних даних, тож повторно надіслану доставку не можна перепозначити іншою датою.
  • X-Votinova-SignatureHMAC-SHA256 у шістнадцятковому вигляді, без префікса.

Тіло — це компактний JSON із подією та всіма задіяними ідентифікаторами; ось, байт у байт, підписаний приклад доставки:

{"event":"session.ended","session_id":"68b2e3d4c5f607182930a5bc"}

Перевірка підпису

Кожна доставка підписується HMAC-SHA256 за часовою міткою, крапкою й тілом запиту, із ключем-секретом кінцевої точки. Порівняйте результат із заголовком X-Votinova-Signature.

  • Підписуйте НЕОБРОБЛЕНЕ тіло. Розбір і повторна серіалізація змінюють пробіли, і підпис перестає збігатися.
  • Порівнюйте за сталий час, а не через ==.
Перевірено на справжній доставці
const crypto = require("node:crypto");

function verify(headers, rawBody, secret) {
  const timestamp = headers["x-votinova-timestamp"];
  const signature = headers["x-votinova-signature"];
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
secret     whsec_3f8a1c92d4e5b6a7
timestamp  1785321600
body       {"event":"session.ended","session_id":"68b2e3d4c5f607182930a5bc"}

HMAC-SHA256(secret, timestamp + "." + body)
= 10a86171bd92f5fcf8c28b873978e0214302cc2291c54cc016d18347f3ee7c38

Повтори

Доставки webhook: щонайбільше 8 спроб, зі зростаючими паузами 21, 45, 95, 171, 369, 732, 1480 секунд. Коли спроби вичерпано, доставка потрапляє до черги невідправлених, і її можна надіслати повторно вручну.

Ідемпотентність

Використовуйте X-Votinova-Delivery-Id як ключ дедуплікації: доставка може прийти більш ніж один раз, а Ваш ефект має застосуватися лише раз.

X-Votinova-Delivery-Id

Найкращі практики

  • Відповідайте 200, щойно доставка в безпеці, і обробляйте її у власній черзі — повільний приймач накопичує повтори.
  • ЗАВЖДИ перевіряйте підпис перед розбором: без цього будь-хто, хто знає Вашу URL-адресу, може вигадувати події.
  • Дедуплікуйте за X-Votinova-Delivery-Id: доставка щонайменше один раз означає, що та сама доставка може прийти двічі.
  • Після 10 невдач поспіль кінцева точка призупиняється сама; увімкніть її знову з панелі або через API, коли Ваш приймач відновиться.