Gå til innholdet

Webhooks

Webhooks lar systemene dine motta sanntids HTTP POST-varsler når køhendelser skjer — en kølapp blir med i køen, ropes opp, fullføres, og så videre.

  1. Åpne admin.jonot.io/settings/integrations.
  2. Klikk Legg til endepunkt.
  3. Skriv inn en offentlig HTTPS-URL serveren din lytter på.
  4. Velg hvilke hendelser du vil abonnere på.
  5. Klikk Lagre.

Lagre signeringshemmeligheten din — den vises bare én gang. For å bekrefte at endepunktet ditt er nåbart, bruk knappen Send testforespørsel på redigeringssiden for endepunktet.

HendelsesnavnNår den utløses
ticket.joinedEn kunde stiller seg i en kø
ticket.calledEn ansatt roper opp en kølapp til skranken
ticket.completedEn kølapp markeres som fullført
ticket.cancelledEn kunde eller ansatt avbryter en kølapp, eller en administrator sletter stedet eller køen som inneholder den
ticket.skippedEn kølapp hoppes over (en utsettelse som kan ropes opp igjen)
ticket.no_showEn oppropt eller hoppet-over kølapp bekreftes som en uteblivelse
queue.status_changedStatusen til en kø endres (ACTIVE, PAUSED, eller CLOSED)

Når en administrator sletter et sted eller en kø, sender Jonot ticket.cancelled for hver kølapp som fortsatt ventet eller var oppropt, opptil 50 kølapper per sletting. Kølapper utover denne grensen får ingen hendelse. Sletting av en organisasjon sender ingen webhooks, fordi endepunktene slettes sammen med den.

Hver levering er en HTTP POST med:

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

Standardkroppen er en JSON-konvolutt. Formen på payload-feltet varierer etter hendelse:

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 signerer hver levering med HMAC-SHA256 over strengen:

<deliveryId>.<timestamp>.<body>

Slik verifiserer du i Node.js (≥18):

import { createHmac, timingSafeEqual } from "node:crypto";
/**
* Returns true when the signature header is valid and the timestamp is
* within 5 minutes of now. Throws for malformed input.
*/
function verifySignature(secret, deliveryId, timestamp, body, header) {
// Replay-attack guard: reject deliveries older than 5 minutes.
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 prevents timing-oracle attacks.
// Buffers must be the same length — if lengths differ the signature is
// invalid, but we still compare a dummy value to keep constant time.
const expectedBuf = Buffer.from(expected);
const headerBuf = Buffer.from(header);
if (expectedBuf.length !== headerBuf.length) return false;
return timingSafeEqual(expectedBuf, headerBuf);
}

Du kan erstatte standard JSON-kroppen med en egendefinert mal. Maler bruker en forenklet Mustache-syntaks:

  • {{ path.to.value }} — erstattes og escapes for innholdstypen: JSON-streng-escapet for application/json, prosentkodet for application/x-www-form-urlencoded, rått for text/plain
  • {{{ path.to.value }}} — erstattes rått (ingen escaping)

Eksempelmal for application/json (abonnert på ticket.joined):

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

Feltet for nyttelastmalen er en fullstendig kodeeditor med:

  • Syntaksmarkering og parentesmatching for JSON-maler.
  • Variabelpalett — en alltid synlig rad med innsettingsknapper, én per tilgjengelig variabelbane for de valgte hendelsene dine. Klikk på en knapp for å sette inn et {{ path }}-tegn ved markøren.
  • Live-validering — mens du skriver, sjekker redigeringsverktøyet både JSON-strukturen (når innholdstypen er application/json og ingen rå {{{ }}}-tagger er til stede) og variabelbanene. Diagnostikk vises som innebygde markører i redigeringsverktøyet og som et sammendragsbanner under det:
    • Feil — en bane som er ukjent i alle de valgte hendelsene dine.
    • Advarsel — en bane som bare finnes for noen av de valgte hendelsene dine (den vil være tom for leveringer av de andre hendelsene).

Validering kjører også ved lagring på serveren — tilbakemeldingen i redigeringsverktøyet gjenspeiler serverreglene nøyaktig.

Cloudflare Queues venter stadig lenger før hvert nye forsøk. En levering mislykkes når endepunktet returnerer en status utenfor 2xx-området eller tilkoblingen feiler. Hvis det første forsøket og alle 3 nye forsøk mislykkes, flyttes leveringen til dødbrevkøen. Da øker også endepunktets teller for påfølgende feil.

Så snart et endepunkt samler opp 20 påfølgende feil, deaktiveres det automatisk. Aktiver det på nytt fra endepunktets redigeringsside; telleren nullstilles.

Hvis leveransene for én hendelse ville tatt deg over grensen, registreres alle leveransene for den hendelsen som Grense nådd, og ingen av dem sendes. Jonot prøver dem ikke på nytt, og de teller ikke med i de 20 påfølgende feilene som automatisk deaktiverer et endepunkt. Fanen Leveranser registrerer forkastede leveranser opp til en grense per minutt, så en langvarig topp etterlater et begrenset antall oppføringer i stedet for én per forkastet leveranse.

Fanen Leveranser på hvert endepunkt viser leveringsforsøkene fra de siste 30 dagene: hendelsestype, HTTP-status, antall forsøk, og tidsstempel. Bruk knappen Last inn mer for å bla gjennom eldre oppføringer.

GrenseVerdi
Endepunkter per organisasjon5
Egendefinerte hoder per endepunkt10
Lengde på hodeverdi1 024 bytes
Størrelse på nyttelastmal16 KB
Leveringstidsavbrudd10 s
Oppbevaringstid for leveringshistorikk30 dager
Maks leveranser per organisasjon600 / 60 s
Maks registrerte forkastelser per organisasjon100 / 60 s
  1. Åpne redigeringssiden for endepunktet.
  2. Klikk Bytt signeringshemmelighet.
  3. Bekreft rotasjonen i dialogen.
  4. Kopier den nye hemmeligheten umiddelbart — den vises bare én gang og kan ikke gjenopprettes. Hvis du lukker dialogen uten å lagre den, må du rotere på nytt for å få en ny klartekstverdi.
  5. Oppdater serveren din til å verifisere signaturer med den nye hemmeligheten.

Det finnes ingen overgangsperiode. Den gamle hemmeligheten slutter å virke straks du bekrefter rotasjonen. Distribuer den nye hemmeligheten til mottakeren med én gang.

Grensesnittet viser Aktiv hemmelighet: ····XXXX (de siste fire tegnene) ved siden av Bytt-knappen, slik at du kan bekrefte hvilken hemmelighet som gjelder for øyeblikket — nyttig for å bekrefte at mottakeren din og serveren er synkronisert etter en rotasjon.

Når du bør rotere:

  • Mistenkt kompromittering: hemmeligheten dukket opp i en loggfil, ble delt med en ansatt som sluttet, eller ble fanget i en skjermopptak.
  • Rutinehygiene: regelmessig rotasjon begrenser skadeomfanget av en uoppdaget eksponering.
  • Etter enhver endring i hvilke tjenester som kan lese hemmeligheten (rotasjon av nøkkelforvaltning).

Slik oppdaterer du mottakeren:

  1. Roter i admin-grensesnittet og kopier den nye hemmeligheten.
  2. Oppdater hemmeligheten i mottakerens hemmelighetslager (miljøvariabel, hemmelighetsforvalter osv.).
  3. Distribuer den oppdaterte mottakeren.
  4. Bekreft at neste levering lykkes i fanen Leveranser.

Hvis du mistet den nye hemmeligheten før du lagret den:

Roter på nytt. Hver rotasjon genererer en ny tilfeldig hemmelighet. Den forrige klarteksten kan ikke gjenopprettes — bare en AEAD-kryptert form lagres på serversiden.