Ringhum.

Ontwikkelaars

Webhooks

Ontvang ondertekende HTTPS-meldingen wanneer gesprekken eindigen, berichten worden aangenomen, afspraken, bestellingen en reserveringen wijzigen, of een campagne eindigt, en controleer of elke melding echt van Ringhum kwam.

6 min leestijd Bijgewerkt op 24 september 2026

Op deze pagina

Een webhook stuurt op het moment dat er iets in je werkruimte gebeurt een HTTPS-verzoek naar je server. Gebruik webhooks in plaats van de API te pollen: wanneer een gesprek eindigt, ontvang je meteen de samenvatting, uitkomst, verzamelde gegevens en het transcript. Elke aflevering wordt ondertekend met een geheim dat alleen jij en Ringhum kennen, zodat je server alles kan weigeren dat niet van Ringhum kwam.

Een endpoint toevoegen

Alleen de Eigenaar en Beheerders van de werkruimte kunnen endpoints toevoegen, testen en verwijderen.

  1. Open Ontwikkelaars in de zijbalk.
  2. Klik in het kaartje Webhooks op Endpoint toevoegen.
  3. Voer de Endpoint-URL in. Deze moet beginnen met https://.
  4. Vink onder Events de events aan die je wilt. call.ended staat al aangevinkt.
  5. Klik op Endpoint toevoegen.
  6. Kopieer het ondertekeningsgeheim uit het groene vak (het begint met whsec_) en bewaar het op je server. Klik op Klaar.

Belangrijk: Het ondertekeningsgeheim wordt maar één keer getoond. Verwijder het endpoint en voeg het opnieuw toe om een nieuw geheim te krijgen als je het kwijtraakt.

Je kunt zoveel endpoints toevoegen als je nodig hebt. Webhooks dekken elke assistent in de werkruimte. Je kunt endpoints ook via de API beheren, met POST /webhooks en een sleutel met de scope write.

Events

Event Wanneer het wordt verstuurd
call.started Een gesprek werd beantwoord door een assistent
call.ended Een gesprek eindigde en werd samengevat (bevat transcript en samenvatting)
call.transferred Een gesprek werd doorverbonden naar een mens
message.taken De assistent nam een bericht aan
appointment.booked De assistent boekte een afspraak
appointment.rescheduled Een afspraak werd verzet naar een nieuwe tijd
appointment.cancelled Een afspraak werd geannuleerd
order.created Er werd een bestelling geplaatst (door een assistent, met de hand of via de API)
order.updated Een bestelling kreeg een nieuwe status
order.cancelled Een bestelling werd geannuleerd
reservation.created Er werd een kamer gereserveerd (door een assistent, met de hand of via de API)
reservation.updated Een reservering kreeg een nieuwe status (bevestigd, ingecheckt, uitgecheckt, niet verschenen)
reservation.cancelled Een reservering werd geannuleerd
campaign.completed Een uitgaande campagne beëindigde het bellen van zijn lijst
test.ping Je klikte op Test versturen

Hoe een aflevering eruitziet

Elke aflevering is een POST met een JSON-body en deze headers:

POST https://example.com/hooks/ringhum
Content-Type: application/json
User-Agent: Ringhum-Webhooks/1.0
X-Ringhum-Event: call.ended
X-Ringhum-Timestamp: 1789250000
X-Ringhum-Signature: v1=5f1a…

{
  "id": "evt_8f2k…",
  "type": "call.ended",
  "created_at": "2026-09-24T14:03:11+00:00",
  "data": {
    "call_id": 4812,
    "direction": "inbound",
    "from": "+14155550132",
    "to": "+14155550100",
    "assistant_id": 3,
    "status": "completed",
    "outcome": "message_taken",
    "sentiment": "neutral",
    "duration_seconds": 94,
    "summary": "Caller asked for a quote for a kitchen repair…",
    "extracted": { "name": "Dana Lee", "reason": "Quote" },
    "transcript": [
      { "role": "assistant", "content": "Hello, you've reached…" },
      { "role": "user", "content": "Hi, I'd like a quote…" }
    ]
  }
}

Het object data hangt af van het event:

  • call.ended en message.taken: de bovenstaande gespreksvelden.
  • call.started en call.transferred: call_id, direction, from, to, assistant_id, status en started_at.
  • appointment.*: appointment_id, title, status, starts_at, ends_at, timezone, customer (naam, telefoon, e-mail), contact_id, service, staff, call_id en notes.
  • order.*: order_id, number, status, fulfillment, customer, address, items met opties en prijzen, currency, subtotal, fee, total, source, call_id en, bij annuleringen, cancel_reason.
  • reservation.*: reservation_id, number, status, room, check_in, check_out, nights, adults, children, guest, currency, nightly, total en source.
  • campaign.completed: campaign_id, name en de voortgangscijfers van de campagne.

Let op: Wanneer de assistent tijdens een gesprek een afspraak boekt, kun je appointment.booked twee keer ontvangen. De ene wordt verstuurd zodra de boeking wordt gemaakt, met de afspraakvelden. De andere wordt verstuurd nadat het gesprek is samengevat, met de gespreksvelden. Controleer of data een appointment_id of call_id heeft, en gebruik het veld id om te voorkomen dat je een aflevering twee keer verwerkt.

De handtekening controleren

De handtekening is een HMAC-SHA256 van de timestamp, een punt, en de ruwe requestbody, versleuteld met het ondertekeningsgeheim van je endpoint. Deze wordt verstuurd als v1= gevolgd door de hexadecimale digest.

  1. Lees de ruwe body precies zoals ontvangen, vóór enige JSON-parsing.
  2. Bouw de string {X-Ringhum-Timestamp}.{ruwe body}.
  3. Bereken de HMAC-SHA256 met je geheim en zet er v1= voor.
  4. Vergelijk deze met X-Ringhum-Signature met een constante-tijd vergelijking.
  5. Wijs het verzoek af als de timestamp ouder is dan vijf minuten, om herhaalde verzoeken te blokkeren.

Node.js:

const crypto = require('crypto');

function isValid(req, rawBody, secret) {
  const ts = req.header('X-Ringhum-Timestamp');
  const sig = req.header('X-Ringhum-Signature') || '';
  const expected = 'v1=' + crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && sig.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

PHP:

$ts = $_SERVER['HTTP_X_RINGHUM_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_RINGHUM_SIGNATURE'] ?? '';
$expected = 'v1=' . hash_hmac('sha256', $ts . '.' . file_get_contents('php://input'), $secret);
if (! hash_equals($expected, $sig) || abs(time() - (int) $ts) > 300) {
    http_response_code(400);
    exit;
}

Responses, timeouts en herhaalpogingen

  • Antwoord met een 2xx-status om de aflevering te bevestigen. Doe traag werk pas nadat je hebt geantwoord.
  • Ringhum wacht maximaal 10 seconden op je antwoord.
  • Antwoordt je endpoint niet met een 2xx, dan wordt de aflevering in totaal tot 3 keer geprobeerd: meteen, opnieuw na ongeveer 10 seconden, en een laatste keer ongeveer 60 seconden later. Daarna wordt deze afgebroken.
  • Afleveringen kunnen in een andere volgorde binnenkomen. Gebruik created_at en de id's in data om ze in volgorde te zetten.

De tabel Webhooks toont van elk endpoint de laatste HTTP-status en wanneer deze is verstuurd. Een mislukt endpoint blijft actief; Ringhum zet het niet voor je uit.

Testen, pauzeren en verwijderen

  • Test versturen stuurt meteen een test.ping-event, en een bericht toont de HTTP-status die je endpoint teruggaf.
  • De schakelaar Actief pauzeert een endpoint. Events die gebeuren terwijl het uitstaat, worden niet later alsnog verstuurd.
  • Verwijderen verwijdert het endpoint en zijn geheim.

Veelgestelde vragen

Wat is het verschil met de Zapier-, Make- en n8n-apps onder Integraties? Die koppelingen gebruiken de pagina Integraties en de zes eventtypes ervan. Hun body is {"event", "workspace", "sent_at", "data"}, en wanneer je een geheim instelt, is de handtekeningheader X-Ringhum-Signature: sha256=…, een HMAC-SHA256 van alleen de body. Ontwikkelaarswebhooks, hier beschreven, dekken meer events en gebruiken de v1=-handtekening met een timestamp. Zie Kiezen wat wordt verstuurd.

Mijn endpoint geeft 2xx terug maar mijn code ziet niets. Controleer of het event is aangevinkt voor dat endpoint, of het endpoint actief is, en of je firewall verzoeken vanaf het internet toestaat.

Waarom mislukt de handtekeningcontrole? Meestal omdat de body werd geparseerd en opnieuw gecodeerd vóór het hashen. Hash de ruwe bytes precies zoals ontvangen.

Kom je er niet uit?

Mail naar [email protected] of stuur ons een bericht. De abonnementen Team en Scale krijgen support met voorrang.

Contact opnemen met support