Webhooks
Webhooks verbinden Rufona per HTTP mit deinem System — in beide Richtungen. Eine Integration, zwei Auslöser-Arten (Feld „Auslöser” im Editor):
- „Automatisch” (bei einem Ereignis): Rufona sendet eine HTTP-Anfrage an deine URL, z. B. nach jedem Anruf.
- „Auf Anfrage” (Assistent entscheidet): der Assistent fragt während des Gesprächs deine API ab und nutzt die Antwort im Gespräch.
Einrichten
Abschnitt betitelt „Einrichten“- Seitenleiste „Assistenten” → Assistent öffnen → Tab „Integrationen” → Karte „Webhooks” (noch nicht hinzugefügt: über „Integration hinzufügen” aus dem Katalog wählen).
- „Webhook hinzufügen”, dann den „Auslöser” wählen.
- „Speichern” — Änderungen gelten erst danach.
Mehrere Webhooks pro Assistent sind möglich, jeder einzeln per Schalter aktivierbar. Der Master-Schalter der Integration schaltet alle gemeinsam ab. Ein grauer Statuspunkt in der Liste heißt: der Eintrag ist noch wirkungslos (URL fehlt, bei „Auf Anfrage” auch ein gültiger Name).
Auslöser „Automatisch”: Ereignis-Webhooks
Abschnitt betitelt „Auslöser „Automatisch”: Ereignis-Webhooks“Du hinterlegst eine „URL” (nur öffentliche https-URLs, keine internen/lokalen Adressen) und wählst unter „Events” die Ereignisse. Die UI zeigt deutsche Labels; die technische Event-ID steht im Payload.
Gruppe „Nach dem Anruf” — gefeuert, sobald der Anruf abgeschlossen und ausgewertet ist (inkl. Zusammenfassung, Transkript, extrahierter Felder):
| Event | ID |
|---|---|
| Anruf abgeschlossen | call.completed |
| An Mitarbeiter weitergeleitet | call.transferred |
| Anrufer hat aufgelegt | call.missed |
| Technischer Fehler | call.failed |
| Jeder Anruf-Abschluss | call.ended (Sammel-Abo, deckt alle vier ab) |
Gruppe „Während des Anrufs” — live gefeuert, mit leichterem Payload (noch kein Transkript, keine Zusammenfassung):
| Event | ID |
|---|---|
| Anruf angenommen | call.started (direkt nach der Begrüßung) |
| Weiterleitung gestartet | call.transfer.started (beim Versuch — ob sie gelingt, meldet danach An Mitarbeiter weitergeleitet) |
Payload
Abschnitt betitelt „Payload“Standard-Schema (JSON) eines Nach-dem-Anruf-Webhooks — das Feld event trägt immer die konkrete Event-ID, auch beim Sammel-Abo call.ended:
{ "event": "call.completed", "deliveryId": "…", "timestamp": "2026-07-13T14:30:00.000Z", "call": { "id": "…", "agentId": "…", "contactId": null, "phoneNumber": "+4930…", "direction": "inbound", "outcome": "…", "summary": "Anrufer möchte einen Rückruf zu seiner Bestellung.", "transcript": [ { "role": "…", "text": "…" } ], "extractedFields": { "name": "…", "email": "…" }, "durationSeconds": 142, "consent": "…", "callerRegion": "…", "createdAt": "…" }}contactId ist der erkannte bzw. angelegte Kontakt, sonst null. Während-des-Anrufs-Events tragen stattdessen nur call: { agentId, callerNumber, dialedNumber }. Die exakte Struktur mit einem Beispiel-Anruf zeigt die „JSON-Vorschau” im Editor (Button „Kopieren”).
Unter „Eigener Payload (optional)” → „Vorlage” ersetzt ein eigenes JSON-Template das Standard-Schema. Platzhalter wie {{call.summary}}, {{call.phoneNumber}}, {{event}} sind reine Wertersetzung (keine Logik) und gehören innerhalb von Anführungszeichen. Ist die gerenderte Vorlage kein gültiges JSON, wird das Standard-Schema gesendet.
Header und Signatur
Abschnitt betitelt „Header und Signatur“Jede Zustellung trägt:
| Header | Inhalt |
|---|---|
x-rufona-event | Event-ID |
x-rufona-delivery | eindeutige Zustell-ID |
user-agent | rufona-webhook/2 |
x-rufona-signature | nur bei gesetztem „Signing-Secret (optional)” |
Unter „Eigene Header (optional)” gibst du eigene Schlüssel/Wert-Paare mit (z. B. Authorization), die jeder Anfrage angehängt werden. Reservierte Header (content-type, host, user-agent, x-rufona-*) können nicht überschrieben werden.
Signatur: HMAC-SHA256 über <timestamp>.<body>, Header-Wert im Format t=<unix-sekunden>,v1=<hex>. Zum Verifizieren rechnest du die HMAC mit dem geteilten Secret über den rohen Request-Body nach (nicht über das geparste JSON):
const crypto = require("node:crypto");
function verify(header, rawBody, secret) { const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("="))); const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex"); return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));}Unter „Erweitert (Methode, Format, Signatur)” wählst du außerdem die „Methode” (POST/PUT/PATCH, Standard POST) und das „Format” („JSON” oder „Form-encoded” — flaches URL-encoded-Formular, verschachtelte Objekte als JSON-String).
Bedingungen
Abschnitt betitelt „Bedingungen“Unter „Bedingungen (wann genau)” grenzt du die Zustellung ein:
- „Mindestdauer”: Keine / ab 10 Sekunden / ab 30 Sekunden / ab 1 Minute / ab 2 Minuten.
- „Richtung”: „Alle Anrufe” / „Nur eingehende” / „Nur ausgehende”.
- „Pflichtfelder (optional)”: nur senden, wenn diese extrahierten Felder vorhanden sind (Komma-getrennt, z. B.
name, email). - „Test-Anrufe einschließen”: standardmäßig aus — In-Dashboard-Testanrufe lösen sonst keine Webhooks aus.
„Mindestdauer” und „Pflichtfelder” wirken nur auf Nach-dem-Anruf-Events, nicht auf Anruf angenommen / Weiterleitung gestartet.
Zustellung
Abschnitt betitelt „Zustellung“Bei vorübergehenden Fehlern (5xx, 429, Netzwerkfehler/Timeout) versucht Rufona die Zustellung bis zu 3-mal in kurzen Abständen; bei 4xx-Ablehnung oder Redirect gibt es keinen weiteren Versuch. Timeout: 5 s pro Versuch. Die Zustellung läuft unabhängig vom Anruf — ein nicht erreichbares System beeinträchtigt nie den Anruf oder dessen Erfassung im Anrufverlauf (Transkript, Zusammenfassung, Felder). Den Empfang prüfst du über den Button „Test senden” und dein eigenes Empfangssystem; ein Zustellprotokoll im Dashboard gibt es nicht.
Testen: Button „Test senden” schickt einen Beispiel-Payload (markiert mit test: true) an deine URL — Ergebnis: „Erfolgreich zugestellt (Status …).” oder „Fehlgeschlagen: …” mit Antwort-Ausschnitt. Der Test macht genau einen Zustellversuch ohne Wiederholung.
Auslöser „Auf Anfrage”: Live-Datenabruf
Abschnitt betitelt „Auslöser „Auf Anfrage”: Live-Datenabruf“Der Assistent fragt während des Gesprächs selbst deine API ab — z. B. einen Bestellstatus, den der Anrufer wissen will:
- Du definierst den „Name” (Pflicht — der Tool-Bezeichner, den der Assistent sieht; beginnt mit einem Buchstaben, dann Buchstaben/Ziffern/Unterstrich, max. 64 Zeichen, z. B.
bestellstatus_abfragen), „Wann nutzen?” (beschreibt dem Assistenten, wofür die Abfrage gedacht ist), „Methode” (GET/POST/PUT/PATCH/DELETE, Standard GET) und die „URL” mit Platzhaltern, z. B.https://api.musterfirma.de/orders/{{params.bestellnummer}}. - Unter „Parameter” legst du je Wert einen Namen (z. B.
bestellnummer) plus „Beschreibung (für den Assistenten)” an. Der Assistent entscheidet im Anruf anhand von „Wann nutzen?” selbst, das Tool zu nutzen, und entnimmt die Parameterwerte dem Gespräch. - Rufona baut die Anfrage serverseitig zusammen und ruft deine API auf. Bei POST/PUT/PATCH steuert die „Body-Vorlage (optional, JSON)” den Body; leer = die Parameter werden als JSON gesendet. GET/DELETE senden keinen Body.
- Die „Antwort-Vorlage (optional)” formt die Antwort für den Assistenten, z. B.
Status: {{response.status}}, voraussichtlich am {{response.eta}}.— leer = die rohe (auf ~4000 Zeichen gekürzte) JSON-Antwort. Der Assistent spricht die Information dann aus.
Latenz: Der Anrufer wartet hörbar — der Assistent überbrückt die Abfrage mit kurzen natürlichen Füllsätzen. Antworte deshalb so schnell wie möglich; nach ~6 s bricht Rufona die Abfrage ab. Schlägt sie fehl, erhält der Assistent „Die externe Datenquelle ist gerade nicht erreichbar.” und reagiert freundlich — der Anruf bricht nie ab.
Testen ohne Anruf: Unter „Test mit Beispielwerten” trägst du je Parameter einen „Beispielwert” ein, dann „Test abfragen” — die Box „Antwort des Assistenten” zeigt exakt den Text, den der Assistent im Anruf bekäme.
Grenzen
Abschnitt betitelt „Grenzen“- Nur öffentliche https-URLs; interne/lokale Adressen werden blockiert. HTTP-Redirects werden nicht gefolgt und zählen als fehlgeschlagen.
- Eigener Payload/Body: nur gültiges JSON wird gesendet; sonst fällt Rufona auf das Standard-Schema (bzw. Parameter-als-JSON) zurück.
- Webhooks erfordern keinen bestimmten Tarif; Live-Anrufe setzen generell einen aktiven Tarif voraus, siehe Abrechnung.