Webhooks
Webhooks er, hvordan din backend får besked om ting, der sker asynkront — sessioner der slutter, optagelser der bliver færdigbehandlet, audit-kæder der forankres hos TSA'en. Registrér en URL, verificér signaturen på hver POST, dispatch efter event-type.
Event-typer
| Hændelse | Hvornår |
|---|---|
session.created | Ny session via SPA eller offentligt API |
session.completed | Session afsluttet (manuelt eller via API) |
participant.joined | Feltbruger (eller observatør) deltog i en session |
participant.left | Deltager afbrudt |
evidence.added | Nyt snapshot / annotering / whiteboard / klip / dokument registreret |
recording.ready | Efterbehandlede optagelsesartefakter tilgængelige |
audit.anchored | Kædehoved forankret hos en af de konfigurerede TSA'er |
signature.completed | En underskrevet PDF (SES/AES/QES) er klar til download |
webhook.test | Udløst af "Test fire"-knappen i SPA-admin, med en lille syntetisk payload |
Envelope-form
{
"id": "evt_01HGB9...",
"type": "session.completed",
"created_at": "2026-05-23T11:42:15Z",
"org_id": 42,
"data": {
/* event-specific payload — full resource shape */
}
} id er stabilt på tværs af genforsøg — brug det som din idempotensnøgle på modtagersiden.
Signatur-header
Hver POST bærer en NB-Signature-header i Stripe-stil-format:
NB-Signature: t=1716461235,v1=5257a8...3e2c1f Værdien v1 er HMAC-SHA256(secret, "{timestamp}.{body}") i hex. Værdien t er et Unix-tidsstempel på signeringstidspunktet. Et 5-minutters skew-vindue afviser replays af ældre payloads.
Verifikation i kode
Node
import { NexBasira, InvalidSignatureError } from "@nexbasira/node";
const nb = new NexBasira({ apiKey: "...", apiSecret: "..." });
// Express handler — important: use express.raw() so the body is the
// untouched bytes the signature was computed over.
app.post("/nb-webhook", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.header("NB-Signature")!;
const secret = process.env.NB_WEBHOOK_SECRET!;
let event;
try {
event = nb.webhooks.constructEvent(req.body, sig, secret);
} catch (err) {
if (err instanceof InvalidSignatureError) {
return res.status(401).send("bad signature");
}
throw err;
}
// event is now type-narrowed by event.type
return handleEvent(event, res);
}); Python
from nexbasira import NexBasira, InvalidSignatureError
nb = NexBasira(api_key="...", api_secret="...")
# Flask handler — get the raw body, not request.get_json()
@app.post("/nb-webhook")
def webhook():
sig = request.headers["NB-Signature"]
secret = os.environ["NB_WEBHOOK_SECRET"]
try:
event = nb.webhooks.construct_event(request.data, sig, secret)
except InvalidSignatureError:
return ("bad signature", 401)
return handle_event(event) Genforsøgsadfærd
En levering betragtes som vellykket, når dit endpoint returnerer et 2xx inden for 30 s. Alt andet udløser eksponentiel backoff:
30s → 5m → 1h → 6h → 24h → DROPPED Efter 50 på hinanden følgende fejl på tværs af alle events deaktiveres endpointet automatisk. Org-administratoren kan genaktivere fra SPA-admin, når modtageren er tilbage.
Idempotens på din side
Webhook-leveringer kan gentages. Behandl event.id som dedupliceringsnøglen:
-- Postgres example
INSERT INTO webhook_deliveries (event_id, processed_at)
VALUES ($1, NOW())
ON CONFLICT (event_id) DO NOTHING
RETURNING event_id;
-- If RETURNING is empty, this is a duplicate — skip the side-effect. Signeringshemmeligheder
Hvert registreret webhook-endpoint har sin egen whsec_*-signeringshemmelighed. Klarteksten vises præcis én gang, når du registrerer endpointet (eller roterer det); derefter gemmer vi en Fernet-krypteret kopi og viser kun de første 6 tegn til identifikation.
Rotér fra SPA → Admin → Webhooks → Rotate secret. Eksisterende modtagere vil afvise signerede events, indtil de er opdateret med den nye hemmelighed — planlæg rotationen med et deploy-vindue.
Testkald
Hvert registreret endpoint har en "Test fire"-knap i SPA-admin, der sender en webhook.test-envelope, så du kan verificere din modtager, før du går live. Test-envelopen har samme form som en rigtig event, men med en syntetisk payload markeret "test": true i data.
Leveringslog
SPA → Admin → Webhooks viser de seneste 100 leveringer pr. endpoint med HTTP-status, forsøg, seneste response-body (afkortet) og tidsstempler. Filtrér efter status / endpoint for at fejlfinde modtagerproblemer.