Webhooki

Dogodke svojih sej prejemajte v svojem zaledju: vsaka dostava je podpisana s HMAC-SHA256, se ponavlja z eksponentnim zamikom in nosi enolični id, da je vaš prejemnik lahko idempotenten.

Kdaj uporabiti webhooke

Da se odzovete na dogajanje v sobi brez poizvedovanja: platforma vas pokliče, ko se seja začne ali konča, ko se vprašanje zapre ali ko so njegovi rezultati dokončni. Dostava je vsaj enkrat – lahko se ponovi, nikoli pa ne odpove tiho –, zato mora biti vaš prejemnik idempotenten.

Katalog dogodkov

Streže ga API na /public/v1/limits – ta stran nima svoje kopije.

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

Glave v vsaki dostavi

  • X-Votinova-EventVrsta dogodka, natanko tako, kot je zapisana v katalogu.
  • X-Votinova-Delivery-IdEnolična za vsako dostavo – vaš ključ razdvajanja.
  • X-Votinova-TimestampSekunde od epohe; del podpisanega, zato ponovljene dostave ni mogoče prestaviti v drug čas.
  • X-Votinova-SignatureHMAC-SHA256 v šestnajstiškem zapisu, brez predpone.

Telo je strnjen JSON z dogodkom in vsemi vpletenimi identifikatorji – to je, bajt za bajtom, podpisani vzorčni primer dostave:

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

Preverjanje podpisa

Vsaka dostava je podpisana s HMAC-SHA256 čez časovni žig, piko in telo, s ključem skrivnosti končne točke. Rezultat primerjajte z glavo X-Votinova-Signature.

  • Podpišite SUROVO telo. Če ga razčlenite in znova serializirate, se presledki spremenijo in podpis se neha ujemati.
  • Primerjajte v stalnem času, ne z operatorjem ==.
Preverjeno na resnični dostavi
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

Ponovni poskusi

Dostave webhook: največ 8 poskusov, z naraščajočimi čakanji 21, 45, 95, 171, 369, 732, 1480 s. Ko so izčrpani, gre dostava med dokončno neuspele in jo je mogoče ročno dostaviti znova.

Idempotentnost

Za ključ razdvajanja uporabite X-Votinova-Delivery-Id: dostava lahko pride večkrat, vaš učinek pa se sme uveljaviti samo enkrat.

X-Votinova-Delivery-Id

Dobre prakse

  • Odgovorite 200 takoj, ko je dostava na varnem, obdelavo pa opravite v svoji vrsti – počasen prejemnik kopiči ponovne poskuse.
  • Podpis VEDNO preverite pred razčlenjevanjem: brez tega si lahko vsak, ki pozna vaš naslov, izmisli dogodke.
  • Razdvajajte po X-Votinova-Delivery-Id: „vsaj enkrat“ pomeni, da isti dogodek lahko pokliče dvakrat.
  • Po 10 zaporednih neuspehih se končna točka sama zaustavi; ko je vaš prejemnik spet na nogah, jo znova omogočite na plošči ali prek API-ja.