LIVE · AUDIT-KETJU · EU
JÄRJESTELMÄ · 99,99 % KÄYTETTÄVYYS
v 1.0 ↗ TEHTY EU:SSA

Webhookit

Webhookit ovat tapa, jolla taustajärjestelmäsi saa tiedon asioista, jotka tapahtuvat asynkronisesti — istunnot päättyvät, tallenteiden jälkikäsittely valmistuu, auditointiketjut ankkuroituvat TSA:han. Rekisteröi URL, varmenna allekirjoitus jokaisessa POST-pyynnössä, ohjaa tapahtumatyypin mukaan.

Tapahtumatyypit

TapahtumaMilloin
session.createdUusi istunto SPA:n tai julkisen API:n kautta
session.completedIstunto päättyi (manuaalisesti tai API:n kautta)
participant.joinedKenttäkäyttäjä (tai tarkkailija) liittyi istuntoon
participant.leftOsallistuja katkaisi yhteyden
evidence.addedUusi tilannekuva / merkintä / valkotaulu / leike / dokumentti tallennettu
recording.readyJälkikäsitellyt tallenneartefaktit saatavilla
audit.anchoredKetjun pää ankkuroitu johonkin määritetyistä TSA:ista
signature.completedAllekirjoitettu PDF (SES/AES/QES) valmis ladattavaksi
webhook.testLaukaistu SPA-ylläpidon "Testilaukaus"-painikkeella, pienellä synteettisellä hyötykuormalla

Kuoren muoto

{
  "id": "evt_01HGB9...",
  "type": "session.completed",
  "created_at": "2026-05-23T11:42:15Z",
  "org_id": 42,
  "data": {
    /* event-specific payload — full resource shape */
  }
}

id on vakaa uudelleenyritysten yli — käytä sitä idempotenssiavaimena vastaanottajan puolella.

Allekirjoitusotsake

Jokainen POST kantaa NB-Signature-otsakkeen Stripe-tyylisessä muodossa:

NB-Signature: t=1716461235,v1=5257a8...3e2c1f

Arvo v1 on HMAC-SHA256(secret, "{timestamp}.{body}") heksadesimaaleina. Arvo t on Unix-aikaleima allekirjoitushetkellä. 5 minuutin poikkeamaikkuna hylkää vanhempien hyötykuormien toistot.

Varmentaminen koodissa

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)

Uudelleenyrityskäyttäytyminen

Toimitus katsotaan onnistuneeksi, kun päätepisteesi palauttaa 2xx 30 sekunnin sisällä. Mikä tahansa muu laukaisee eksponentiaalisen perääntymisen:

30s 5m 1h 6h 24h DROPPED

50 peräkkäisen epäonnistumisen jälkeen kaikkien tapahtumien osalta päätepiste poistuu automaattisesti käytöstä. Organisaation ylläpitäjä voi ottaa sen uudelleen käyttöön SPA-ylläpidosta, kun vastaanotin on taas pystyssä.

Idempotenssi sinun puolellasi

Webhook-toimitukset voivat toistua. Käsittele event.id deduplikointiavaimena:

-- 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.

Allekirjoitussalaisuudet

Jokaisella rekisteröidyllä webhook-päätepisteellä on oma whsec_*-allekirjoitussalaisuutensa. Selkokielinen näytetään täsmälleen kerran, kun rekisteröit päätepisteen (tai kierrätät sen); sen jälkeen tallennamme Fernet-salatun kopion ja näytämme vain ensimmäiset 6 merkkiä tunnistamista varten.

Kierrätä kohdasta SPA → Admin → Webhookit → Kierrätä salaisuus. Olemassa olevat vastaanottimet hylkäävät allekirjoitetut tapahtumat, kunnes ne on päivitetty uudella salaisuudella — ajoita kierrätys julkaisuikkunaan.

Testilaukaus

Jokaisella rekisteröidyllä päätepisteellä on SPA-ylläpidossa "Testilaukaus"-painike, joka lähettää webhook.test-kuoren, jotta voit varmentaa vastaanottimesi ennen tuotantoon menoa. Testikuorella on sama muoto kuin oikealla tapahtumalla, mutta synteettisellä hyötykuormalla, joka on merkitty "test": true kentässä data.

Toimitusloki

SPA → Admin → Webhookit näyttää viimeiset 100 toimitusta päätepistettä kohti HTTP-statuksella, yrityksillä, viimeisimmän vastauksen rungolla (typistettynä) ja aikaleimoilla. Suodata statuksen / päätepisteen mukaan vastaanotinongelmien debuggaamiseksi.