Μετάβαση στο περιεχόμενο

Webhooks

Τα Webhooks επιτρέπουν στα συστήματα σας να λαμβάνουν ειδοποιήσεις HTTP POST σε πραγματικό χρόνο όταν συμβαίνουν συμβάντα ουράς — ένα εισιτήριο μπαίνει, καλείται, ολοκληρώνεται, και ούτω καθεξής.

  1. Ανοίξτε το admin.jonot.io/settings/integrations.
  2. Κάντε κλικ στο Προσθήκη τελικού σημείου.
  3. Εισαγάγετε μια δημόσια διεύθυνση URL HTTPS στην οποία ακούει ο διακομιστής σας.
  4. Επιλέξτε σε ποια συμβάντα θα εγγραφείτε.
  5. Κάντε κλικ στο Αποθήκευση τελικού σημείου.

Αποθηκεύστε το μυστικό υπογραφής σας — εμφανίζεται μία φορά. Για να επιβεβαιώσετε ότι το τελικό σημείο σας είναι προσβάσιμο, χρησιμοποιήστε το κουμπί Αποστολή δοκιμαστικού αιτήματος στη σελίδα επεξεργασίας τελικού σημείου.

Όνομα συμβάντοςΠότε ενεργοποιείται
ticket.joinedΈνας πελάτης μπαίνει σε μια ουρά
ticket.calledΈνα μέλος προσωπικού καλεί ένα εισιτήριο στον σταθμό εξυπηρέτησης
ticket.completedΈνα εισιτήριο σημειώνεται ως ολοκληρωμένο
ticket.cancelledΈνας πελάτης ή μέλος προσωπικού ακυρώνει ένα εισιτήριο
ticket.skippedΈνα εισιτήριο παραλείπεται (μια ανακλητή αναβολή)
ticket.no_showΈνα κληθέν ή παραλειφθέν εισιτήριο επιβεβαιώνεται ως μη εμφάνιση
queue.status_changedΗ κατάσταση μιας ουράς αλλάζει (ACTIVE, PAUSED, ή CLOSED)

Κάθε παράδοση είναι ένα HTTP POST με:

Content-Type: application/json
X-Jonot-Event: ticket.called
X-Jonot-Delivery-Id: <uuid>
X-Jonot-Timestamp: 2024-06-01T12:00:00.000Z
X-Jonot-Signature: v1,<base64-hmac-sha256>
X-Jonot-Payload-Version: v1

Το προεπιλεγμένο σώμα είναι ένας φάκελος JSON. Το σχήμα του πεδίου payload διαφέρει ανά συμβάν:

ticket.joined

{
"deliveryId": "<uuid>",
"event": "ticket.joined",
"timestamp": "2024-06-01T12:00:00.000Z",
"org": { "id": "org_…", "name": "My Org" },
"payload": {
"ticket": { "id": "tkt_…", "queueId": "q_…" },
"queue": { "id": "q_…", "name": "Main Queue" },
"location": { "id": "loc_…", "name": "Downtown" }
}
}

ticket.called / ticket.completed / ticket.skipped / ticket.no_show

{
"deliveryId": "<uuid>",
"event": "ticket.called",
"timestamp": "2024-06-01T12:00:00.000Z",
"org": { "id": "org_…", "name": "My Org" },
"payload": {
"ticket": {
"id": "tkt_…",
"number": 42,
"status": "CALLED",
"queueId": "q_…",
"createdAt": "2024-06-01T11:58:00.000Z",
"updatedAt": "2024-06-01T12:00:00.000Z"
}
}
}

ticket.cancelled

{
"deliveryId": "<uuid>",
"event": "ticket.cancelled",
"timestamp": "2024-06-01T12:00:00.000Z",
"org": { "id": "org_…", "name": "My Org" },
"payload": {
"ticketId": "tkt_…",
"queueId": "q_…"
}
}

queue.status_changed

{
"deliveryId": "<uuid>",
"event": "queue.status_changed",
"timestamp": "2024-06-01T12:00:00.000Z",
"org": { "id": "org_…", "name": "My Org" },
"payload": {
"queueId": "q_…",
"status": "PAUSED"
}
}

Το Jonot υπογράφει κάθε παράδοση με HMAC-SHA256 πάνω στη συμβολοσειρά:

<deliveryId>.<timestamp>.<body>

Για επαλήθευση σε Node.js (≥18):

import { createHmac, timingSafeEqual } from "node:crypto";
/**
* Επιστρέφει true όταν η κεφαλίδα υπογραφής είναι έγκυρη και η χρονοσφραγίδα
* είναι εντός 5 λεπτών από τώρα. Πετάει σφάλμα για κακοσχηματισμένη είσοδο.
*/
function verifySignature(secret, deliveryId, timestamp, body, header) {
// Προστασία από επίθεση επανάληψης: απόρριψη παραδόσεων παλαιότερων των 5 λεπτών.
const ageMs = Date.now() - new Date(timestamp).getTime();
if (Math.abs(ageMs) > 5 * 60 * 1000) return false;
const expected =
"v1," +
createHmac("sha256", secret)
.update(`${deliveryId}.${timestamp}.${body}`)
.digest("base64");
// Το timingSafeEqual αποτρέπει επιθέσεις timing-oracle.
// Τα Buffer πρέπει να έχουν το ίδιο μήκος — αν τα μήκη διαφέρουν η υπογραφή
// είναι άκυρη, αλλά συγκρίνουμε ακόμα μια εικονική τιμή για να διατηρηθεί ο σταθερός χρόνος.
const expectedBuf = Buffer.from(expected);
const headerBuf = Buffer.from(header);
if (expectedBuf.length !== headerBuf.length) return false;
return timingSafeEqual(expectedBuf, headerBuf);
}

Μπορείτε να αντικαταστήσετε το προεπιλεγμένο σώμα JSON με ένα προσαρμοσμένο πρότυπο. Τα πρότυπα χρησιμοποιούν σύνταξη Mustache-lite:

  • {{ path.to.value }} — αντικαθίσταται και διαφεύγει σύμφωνα με τον τύπο περιεχομένου: JSON-string escaped για application/json, percent-encoded για application/x-www-form-urlencoded, raw για text/plain
  • {{{ path.to.value }}} — αντικαθίσταται raw (χωρίς διαφυγή)

Παράδειγμα προτύπου για application/json (εγγεγραμμένο στο ticket.joined):

{
"type": "{{ event }}",
"ticketId": "{{ payload.ticket.id }}",
"queueName": "{{ payload.queue.name }}"
}

Το πεδίο προτύπου payload είναι ένας πλήρης επεξεργαστής κώδικα με:

  • Επισήμανση σύνταξης και αντιστοίχιση αγκυλών για πρότυπα JSON.
  • Παλέτα μεταβλητών — μια πάντα ορατή σειρά κουμπιών εισαγωγής, ένα ανά διαθέσιμη διαδρομή μεταβλητής για τα επιλεγμένα συμβάντα σας. Κάντε κλικ σε ένα κουμπί για να εισαγάγετε ένα token {{ path }} στη θέση του δρομέα.
  • Ζωντανή επικύρωση — ενόσω πληκτρολογείτε, ο επεξεργαστής ελέγχει τόσο τη δομή JSON (όταν ο τύπος περιεχομένου είναι application/json και δεν υπάρχουν ετικέτες raw {{{ }}}) όσο και τις διαδρομές μεταβλητών. Τα διαγνωστικά εμφανίζονται ως ενσωματωμένοι δείκτες στον επεξεργαστή και ως συνοπτικό banner από κάτω:
    • Σφάλμα — μια διαδρομή που είναι άγνωστη σε όλα τα επιλεγμένα συμβάντα σας.
    • Προειδοποίηση — μια διαδρομή που υπάρχει μόνο για μερικά από τα επιλεγμένα συμβάντα σας (θα είναι κενή για παραδόσεις των άλλων συμβάντων).

Η επικύρωση εκτελείται επίσης τη στιγμή της αποθήκευσης στον διακομιστή — η ανατροφοδότηση του επεξεργαστή αντικατοπτρίζει ακριβώς τους κανόνες του διακομιστή.

Αποτυχημένες παραδόσεις (μη-2xx ή σφάλμα σύνδεσης) επαναλαμβάνονται έως 3 φορές με εκθετική οπισθοχώρηση από τα Cloudflare Queues. Μετά από 3 αποτυχίες η παράδοση καταλήγει στην ουρά dead-letter και ο μετρητής διαδοχικών αποτυχιών του τελικού σημείου αυξάνεται.

Μόλις ένα τελικό σημείο συσσωρεύσει 20 διαδοχικές αποτυχίες απενεργοποιείται αυτόματα. Επανενεργοποιήστε το από τη σελίδα επεξεργασίας τελικού σημείου· ο μετρητής μηδενίζεται.

Η καρτέλα Παραδόσεις σε κάθε τελικό σημείο εμφανίζει τις τελευταίες 30 ημέρες προσπαθειών παράδοσης: τύπο συμβάντος, κατάσταση HTTP, αριθμό προσπαθειών, και χρονοσφραγίδα. Χρησιμοποιήστε το κουμπί Φόρτωση περισσότερων για να περιηγηθείτε σε παλαιότερες εγγραφές.

ΌριοΤιμή
Τελικά σημεία ανά οργανισμό5
Προσαρμοσμένες κεφαλίδες ανά τελικό σημείο10
Μήκος τιμής κεφαλίδας1.024 bytes
Μέγεθος προτύπου payload16 KB
Χρονικό όριο παράδοσης10 δ.
Διατήρηση ιστορικού παραδόσεων30 ημέρες
Μέγιστος ρυθμός παράδοσης ανά οργανισμό120 / 60 δ.
  1. Ανοίξτε τη σελίδα επεξεργασίας τελικού σημείου.
  2. Κάντε κλικ στο Εναλλαγή μυστικού υπογραφής.
  3. Επιβεβαιώστε την εναλλαγή στο παράθυρο διαλόγου.
  4. Αντιγράψτε το νέο μυστικό αμέσως — εμφανίζεται μία φορά και δεν μπορεί να ανακτηθεί. Αν απορρίψετε το παράθυρο διαλόγου χωρίς να το αποθηκεύσετε, πρέπει να εναλλάξετε ξανά για να λάβετε ένα νέο απλό κείμενο.
  5. Ενημερώστε τον διακομιστή σας να επαληθεύει υπογραφές με το νέο μυστικό.

Δεν υπάρχει παράθυρο επικάλυψης. Το παλιό μυστικό σταματά να επαληθεύει μόλις επιβεβαιώσετε την εναλλαγή. Σχεδιάστε να αναπτύξετε το νέο μυστικό στον δέκτη σας αμέσως μετά την εναλλαγή.

Η διεπαφή εμφανίζει Ενεργό μυστικό: ····XXXX (οι τελευταίοι τέσσερις χαρακτήρες) δίπλα στο κουμπί Εναλλαγή ώστε να μπορείτε να επιβεβαιώσετε ποιο μυστικό είναι σε ισχύ αυτή τη στιγμή — χρήσιμο για να επιβεβαιώσετε ότι ο δέκτης σας και ο διακομιστής είναι συγχρονισμένοι μετά από μια εναλλαγή.

Πότε να εναλλάξετε:

  • Ύποπτη παραβίαση: το μυστικό εμφανίστηκε σε αρχείο καταγραφής, μοιράστηκε με έναν αποχωρούντα υπάλληλο, ή καταγράφηκε σε εγγραφή οθόνης.
  • Τακτική υγιεινή: η περιοδική εναλλαγή περιορίζει την ακτίνα έκθεσης μιας μη εντοπισμένης διαρροής.
  • Μετά από κάθε αλλαγή στις υπηρεσίες που μπορούν να διαβάσουν το μυστικό (εναλλαγή διαχείρισης κλειδιών).

Πώς να ενημερώσετε τον δέκτη:

  1. Εναλλάξτε στη διεπαφή admin και αντιγράψτε το νέο μυστικό.
  2. Ενημερώστε το μυστικό στον αποθηκευτικό χώρο μυστικών του δέκτη σας (μεταβλητή περιβάλλοντος, διαχειριστή μυστικών, κ.λπ.).
  3. Αναπτύξτε τον ενημερωμένο δέκτη.
  4. Επιβεβαιώστε ότι η επόμενη παράδοση πετυχαίνει στην καρτέλα Παραδόσεις.

Αν χάσατε το νέο μυστικό πριν το αποθηκεύσετε:

Εναλλάξτε ξανά. Κάθε εναλλαγή δημιουργεί ένα νέο τυχαίο μυστικό. Το προηγούμενο απλό κείμενο δεν είναι ανακτήσιμο — μόνο μια μορφή κρυπτογραφημένη με AEAD αποθηκεύεται στον διακομιστή.