Webhooki
Zdarzenia z Państwa sesji trafiają prosto do Państwa backendu: każde dostarczenie jest podpisane HMAC-SHA256, ponawiane z wykładniczo rosnącym odstępem i ma unikalny identyfikator, dzięki czemu odbiornik może być idempotentny.
Kiedy używać webhooków
Aby reagować na to, co dzieje się w pokoju, bez odpytywania: platforma sama wywołuje Państwa endpoint, gdy sesja się zaczyna lub kończy, gdy pytanie zostaje zamknięte albo gdy jego wyniki są finalizowane. Dostarczenie działa w trybie at-least-once – może się powtórzyć, nigdy nie zawodzi po cichu – i właśnie dlatego odbiornik musi być idempotentny.
Katalog zdarzeń
Udostępniany przez API pod /public/v1/limits – ta strona nie przechowuje kopii.
- presentation.import.completed
- presentation.import.failed
- question.activated
- question.closed
- question.results.finalized
- report.ready
- session.ended
- session.paused
- session.resumed
- session.started
Nagłówki w każdym dostarczeniu
X-Votinova-EventTyp zdarzenia, dokładnie tak jak w katalogu.X-Votinova-Delivery-IdUnikalny dla każdego dostarczenia – Państwa klucz deduplikacji.X-Votinova-TimestampSekundy epoki; objęte podpisem, więc powtórzonego dostarczenia nie da się przedatować.X-Votinova-SignatureHMAC-SHA256 szesnastkowo, bez prefiksu.
Treść to zwarty JSON ze zdarzeniem i wszystkimi powiązanymi identyfikatorami – to jest, bajt w bajt, podpisane przykładowe dostarczenie:
{"event":"session.ended","session_id":"68b2e3d4c5f607182930a5bc"}Weryfikacja podpisu
Każde dostarczenie jest podpisane HMAC-SHA256 z sygnatury czasowej, kropki i treści, a kluczem jest sekret endpointu. Wynik należy porównać z nagłówkiem X-Votinova-Signature.
- Podpisywać należy SUROWĄ treść. Sparsowanie i ponowna serializacja zmieniają białe znaki i podpis przestaje się zgadzać.
- Porównanie powinno przebiegać w stałym czasie, nie przez ==.
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)
= 10a86171bd92f5fcf8c28b873978e0214302cc2291c54cc016d18347f3ee7c38Ponowienia
Dostarczenia webhooków: liczba prób maksymalnie 8, z rosnącymi odstępami 21, 45, 95, 171, 369, 732, 1480 s. Po ich wyczerpaniu dostarczenie trafia do martwej kolejki i można je ponowić ręcznie.
Idempotentność
Jako klucza deduplikacji należy używać X-Votinova-Delivery-Id: dostarczenie może przyjść więcej niż raz, a efekt po Państwa stronie musi zajść tylko raz.
X-Votinova-Delivery-Id
Dobre praktyki
- Odpowiedź 200 należy wysyłać, gdy tylko dostarczenie jest bezpiecznie przyjęte, a przetwarzanie prowadzić we własnej kolejce – wolny odbiornik piętrzy ponowienia.
- ZAWSZE należy zweryfikować podpis przed parsowaniem: bez tego każdy, kto zna Państwa adres URL, może zmyślać zdarzenia.
- Deduplikacja po X-Votinova-Delivery-Id: at-least-once oznacza, że to samo dostarczenie może wywołać endpoint dwukrotnie.
- Po 10 kolejnych niepowodzeniach endpoint sam się wstrzymuje; po przywróceniu odbiornika należy włączyć go ponownie w panelu albo przez API.