Webhooks
Modtag dine sessioners hændelser i din backend: hver levering er signeret med HMAC-SHA256, forsøges igen med eksponentielt stigende ventetid og har et unikt id, så din modtager kan være idempotent.
Hvornår du skal bruge webhooks
Til at reagere på det, der sker i rummet, uden at spørge hele tiden: platformen kalder dig, når en session starter eller slutter, når et spørgsmål lukkes, eller når dets resultater gøres endelige. Levering sker mindst én gang – den kan gentages, den fejler aldrig i stilhed – og derfor skal din modtager være idempotent.
Katalog over hændelser
Leveres af API'et på /public/v1/limits – denne side gemmer ingen kopi.
- presentation.import.completed
- presentation.import.failed
- question.activated
- question.closed
- question.results.finalized
- report.ready
- session.ended
- session.paused
- session.resumed
- session.started
Headere på hver levering
X-Votinova-EventHændelsestypen, præcis som den står i kataloget.X-Votinova-Delivery-IdUnik pr. levering – din nøgle til at fjerne dubletter.X-Votinova-TimestampSekunder siden epoch; en del af det, der signeres, så en gentaget levering ikke kan få en ny dato.X-Votinova-SignatureHMAC-SHA256 i hex, uden præfiks.
Indholdet er kompakt JSON med hændelsen og alle involverede id'er – dette er, byte for byte, den signerede eksempellevering:
{"event":"session.ended","session_id":"68b2e3d4c5f607182930a5bc"}Sådan verificerer du signaturen
Hver levering signeres med HMAC-SHA256 over tidsstemplet, et punktum og indholdet, med endpointets hemmelighed som nøgle. Sammenlign resultatet med X-Votinova-Signature-headeren.
- Signer det RÅ indhold. Hvis du læser det og skriver det ud igen, ændres mellemrummene, og signaturen passer ikke længere.
- Sammenlign i konstant tid, ikke med ==.
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)
= 10a86171bd92f5fcf8c28b873978e0214302cc2291c54cc016d18347f3ee7c38Gentagne forsøg
Webhook-leveringer: op til 8 forsøg med stigende ventetider på 21, 45, 95, 171, 369, 732, 1480 sekunder. Når de er brugt op, sættes leveringen til side (dead letter) og kan sendes igen manuelt.
Idempotens
Brug X-Votinova-Delivery-Id som din nøgle til at fjerne dubletter: en levering kan komme frem mere end én gang, og din handling må kun ske én gang.
X-Votinova-Delivery-Id
Bedste praksis
- Svar 200, så snart leveringen er i sikkerhed, og behandl den i din egen kø – en langsom modtager hober gentagne forsøg op.
- Verificer ALTID signaturen, før du læser indholdet: uden den kan enhver, der kender din URL, finde på hændelser.
- Fjern dubletter ud fra X-Votinova-Delivery-Id: mindst én gang betyder, at den samme levering kan kalde to gange.
- Efter 10 fejl i træk sætter endpointet sig selv på pause; slå det til igen fra panelet eller via API'et, når din modtager er tilbage.