Koppelingen: API en webhooks
Lees terugbelverzoeken uit met de API en krijg direct een bericht op je eigen adres als er iets binnenkomt of verandert. Onderdeel van Belterug Zakelijk.
Koppelingen horen bij Belterug Zakelijk. Je beheert ze op je profiel onder “Koppelingen”: daar maak je API-sleutels aan, registreer je webhooks en zie je van elke webhook de laatste leveringen. Een sleutel of webhook werkt altijd namens het account zelf, niet namens een teamlid.
Authenticatie
Maak op je profiel een API-sleutel aan; je ziet hem één keer. Stuur hem bij elk verzoek mee als Bearer-token.
Alle adressen beginnen met https://belterug.nl/api/v1 en antwoorden met JSON.
curl https://belterug.nl/api/v1/requests \
-H "Authorization: Bearer belterug_XXXXXXXX" \
-H "Accept: application/json"
Een onbekende of ingetrokken sleutel geeft 401. Is het abonnement van het account geen Belterug Zakelijk
meer, dan geeft elk verzoek 403 tot het plan weer actief is; de sleutels blijven bestaan.
Limieten
Per sleutel zijn 60 verzoeken per minuut toegestaan. Elk antwoord draagt de headers X-RateLimit-Limit
en X-RateLimit-Remaining; daarboven krijg je 429 met een Retry-After-header.
Haal wijzigingen liever op via een webhook dan door vaak te pollen.
Endpoints
GET /requests
De terugbelverzoeken van het account, nieuwste eerst, 50 per pagina (?page=2 voor de volgende). Verzoeken die nog op een e-mailbevestiging van de beller wachten, staan er niet in; dat is dezelfde regel als op het dashboard.
status | new of called_back. |
|---|---|
number_id | Alleen verzoeken die via dit nummer binnenkwamen (id uit /numbers). |
since | Alleen verzoeken aangemaakt op of na dit moment, ISO 8601 (2026-10-01 of 2026-10-01T08:00:00+02:00). |
archived | true: alleen gearchiveerde verzoeken; false: alleen de lijst. Weggelaten: beide. |
GET https://belterug.nl/api/v1/requests?status=new&archived=false&since=2026-10-01
{
"data": [ { ...request... }, ... ],
"links": { "first": "...", "last": "...", "prev": null, "next": "..." },
"meta": { "current_page": 1, "per_page": 50, "total": 123, ... }
}
GET /requests/{id}
Eén verzoek. Een id van een ander account bestaat voor jouw sleutel niet en geeft 404.
{
"data": {
"id": 4821,
"caller_name": "Noor de Vries",
"caller_number": "0612345678",
"caller_email": "noor@example.com",
"message": "Graag terugbellen over de offerte.",
"reason": "Offerte of afspraak",
"callback_window": "ochtend",
"status": "new",
"archived_at": null,
"claimed_by": null,
"phone_number": { "id": 7, "label": "Winkel", "number": "0851234567" },
"created_at": "2026-10-24T09:41:12+02:00"
}
}
status is new of called_back. callback_window is de sleutel van het
door de beller gekozen tijdvak (of null); reason is het onderwerp uit jouw eigen lijst.
claimed_by wordt { "id", "name" } zodra een collega het verzoek in de teaminbox heeft opgepakt.
PATCH /requests/{id}
Zet de status en/of archiveer. Beide velden zijn optioneel; het antwoord is het bijgewerkte verzoek. De wijziging vuurt dezelfde webhooks af als een klik op het dashboard.
PATCH https://belterug.nl/api/v1/requests/4821
Content-Type: application/json
{ "status": "called_back", "archived": true }
GET /numbers
Alle nummers van het account, het inlognummer eerst. Het id is wat number_id op /requests verwacht.
{
"data": [
{ "id": 1, "label": null, "number": "0612345678", "type": "mobile", "is_primary": true, "verified": true, "callback_url": "https://belterug.nl/0612345678" },
{ "id": 7, "label": "Winkel", "number": "0851234567", "type": "landline", "is_primary": false, "verified": true, "callback_url": "https://belterug.nl/0851234567" }
]
}
Webhooks
Een webhook is een https-adres van jou waar we een POST met JSON naartoe sturen zodra een van de gekozen
gebeurtenissen plaatsvindt. Je registreert hem op je profiel en kiest daar de gebeurtenissen; bij het aanmaken krijg
je één keer het geheim te zien waarmee elk bericht wordt ondertekend. Met “Test versturen” stuur je direct een
ping om je ontvanger te controleren.
request.created | Nieuw verzoek |
|---|---|
request.updated | Status gewijzigd (teruggebeld, teruggezet) |
request.archived | Gearchiveerd |
ping | Het testbericht vanaf je profiel; data bevat alleen een korte tekst. |
request.created komt zodra het verzoek op het dashboard staat: bij een beller die zijn e-mailadres nog
moet bevestigen dus pas na die bevestiging. request.updated volgt op een statuswijziging, het terugzetten
uit het archief en het oppakken door een collega; request.archived op archiveren (ook via een spammelding).
Bericht
data heeft precies de vorm van een verzoek uit de API, zodat je één verwerker voor beide kunt gebruiken.
POST https://jouw-server.example/belterug
Content-Type: application/json
User-Agent: belterug.nl-webhooks/1.0
X-Belterug-Event: request.created
X-Belterug-Delivery: 3f1c2d58-6c0e-4a3e-9d7b-2a7e5c1f0b44
X-Belterug-Signature: sha256=5d41402abc4b2a76b9719d911017c592...
{
"event": "request.created",
"created_at": "2026-10-24T09:41:13+02:00",
"data": { "id": 4821, "caller_name": "Noor de Vries", ... }
}
X-Belterug-Event | De gebeurtenis, gelijk aan event in de body. |
|---|---|
X-Belterug-Delivery | Uniek id van deze levering. Een herhaalde poging draagt hetzelfde id, zodat je dubbele verwerking kunt voorkomen. |
X-Belterug-Signature | sha256= gevolgd door de HMAC-SHA256 (hex) van de ruwe body met jouw geheim als sleutel. |
Handtekening controleren
Bereken de HMAC over de body precies zoals die binnenkwam (niet opnieuw geserialiseerd) en vergelijk met een tijdsveilige vergelijking. Zo weet je dat het bericht van belterug.nl komt en onderweg niet is veranderd.
// PHP
$valid = hash_equals('sha256='.hash_hmac('sha256', file_get_contents('php://input'), $secret), $_SERVER['HTTP_X_BELTERUG_SIGNATURE'] ?? '');
// Node.js (rawBody is a Buffer or string with the unparsed body)
const valid = require('crypto').timingSafeEqual(Buffer.from('sha256=' + require('crypto').createHmac('sha256', secret).update(rawBody).digest('hex')), Buffer.from(req.headers['x-belterug-signature'] || ''));
Antwoorden en herhalingen
- Antwoord binnen 5 seconden met een
2xx-status; de inhoud van je antwoord lezen we niet. Doe zwaar werk pas na het antwoord. - Elke andere status, een time-out of een verbindingsfout telt als mislukt. We proberen het dan nog eens, tot 3 pogingen in totaal binnen 24 uur; de herhalingen lopen ongeveer eens per uur.
- Na 10 mislukte leveringen op rij schakelt de webhook zichzelf uit en krijg je daar één e-mail over. Op je profiel zet je hem weer aan; de teller begint dan opnieuw.
- Op je profiel zie je per webhook de laatste 20 leveringen met status, duur en foutmelding.
Zapier, Make en vergelijkbare tools
Een “Catch Hook”-adres van Zapier (Webhooks by Zapier) of een “Custom webhook” van Make werkt direct als webhook-adres:
plak het op je profiel, kies de gebeurtenissen en stuur een test. De velden uit data verschijnen daar als
losse waarden die je in elke volgende stap kunt gebruiken.
CSV-export
Liever een spreadsheet dan een koppeling? Op het dashboard staat voor Belterug Plus en Belterug Zakelijk de knop “Exporteer CSV”: alle verzoeken, nieuwste eerst, als UTF-8 met puntkomma's, zodat Excel het bestand direct opent.
Hulp nodig?
Mail ons via de contactpagina met een voorbeeld van je verzoek (zonder je sleutel) en wat je terugkreeg.