Webhooky

Dostávejte události svých relací do vlastního backendu: každé doručení je podepsané HMAC-SHA256, opakuje se s exponenciálně rostoucí prodlevou a nese jedinečné id, aby Váš příjemce mohl být idempotentní.

Kdy použít webhooky

Abyste reagovali na dění v místnosti bez opakovaného dotazování: platforma Vám zavolá, když relace začne nebo skončí, když se otázka uzavře nebo když jsou její výsledky finální. Doručení je aspoň jednou – může se zopakovat, nikdy neselže potichu – a právě proto musí být Váš příjemce idempotentní.

Katalog událostí

Poskytuje ho API na /public/v1/limits – tato stránka si žádnou kopii nedrží.

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

Hlavičky u každého doručení

  • X-Votinova-EventTyp události, přesně tak, jak je uvedený v katalogu.
  • X-Votinova-Delivery-IdJedinečné pro každé doručení – Váš klíč pro odstranění duplicit.
  • X-Votinova-TimestampSekundy od epochy; je součástí podpisu, takže přehrané doručení nelze předatovat.
  • X-Votinova-SignatureHMAC-SHA256 v hexadecimálním tvaru, bez prefixu.

Tělo je kompaktní JSON s událostí a všemi souvisejícími id – tohle je bajt po bajtu podepsaná ukázka doručení:

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

Ověření podpisu

Každé doručení je podepsané HMAC-SHA256 přes časové razítko, tečku a tělo, s klíčem daného koncového bodu. Výsledek porovnejte s hlavičkou X-Votinova-Signature.

  • Podepisujte SUROVÉ tělo. Parsování a opětovné serializování změní bílé znaky a podpis přestane sedět.
  • Porovnávejte v konstantním čase, ne pomocí ==.
Ověřeno proti skutečnému doručení
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

Opakování

Doručení webhooků: počet pokusů 8, s rostoucími prodlevami 21, 45, 95, 171, 369, 732, 1480 s. Po jejich vyčerpání se doručení odloží do fronty nedoručených a lze ho poslat znovu ručně.

Idempotence

Použijte X-Votinova-Delivery-Id jako klíč pro odstranění duplicit: doručení může dorazit víckrát a Váš efekt se smí uplatnit jen jednou.

X-Votinova-Delivery-Id

Osvědčené postupy

  • Odpovězte 200, jakmile máte doručení v bezpečí, a zpracujte ho ve vlastní frontě – pomalý příjemce si nahromadí opakování.
  • VŽDY ověřte podpis, než začnete tělo parsovat: bez toho si kdokoli, kdo zná Vaši adresu, může události vymyslet.
  • Odstraňujte duplicity podle X-Votinova-Delivery-Id: doručení aspoň jednou znamená, že totéž doručení může přijít dvakrát.
  • Po 10 selháních za sebou se koncový bod sám pozastaví; jakmile je Váš příjemce zpátky, zapněte ho znovu z panelu nebo přes API.