De gebeurtenissen
Een webhook is een adres op je server waarnaar we een gebeurtenis sturen zodra die plaatsvindt. Er zijn zes gebeurtenissen:
form.response.created Eine neue Antwort auf eines deiner Formulare
form.response.updated Jemand hat seine Antwort über den Bearbeitungslink geändert
order.paid Eine Bestellung ist bezahlt
order.fulfilled Eine Bestellung ist versendet oder übergeben
order.canceled Eine bestätigte Bestellung wurde storniert
order.refunded Eine Bestellung wurde erstattetorder.refunded komt bij de eerste gedeeltelijke terugbetaling en bij de volledige terugbetaling. Een checkout die nooit is betaald en verloopt, is geen annulering — daarvoor wordt geen gebeurtenis verstuurd.
Een webhook instellen
Programma's kunnen webhooks ook zelf registreren: POST /v1/webhooks met een sleutel die webhooks:manage heeft — en daarnaast het leesrecht voor de gegevens die de webhook verstuurt (forms:read voor formuliergebeurtenissen, orders:read voor bestellingen).
- Open in het dashboard het onderdeel Ontwikkelaar.
- Vul onder “Webhooks” het adres van je ontvanger in — het begint met https.
- Kies onder “Welke gebeurtenissen?” wat je wilt ontvangen en klik op “Webhook aanmaken”.
- Kopieer het geheim dat daarna verschijnt naar je ontvanger.
- Klik op “Test versturen” — het resultaat staat er meteen onder.
Wat er binnenkomt
Elke gebeurtenis is een POST met JSON. In data.object staat het object in dezelfde vorm als in de API — een bestelling zoals bij GET /v1/orders/{id}, een antwoord zoals in de lijst met antwoorden. Bij formuliergebeurtenissen staat in data.form bovendien bij welk formulier het antwoord hoort.
{
"id": "evt_Q2x9kLmP4vT7aB1cD3eF5gH7",
"object": "event",
"type": "order.paid",
"api_version": "2026-09-23",
"created_at": "2026-09-23T14:05:12Z",
"data": {
"object": {
"id": 5531,
"object": "order",
"number": 42,
"status": "confirmed",
"payment_status": "paid",
"currency": "EUR",
"total": 3890,
"customer": { "email": "mara@example.com", "name": "Mara Sol" },
"items": [
{ "name": "Kaffeebohnen, 500 g", "sku": "KAF-500", "quantity": 2, "unit_price": 1690 }
]
}
}
}De handtekening controleren
Elke aanroep bevat de header KENJTEC-Signature: t=<tijd>,v1=<handtekening>. De handtekening is een HMAC-SHA256 over de tijd, een punt en de ongewijzigde body van het verzoek — met het geheim van je webhook als sleutel. Verwerp alles met een tijdstip dat meer dan vijf minuten oud is.
Controleer tegen de ruwe body voordat je de JSON inleest: één afwijkende spatie levert al een andere handtekening op. Het geheim vind je altijd onder “Geheim tonen”; “Geheim vernieuwen” maakt het oude meteen ongeldig.
import crypto from "node:crypto";
// raw: the unparsed request body (Buffer), header: the KENJTEC-Signature header
export function verify(raw, header, secret) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = crypto.createHmac("sha256", secret)
.update(`${parts.t}.`).update(raw).digest("hex");
const given = String(parts.v1 ?? "");
return given.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given));
}import hashlib, hmac, time
def verify(raw: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > 300:
return False
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))Dezelfde gebeurtenis kan twee keer binnenkomen — bijvoorbeeld als je server antwoordt, maar het antwoord ons niet bereikt. De ID in id (ook in de header KENJTEC-Event-Id) blijft daarbij gelijk: onthoud die en verwerk elke gebeurtenis maar één keer.
Als iets niet aankomt
Elk antwoord met een status van 200 tot 299 binnen tien seconden geldt als afgeleverd. Doorverwijzingen volgen we niet.
Komt een gebeurtenis niet aan, dan proberen we het opnieuw: na 1, 5 en 30 minuten, na 2, 6 en 12 uur en twee keer na 24 uur — ruim drie dagen lang. Komen vijf gebeurtenissen achter elkaar definitief niet aan, dan schakelen we de webhook uit; in het dashboard staat dan waarom, en “Weer inschakelen” zet hem terug.
Onder “Logboek” zie je elke aflevering van de afgelopen 30 dagen met status en inhoud. Van daaruit kun je elke gebeurtenis met “Opnieuw verzenden” nog een keer versturen.

Webhooks gaan alleen naar openbare https-adressen. Adressen in interne netwerken en adressen van KENJTEC zelf accepteren we niet.