ΖΩΝΤΑΝΑ · ΑΛΥΣΙΔΑ ΕΛΕΓΧΟΥ · ΕΕ
ΣΥΣΤΗΜΑ · 99,99% ΔΙΑΘΕΣΙΜΟΤΗΤΑ
v 1.0 ↗ ΦΤΙΑΓΜΕΝΟ ΣΤΗΝ ΕΕ

Webhooks

Τα webhooks είναι ο τρόπος με τον οποίο το backend σας μαθαίνει για πράγματα που συμβαίνουν ασύγχρονα — συνεδρίες που λήγουν, εγγραφές που ολοκληρώνουν το post-processing, αλυσίδες ελέγχου που αγκυρώνονται στην TSA. Καταχωρίστε ένα URL, επαληθεύστε την υπογραφή σε κάθε POST, δρομολογήστε ανά τύπο συμβάντος.

Τύποι συμβάντων

ΣυμβάνΠότε
session.createdΝέα συνεδρία μέσω SPA ή δημόσιου API
session.completedΗ συνεδρία έληξε (χειροκίνητα ή μέσω API)
participant.joinedΧρήστης πεδίου (ή παρατηρητής) εντάχθηκε σε μια συνεδρία
participant.leftΟ συμμετέχων αποσυνδέθηκε
evidence.addedΚαταγράφηκε νέο στιγμιότυπο / σχολιασμός / πίνακας ζωγραφικής / κλιπ / έγγραφο
recording.readyΔιαθέσιμα τα επεξεργασμένα αντικείμενα εγγραφής
audit.anchoredΗ κεφαλή της αλυσίδας αγκυρώθηκε σε μία από τις διαμορφωμένες TSA
signature.completedΈνα υπογεγραμμένο PDF (SES/AES/QES) είναι έτοιμο για λήψη
webhook.testΠυροδοτείται από το κουμπί "Test fire" στο admin του SPA, με ένα μικροσκοπικό συνθετικό payload

Μορφή φακέλου

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

Το id είναι σταθερό μεταξύ επαναλήψεων — χρησιμοποιήστε το ως idempotency key στην πλευρά του δέκτη.

Κεφαλίδα υπογραφής

Κάθε POST φέρει μια κεφαλίδα NB-Signature σε μορφή τύπου Stripe:

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

Η τιμή v1 είναι HMAC-SHA256(secret, "{timestamp}.{body}") σε δεκαεξαδικό. Η τιμή t είναι μια χρονοσφραγίδα Unix τη στιγμή της υπογραφής. Ένα παράθυρο απόκλισης 5 λεπτών απορρίπτει επαναλήψεις παλαιότερων payloads.

Επαλήθευση στον κώδικα

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)

Συμπεριφορά επανάληψης

Μια παράδοση θεωρείται επιτυχής όταν το endpoint σας επιστρέφει 2xx εντός 30s. Οτιδήποτε άλλο πυροδοτεί εκθετική υποχώρηση:

30s 5m 1h 6h 24h DROPPED

Μετά από 50 διαδοχικές αποτυχίες σε όλα τα συμβάντα, το endpoint απενεργοποιείται αυτόματα. Ο admin της org μπορεί να το ενεργοποιήσει ξανά από το admin του SPA μόλις ο δέκτης επανέλθει.

Idempotency στη δική σας πλευρά

Οι παραδόσεις webhook μπορούν να επαναληφθούν. Αντιμετωπίστε το event.id ως κλειδί αποδιπλασιασμού:

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

Μυστικά υπογραφής

Κάθε καταχωρημένο webhook endpoint έχει το δικό του μυστικό υπογραφής whsec_*. Το plaintext εμφανίζεται ακριβώς μία φορά όταν καταχωρίζετε το endpoint (ή το εναλλάσσετε)· έπειτα αποθηκεύουμε ένα αντίγραφο κρυπτογραφημένο με Fernet και εμφανίζουμε μόνο τους πρώτους 6 χαρακτήρες για αναγνώριση.

Εναλλάξτε από SPA → Admin → Webhooks → Rotate secret. Οι υπάρχοντες δέκτες θα απορρίπτουν υπογεγραμμένα συμβάντα μέχρι να ενημερωθούν με το νέο μυστικό — προγραμματίστε την εναλλαγή με ένα παράθυρο deploy.

Test fire

Κάθε καταχωρημένο endpoint έχει ένα κουμπί "Test fire" στο admin του SPA που αποστέλλει έναν φάκελο webhook.test, ώστε να επαληθεύσετε τον δέκτη σας πριν βγείτε live. Ο δοκιμαστικός φάκελος έχει την ίδια μορφή με ένα πραγματικό συμβάν αλλά με συνθετικό payload που φέρει την ετικέτα "test": true στο data.

Αρχείο παραδόσεων

SPA → Admin → Webhooks εμφανίζει τις τελευταίες 100 παραδόσεις ανά endpoint με HTTP status, προσπάθειες, τελευταίο σώμα απόκρισης (περικομμένο) και χρονοσφραγίδες. Φιλτράρετε ανά status / endpoint για την αποσφαλμάτωση προβλημάτων δέκτη.