Skip to main content

Hilfebereich / Webhooks & API

Webhooks & API

Integrieren Sie Swiftner über signierte Webhooks und die eingehende Automation-API mit n8n, Zapier oder Ihren eigenen Systemen.

Swiftner kann Ihre Systeme in dem Moment benachrichtigen, in dem auf einem Anruf etwas passiert, und Ihre Systeme können umgekehrt Daten an Swiftner zurückgeben. Drei Integrations-Kacheln nutzen dieselbe Schnittstelle: n8n, Zapier und generische Webhooks. Alle senden dieselben Payloads; nur das empfangende Tool unterscheidet sich.

Es gibt zwei Richtungen:

  • Ausgehend (Webhooks): Swiftner sendet signiertes JSON per POST an die URLs, die Sie konfigurieren. Das geschieht, wenn ein Anruf beginnt oder endet, wenn ein Coaching-Bericht bereitsteht oder an bestimmten Punkten während der Anrufverarbeitung (Stage-Hooks).
  • Eingehend (API): Ihre Systeme übermitteln Daten an Swiftner mit Ihrem API-Schlüssel. Sie können Anrufe starten, die Identität des Anrufers anhängen, Aufzeichnungen einreichen und Berichte abrufen.

Erste Schritte

  1. Öffnen Sie in Swiftner Admin → Integrationen und aktivieren Sie n8n, Zapier oder Webhooks.
  2. Erzeugen Sie im Integrations-Drawer Ihre Zugangsdaten: einen API-Schlüssel (für eingehende Aufrufe) und ein Signing-Secret (zum Verifizieren ausgehender Webhooks). Kopieren Sie beide sofort, denn sie werden nur einmal angezeigt.
  3. Fügen Sie unter Subscriptions pro gewünschtem Trigger eine Zeile hinzu: Trigger auswählen, Ihre Endpunkt-URL einfügen, speichern.
  4. Verwenden Sie Verbindung testen, um ein signiertes ping an jede konfigurierte URL zu senden.

Der Umschlag

Events, Stage-Hooks und das Test-Ping verwenden alle dieselbe JSON-Struktur:

{
  "event": "call_ended",
  "call_id": "8f14e45f-ceea-467f-a8d6-9f6d3d7f9f10",
  "external_call_id": "your-systems-call-id-or-null",
  "user": {
    "id": "d3b07384-d9a0-4c9e-8b6e-1a2b3c4d5e6f",
    "email": "rep@example.com",
    "name": "Rep Name"
  },
  "workspace_id": "b6589fc6-ab0d-4c82-8b0e-0242ac130003",
  "timestamp": "2026-07-16T17:22:05.123456+00:00",
  "data": {}
}
  • event ist der Name des Triggers (siehe unten). Die Testabfrage sendet "ping".
  • call_id ist die Anruf-ID von Swiftner, oder null bei ping.
  • external_call_id ist die ID, die Ihr System beim Erstellen des Anrufs über die eingehende API übergeben hat, andernfalls null.
  • user ist der Vertriebsmitarbeiter im Anruf. Bei Stage-Hooks ist nur id gesetzt, und email/name können null sein, wenn das Konto entfernt wurde.
  • timestamp ist der Zeitpunkt, zu dem die Payload erstellt wurde, im Format ISO 8601 mit UTC-Offset.
  • data enthält die ereignisspezifischen Felder, die weiter unten pro Event beschrieben werden.

Event-Abonnements

call_started wird ausgelöst, wenn die Live-Sitzung eines Mitarbeiters für einen Anruf geöffnet wird. Nutzen Sie es für Screen-Pops oder um pro Anruf einen Workflow zu starten.

"data": {
  "identifiers": {
    "phone_number": "+4791234567",
    "org_number": "912345678"
  }
}

identifiers enthält alles, was Swiftner in diesem Moment über den Anrufer aus seinen Integrationen erfahren hat. Beide Schlüssel können fehlen, und das Objekt kann leer sein. Anrufe, die Ihr eigener Flow über die eingehende API erstellt hat, senden kein call_started an Sie zurück.

call_ended wird ausgelöst, wenn der Anruf endet, bevor die KI-Verarbeitung abgeschlossen ist.

"data": { "duration_seconds": 342 }

coaching_report_ready wird ausgelöst, wenn die KI-Analyse nach dem Anruf abgeschlossen ist. Dies ist die Payload, die Sie in Ihr CRM zurückschreiben.

"data": {
  "call_summary": "…",
  "coaching_summary": "…",
  "focus_area": "…",
  "coaching_moments": ["…", "…"],
  "interest_level": "…",
  "interest_reason": "…"
}

Jedes Feld kann null sein, zum Beispiel bei Anrufen, die zu kurz für eine Analyse sind.

Stage-Hooks

Stage-Hooks funktionieren nach dem Request-Response-Prinzip. Swiftner sendet per POST eine Momentaufnahme an einem festen Punkt der Anrufverarbeitung, und wenn Ihr Endpunkt mit einem JSON-Objekt antwortet, werden diese Felder am Anruf gespeichert. Sie erscheinen dann in der Anrufansicht des Dashboards, und die KI von Swiftner kann sie als Kontext nutzen. So spielt Ihr Flow CRM-Daten in das Live-Coaching ein oder vermerkt eine Rückschreib-Bestätigung am Anruf.

Trigger Wann es ausgelöst wird
stage:identify Anrufbeginn, während die Identität des Anrufers ermittelt wird
stage:context Nach identify, während der Verlauf nachgeschlagen wird
stage:enrich Nach context, während der Anreicherung mit externen Daten
stage:prepare Bevor das Coaching beginnt, sobald die Gesprächspunkte zusammengestellt sind
stage:summarize Nach dem Anruf, bevor die KI-Zusammenfassungen erstellt werden
stage:export Nachdem der Anruf vollständig verarbeitet wurde, um Ergebnisse hinauszugeben

data der Anfrage:

"data": {
  "stage": "enrich",
  "identifiers": { "phone_number": "+4791234567", "org_number": null },
  "enrichment_context": { "…": "everything integrations have attached to this call so far" }
}

Antwortvertrag:

  • Antworten Sie innerhalb der Frist: standardmäßig 3 Sekunden, maximal 10 Sekunden (in den Einstellungen der Integration konfigurierbar).
  • Ein JSON-Objekt im Body wird unter dem Namespace Ihrer Integration in den Kontext des Anrufs zusammengeführt. Spätere Subscriptions auf derselben Stage überschreiben frühere, Schlüssel für Schlüssel.
  • Alles andere (leerer Body, kein JSON-Objekt, kein 2xx) wird ignoriert. Ein fehlgeschlagener Stage-Hook unterbricht die Anrufverarbeitung nie.

Signaturen verifizieren

Jede ausgehende Anfrage enthält:

X-Swiftner-Signature: t=1784309054,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

t ist ein Unix-Zeitstempel (Sekunden); v1 ist HMAC-SHA256(signing_secret, "{t}." + raw_body) in Hex. Verifizieren Sie sie, bevor Sie einer Payload vertrauen.

Node.js

const crypto = require("crypto");

function verifySwiftnerSignature(rawBody, header, secret, toleranceSec = 300) {
  const parts = Object.fromEntries(header.split(",").map((kv) => kv.split("=")));
  if (!parts.t || !parts.v1) return false;
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > toleranceSec) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${parts.t}.`)
    .update(rawBody) // the raw request bytes, before JSON parsing
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Python

import hashlib, hmac, time

def verify_swiftner_signature(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(kv.split("=", 1) for kv in header.split(","))
    if "t" not in parts or "v1" not in parts:
        return False
    if abs(time.time() - int(parts["t"])) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

Berechnen Sie den HMAC über den rohen Request-Body. Das Parsen und erneute Serialisieren des JSON verändert die Bytes und lässt die Verifizierung fehlschlagen. Weisen Sie veraltete Zeitstempel zurück, um Replays zu blockieren; 5 Minuten sind eine sinnvolle Toleranz. Fügen Sie diese Snippets in n8n und Zapier in einen Code- oder Function-Schritt ein, bevor Sie auf die Payload reagieren.

Zustellung und Wiederholungen

  • Antworten Sie schnell mit einem beliebigen 2xx; bei Event-Abonnements wird der Antwort-Body ignoriert.
  • Timeout für Event-Webhooks: 10 Sekunden.
  • coaching_report_ready wird bei einem Fehler wiederholt (Timeouts, 429, 5xx): bis zu 3 Versuche, etwa 15 Minuten auseinander. Ihr Endpunkt sieht denselben Bericht daher möglicherweise mehr als einmal, deduplizieren Sie deshalb über call_id + event. Wenn Sie mehrere Subscriptions auf demselben Trigger haben, stellt ein erneuter Versuch an alle erneut zu, auch an die, die bereits erfolgreich waren.
  • call_started und call_ended werden nicht wiederholt, da es sich um punktuelle Signale handelt. Alles, was zuverlässig sein muss, sollte auf coaching_report_ready aufbauen oder auf dem Abfragen der eingehenden API.
  • Andere 4xx-Antworten werden als Ablehnungen behandelt und nie wiederholt.

Eingehende API

Alles Eingehende authentifiziert sich mit Ihrem API-Schlüssel im Header X-API-Key. Basis-URL: https://api.hud.swiftner.app/api/v1/automation.

Endpunkt Was es tut
GET /me Prüft Ihren Schlüssel; gibt Ihre Integration + Ihren Mandanten zurück
PUT /external_users Ordnet die Benutzer Ihres Systems Swiftner-Mitarbeitern zu
PUT /external_groups Ordnet Ihre Teams/Gruppen Swiftner-Workspaces zu
POST /calls/start Kündigt einen Anruf an (idempotent bezüglich external_call_id)
POST /calls/{id}/identify Hängt Telefonnummer / Org-Nummer des Anrufers an
POST /calls/{id}/end Markiert den Anruf als beendet
POST /calls/{id}/context Übermittelt freien Kontext an den Anruf (max. 32 KB)
POST /calls/{id}/recording Übermittelt eine Aufzeichnungs-URL zur Transkription (einmal pro Anruf)
GET /calls, GET /calls/{id} Anrufe auflisten / lesen
GET /calls/{id}/report Ruft den Coaching-Bericht ab

Ein typischer Ablauf: Ihr Dialer klingelt → POST /calls/start mit Ihrer external_call_id → Swiftner reichert an, und wenn die Sitzung des Mitarbeiters öffnet, beginnt das Coaching → Ihre Subscriptions call_ended/coaching_report_ready werden ausgelöst → Ihr Flow schreibt die Zusammenfassung zurück in Ihr CRM.

Other docs