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 για την αποσφαλμάτωση προβλημάτων δέκτη.