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 веднага щом доставянето е на сигурно място, и обработвайте в собствената си опашка — бавен приемник трупа повторни опити.
  • ВИНАГИ проверявайте подписа, преди да разчетете тялото: без това всеки, който знае адреса Ви, може да измисля събития.
  • Премахвайте дубликати по X-Votinova-Delivery-Id: „поне веднъж“ значи, че едно и също доставяне може да дойде два пъти.
  • След 10 последователни неуспеха крайната точка се спира сама; включете я отново от панела или по API, щом приемникът Ви се върне.