Webhooky

Prijímajte udalosti svojich relácií do vlastného backendu: každé doručenie je podpísané cez HMAC-SHA256, opakuje sa s exponenciálne narastajúcim odstupom a nesie jedinečné id, takže Váš prijímač môže byť idempotentný.

Kedy použiť webhooky

Aby ste reagovali na dianie v miestnosti bez neustáleho dopytovania: platforma Vám zavolá, keď sa relácia začne alebo skončí, keď sa otázka uzavrie alebo keď sú jej výsledky uzatvorené. Doručenie prebieha v režime aspoň raz: môže sa zopakovať, nikdy však nezlyhá potichu. Práve preto musí byť Váš prijímač idempotentný.

Katalóg udalostí

Poskytuje ho API na adrese /public/v1/limits – táto stránka si žiadnu kópiu 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 v každom doručení

  • X-Votinova-EventTyp udalosti, presne tak, ako je uvedený v katalógu.
  • X-Votinova-Delivery-IdJedinečná pre každé doručenie – Váš kľúč na odstraňovanie duplikátov.
  • X-Votinova-TimestampSekundy od epochy; sú súčasťou podpisu, takže zopakované doručenie sa nedá predatovať.
  • X-Votinova-SignatureHMAC-SHA256 v hexadecimálnom tvare, bez predpony.

Telo je kompaktný JSON s udalosťou a všetkými zúčastnenými id – toto je bajt po bajte podpísané ukážkové doručenie:

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

Overenie podpisu

Každé doručenie je podpísané algoritmom HMAC-SHA256 nad časovou pečiatkou, bodkou a telom, s kľúčom daného koncového bodu. Výsledok porovnajte s hlavičkou X-Votinova-Signature.

  • Podpisujte SUROVÉ telo. Parsovaním a opätovnou serializáciou sa zmenia medzery a podpis prestane sedieť.
  • Porovnávajte v konštantnom čase, nie operátorom ==.
Overené oproti skutočnému doručeniu
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

Opakovania

Doručovanie webhookov: najviac 8 pokusov, s narastajúcimi odstupmi 21, 45, 95, 171, 369, 732, 1480 sekúnd. Po ich vyčerpaní sa doručenie označí ako nedoručiteľné a dá sa zopakovať ručne.

Idempotencia

Ako kľúč na odstraňovanie duplikátov použite X-Votinova-Delivery-Id: doručenie môže prísť aj viackrát a jeho účinok sa smie uplatniť len raz.

X-Votinova-Delivery-Id

Osvedčené postupy

  • Odpovedzte 200 hneď, ako máte doručenie v bezpečí, a spracujte ho vo vlastnom fronte – pomalý prijímač si nahromadí opakovania.
  • Podpis overte VŽDY pred parsovaním: bez toho môže udalosti vymyslieť ktokoľvek, kto pozná Vašu adresu.
  • Duplikáty odstraňujte podľa X-Votinova-Delivery-Id: režim aspoň raz znamená, že to isté doručenie môže prísť dvakrát.
  • Po 10 neúspešných doručeniach za sebou sa koncový bod sám pozastaví; keď je Váš prijímač späť, znova ho zapnite z panela alebo cez API.