Webhooks
Webhooks in Yarla zijn HTTP-verzoeken die wij op een vast moment in het gesprek naar je server sturen. Je maakt ze aan als HTTP-verzoek-actie; dit artikel behandelt wat alle drie de momenten gemeen hebben: de handtekening, het retrybeleid en de time-outs.
Drie momenten
| Moment | Wat er gebeurt | Artikel |
|---|---|---|
| Vóór het gesprek | Zodra een inkomend telefoongesprek binnenkomt, nog vóór de begroeting, sturen wij het nummer van de beller, je eigen nummer en je bedrijfsgegevens naar je endpoint. Dit gebeurt niet bij uitgaande gesprekken, sms, WhatsApp of webchat. De JSON die je teruggeeft krijgt de assistent als context; de waarden gebruik je in de begroeting als {{sleutel}} en in acties na het gesprek als {{inboundContext.sleutel}}. | Inkomende webhook (vóór het gesprek) |
| Tijdens het gesprek | De assistent besluit op basis van je voorwaarde om je endpoint aan te roepen (een "tool call"), bijvoorbeeld om een orderstatus op te zoeken. Je antwoord gaat terug naar de assistent, die het in het gesprek gebruikt. | Webhook tijdens het gesprek |
| Na het gesprek | Nadat het gesprek is afgelopen en de samenvatting en eigen variabelen zijn bepaald, sturen wij de gegevens van het gesprek naar je endpoint. | Webhook na het gesprek |
Wil je voor je hele account een bericht bij elk afgelopen gesprek, elke nieuwe aanvraag en elke afspraak, zonder actie per assistent? Gebruik dan Event-webhooks (Enterprise). Die worden op dezelfde manier ondertekend.
Alle drie zijn standaard POST-verzoeken met Content-Type: application/json. In de actie kun je methode, headers en body aanpassen. De handtekening gaat altijd mee, behalve bij GET: dat verzoek heeft geen body en geen handtekening.
Handtekening controleren
Elk verzoek dat wij versturen, behalve GET, bevat de header:
X-Yarla-Signature: t=1757581245,v1=5f1c9b2a7d0e4c6b8a1f3e5d7c9b2a4f6e8d0c2b4a6f8e0d2c4b6a8f0e2d4c6btis de Unix-tijd in seconden waarop wij het verzoek verstuurden.v1isHMAC-SHA256(secret, t + "." + rawBody), hexadecimaal gecodeerd.
Het geheim vind je onder Instellingen → Koppelingen bij Webhookgeheim. Met Nieuwe maken maak je na bevestiging een nieuw geheim aan; het oude geheim werkt daarna niet meer, dus werk direct daarna je server bij. Alleen beheerders van je eigen bedrijf zien en vernieuwen het geheim hier. Een reseller of supportmedewerker die in je account meekijkt, ziet het niet.
Controleer de handtekening zo:
- Splits de header op de komma en lees
tenv1. - Weiger het verzoek als het verschil tussen nu en
tgroter is dan 300 seconden (bescherming tegen herhaalde verzoeken). - Bereken de HMAC over exact de ruwe body, dus de bytes zoals ontvangen, niet opnieuw geserialiseerde JSON.
- Vergelijk het resultaat met
v1met een vergelijking in constante tijd.
Voorbeeld in Node.js met Express, voor een actie na het gesprek:
const express = require('express');
const crypto = require('crypto');
const app = express();
const SECRET = process.env.YARLA_WEBHOOK_SECRET;
const TOLERANCE_SECONDS = 300;
function verifySignature(header, rawBody) {
if (!header) return false;
const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=')));
const t = Number(parts.t);
const v1 = parts.v1;
if (!t || !v1) return false;
if (Math.abs(Date.now() / 1000 - t) > TOLERANCE_SECONDS) return false;
const expected = crypto
.createHmac('sha256', SECRET)
.update(`${t}.`)
.update(rawBody) // Buffer met de ruwe bytes
.digest('hex');
const a = Buffer.from(expected, 'hex');
const b = Buffer.from(v1, 'hex');
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
// express.raw zorgt dat req.body een Buffer is en niet al geparseerde JSON
app.post('/yarla/webhook', express.raw({ type: 'application/json' }), (req, res) => {
if (!verifySignature(req.get('X-Yarla-Signature'), req.body)) {
return res.status(401).send('invalid signature');
}
const event = JSON.parse(req.body.toString('utf8'));
// Antwoord direct en verwerk daarna asynchroon
res.status(200).json({});
setImmediate(() => handleEvent(event));
});
function handleEvent(event) {
// Zonder eigen body bevat het verzoek onder meer conversationId, summary en outcome
if (event.outcome === 'callback_requested') {
// bijvoorbeeld: taak aanmaken in je CRM
}
}
app.listen(3000);Gebruik de ruwe body
Parseert je framework de JSON al voordat je de handtekening controleert, dan bereken je de HMAC over een andere tekenreeks en klopt hij nooit. Gebruik in Express express.raw, in andere frameworks de vergelijkbare optie om de originele bytes te krijgen.
Retrybeleid
Wij proberen een mislukt verzoek niet automatisch opnieuw, en je kunt het ook niet handmatig opnieuw laten uitvoeren. Een verzoek geldt als mislukt bij een statuscode buiten 2xx, bij een time-out of als je endpoint niet bereikbaar is. Doorverwijzingen volgen wij en het laatste antwoord telt. Gebruik in de actie het definitieve adres: bij een doorverwijzing met 301, 302 of 303 wordt je verzoek een GET zonder body.
- Na het gesprek: het resultaat zie je bij het gesprek in de Inbox. Open Technische details en kijk bij Wat de acties hebben gedaan: daar staat de statuscode en bij een foutcode het begin van het antwoord. Bij een time-out of een onbereikbaar endpoint staat er alleen de foutmelding. Mislukt een actie, dan lopen de volgende acties gewoon door.
- Vóór het gesprek: de assistent begint zonder de gegevens van die actie. Wat je endpoint wel teruggaf, staat onder Technische details bij Gegevens die voor het gesprek zijn opgezocht; een mislukt verzoek zie je daar niet.
- Tijdens het gesprek: het resultaat wordt niet bij het gesprek getoond. Bij een foutcode hoort de assistent dat het opzoeken mislukte en vangt hij dat in het gesprek op.
Ontwerp je endpoint voor acties na het gesprek daarom zo: controleer de handtekening, sla het verzoek op, antwoord direct met 2xx en verwerk de gegevens daarna asynchroon. Verwerk je in het verzoek zelf, dan loop je tegen de time-out aan zodra je CRM even traag is. Bij acties vóór en tijdens het gesprek heeft de assistent je antwoord nodig: geef de gegevens daar direct terug, binnen de time-out hieronder.
IP-adressen toestaan
Een lijst met vaste IP-adressen is niet beschikbaar: onze uitgaande adressen kunnen veranderen. Beveilig je endpoint met HTTPS en de handtekening. Wil je een extra laag, voeg dan in de actie een eigen header toe met een lang, willekeurig token en controleer die op je server. Bij een GET-verzoek is zo'n header de enige controle, want daar gaat geen handtekening mee.
Time-outs
| Moment | Time-out | Bij overschrijding |
|---|---|---|
| Vóór het gesprek | 3 seconden | De assistent begint zonder de gegevens van deze actie. |
| Tijdens het gesprek | 6 seconden | Het opzoeken mislukt en de assistent krijgt geen gegevens van je endpoint. In een telefoongesprek kan de assistent dan stilvallen, dus antwoord ruim binnen deze tijd. |
| Na het gesprek | 8 seconden | De actie wordt bij het gesprek als mislukt gemarkeerd. |
Kom je geregeld in de buurt van deze grenzen, kijk dan in Problemen oplossen: webhooks.