Tillor
Ontwikkelaars

Webhooks

Ontvang realtime events via HTTP POST naar jouw endpoint

Webhooks ontvangen realtime events via HTTP POST naar een door jou geconfigureerde URL. Dezelfde events zijn ook beschikbaar via SSE. Webhooks zijn per organisatie geconfigureerd - elke organisatie heeft zijn eigen webhooks.

Beheer

Zie de OpenAPI-specificatie voor volledige request- en response-schema's.

MethodPadBeschrijving
GET/api/orgs/:orgId/webhooksWebhooks ophalen
GET/api/orgs/:orgId/webhooks/:idWebhook op ID ophalen
POST/api/orgs/:orgId/webhooksWebhook aanmaken
PATCH/api/orgs/:orgId/webhooks/:idWebhook bijwerken
DELETE/api/orgs/:orgId/webhooks/:idWebhook verwijderen

Webhook aanmaken

POST /api/orgs/org_abc123/webhooks
Content-Type: application/json
x-api-key: tkn_xxx
X-Tillor-Org-Id: org_abc123
{
  "url": "https://jouw-server.com/webhooks/tillor",
  "subscribedEventKeys": ["invoice:created", "invoice:paid", "customer:updated"],
  "enabled": true
}
  • url - HTTPS-endpoint die POST-requests accepteert
  • subscribedEventKeys - Array van event keys of ["*"] voor alle events. De volledige lijst staat in Tillor onder Instellingen → Ontwikkelaars bij het aanmaken van een webhook.
  • enabled - true om levering in te schakelen

Webhook-payload

Elke webhook-levering is een POST met:

Headers:

  • Content-Type: application/json
  • X-Webhook-Event-ID - stabiele unieke ID voor deze logische levering (zelfde waarde bij retries)
  • X-Webhook-Signature - HMAC-SHA256 handtekening van de body, formaat sha256=<hex> (zie Handtekening verifiëren)

Body:

{
  "event": "invoice:created",
  "data": {},
  "timestamp": 1735689600000
}
VeldTypeBeschrijving
eventstringEvent key (bijv. invoice:created)
dataobjectEvent-specifieke payload
timestampnumberUnix timestamp (ms) wanneer het event werd uitgezonden

Zie Voorbeelden voor volledige payload-voorbeelden.


Handtekening verifiëren

Elke webhook bevat een eigen signing secret (64 hex-karakters, getoond bij aanmaken in Instellingen → Ontwikkelaars). Tillor ondertekent elke POST met die secret zodat jij kunt verifiëren dat het verzoek écht van Tillor komt en dat de body niet is aangepast.

Hoe Tillor ondertekent:

  1. Bereken HMAC-SHA256(signingSecret, raw_request_body) (lowercase hex).
  2. Stuur dat als X-Webhook-Signature: sha256=<hex>.

Hoe jij verifieert:

  1. Lees de ruwe request-body (vóór JSON-parsen — anders matcht de hash niet).
  2. Bereken zelf HMAC-SHA256(signingSecret, raw_body) in hex.
  3. Vergelijk met de waarde achter sha256= uit de X-Webhook-Signature header met een constant-time vergelijking.
import crypto from "node:crypto";

function verifyTillorWebhook(rawBody, headerSignature, signingSecret) {
  const expected = crypto.createHmac("sha256", signingSecret).update(rawBody).digest("hex");
  const received = headerSignature.replace(/^sha256=/, "");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(received, "hex");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Behandel de secret als wachtwoord

De signing secret wordt eenmalig getoond bij aanmaken. Sla 'm op als secret (env var, vault) en log 'm nooit. Vermoed je een lek? Verwijder de webhook en maak een nieuwe aan; daarmee krijg je een nieuwe secret.


Leveringsgedrag en retries

  • Antwoord met een 2xx-status om succes te bevestigen.
  • Bij een mislukte levering (niet-2xx, netwerkfout of geblokkeerd doel) probeert Tillor de levering automatisch opnieuw met steeds langere tussenpozen. Elke poging hergebruikt dezelfde payload, dezelfde handtekening en hetzelfde event-id (idempotent).
PogingWachttijd sinds vorige poging
1direct
21 seconde
32 seconden
44 seconden
58 seconden
65 minuten
730 minuten
82 uur
96 uur
1024 uur
  • Slaagt één van de pogingen (2xx) → de levering is afgerond.
  • Slaagt ook poging 10 (na 24u) niet → de levering wordt definitief gemarkeerd als mislukt en niet verder geprobeerd.
  • Wordt de webhook intussen uitgeschakeld, dan stopt Tillor met opnieuw proberen.

Idempotentie

Elke retry hergebruikt dezelfde X-Webhook-Event-ID en X-Webhook-Signature. Dedupliceer aan jouw kant op die header zodat een succesvolle retry na een trage 200 geen dubbele verwerking veroorzaakt.


Event types

Event keys gebruiken het formaat entity:action of entity:subresource:action. Hieronder een selectie; de volledige lijst staat in Tillor onder Instellingen → Ontwikkelaars - in Tillor: Instellingen → Ontwikkelaars (per organisatie) bij het aanmaken van een webhook.

Event KeyBeschrijving
* (wildcard)Abonneer op alle events
accessLogEntry:coupledToegangslog-entry gekoppeld aan klant of toegangsmethode
accessLogEntry:processedToegangslog-entry verwerkt
accessMethod:createdToegangsmethode aangemaakt
accessMethod:deletedToegangsmethode verwijderd
accessMethod:updatedToegangsmethode bijgewerkt
accessMethodOperation:createdToegangsmethode-operatie aangemaakt
accessMethodOperation:updatedToegangsmethode-operatie bijgewerkt
barrier:createdBarrière aangemaakt
barrier:deletedBarrière verwijderd
barrier:updatedBarrière bijgewerkt
call:createdGesprek aangemaakt
call:updatedGesprek bijgewerkt
comment:createdReactie aangemaakt
comment:deletedReactie verwijderd
comment:mentionedGebruiker genoemd in reactie
comment:pinnedReactie vastgepind
comment:resolvedReactie opgelost
comment:updatedReactie bijgewerkt
controller:adoption:approvedController-adoptie goedgekeurd
controller:adoption:rejectedController-adoptie afgewezen
controller:adoption:requestedController-adoptie aangevraagd
controller:createdController aangemaakt
controller:deletedController verwijderd
controller:logs:submittedController-logs ingediend
controller:updatedController bijgewerkt
customer:contact:createdKlantcontact aangemaakt
customer:contact:deletedKlantcontact verwijderd
customer:contact:updatedKlantcontact bijgewerkt
customer:createdKlant aangemaakt
customer:deletedKlant verwijderd
customer:updatedKlant bijgewerkt
document:createdDocument aangemaakt
document:deletedDocument verwijderd
document:updatedDocument bijgewerkt
event-log:createdEventlog-entry aangemaakt
event-log:updatedEventlog bijgewerkt
identityDocumentScan:completedIdentiteitsdocument-scan voltooid
identityDocumentScan:deletedIdentiteitsdocument-scan verwijderd
identityDocumentScan:linkedIdentiteitsdocument-scan gekoppeld aan klant
identityDocumentScan:unlinkedIdentiteitsdocument-scan ontkoppeld van klant
invoice:createdFactuur aangemaakt
invoice:deletedFactuur verwijderd
invoice:paidFactuur betaald
invoice:updatedFactuur bijgewerkt
mandate:createdMachtiging aangemaakt
mandate:deletedMachtiging verwijderd
mandate:updatedMachtiging bijgewerkt
nfc-tag:blockedNFC-tag geblokkeerd
nfc-tag:presentedNFC-tag gepresenteerd
nfc-tag:unblockedNFC-tag gedeblokkeerd
nfc-tag:updatedNFC-tag bijgewerkt
notification-delivery:updatedNotificatielevering bijgewerkt
payment-group:assigned-to-invoiceBetalingsgroep aan factuur gekoppeld
payment-group:createdBetalingsgroep aangemaakt
payment-group:deletedBetalingsgroep verwijderd
payment-group:payments-addedBetalingen toegevoegd aan betalingsgroep
payment-group:payments-removedBetalingen verwijderd uit betalingsgroep
payment-group:unassigned-from-invoiceBetalingsgroep ontkoppeld van factuur
payment-group:updatedBetalingsgroep bijgewerkt
payment-report:updatedBetalingsrapport bijgewerkt
payment:updatedBetaling bijgewerkt
pdf:clear-ipadPDF gewist van iPad
pdf:to-ipadPDF naar iPad verzonden
reservation:createdReservering aangemaakt
reservation:updatedReservering bijgewerkt

Webhooks vs SSE

Use caseAanbeveling
Server-side integratieWebhooks - Jouw server ontvangt POSTs
Eenvoudige loggingWebhooks - Minimale setup
Realtime dashboard, live updates in appSSE - Eén verbinding, lage latentie.
Veel event types, client-side filterenSSE - Gebruik events query-param om verkeer te beperken.

Gerelateerd

  • OpenAPI - Volledige API-specificatie
  • HTTP API - REST API en API-sleutels
  • SSE - Zelfde events via Server-Sent Events

On this page