Skip to main content

Eingehende Webhooks

Dynamisches Agenten-Routing — Finn ruft Ihren Server auf, wenn ein eingehender Anruf eintrifft.

6 min read

Eingehender Webhooks

Wenn ein eingehender Anruf eintrifft, kann Finn Ihren Server** in Echtzeit fragen, mit welchem Agenten er antworten soll, welche Variablen injiziert werden sollen und welche Wissensbasis geladen werden soll. Auf diese Weise können Sie dynamisch routen - nach Anrufernummer, Kontoebene, Tageszeit, A / B-Kohorte oder jeder Logik, die Ihrem Backend wichtig ist.

Wenn ein fester Agent genug ist, überspringen Sie dies. Wenn Sie dynamisches Per-Call-Routing wünschen, ist dies die Seite.


Wie es funktioniert

caller dials → Finn answers ring → Finn POSTs to your URL → your server returns agent + vars → Finn streams the voice agent

Der Handschlag fügt ~ 100-200ms Latenz hinzu. Ihr Endpunkt muss in unter 500ms antworten oder Finn fällt auf den Standardagenten zurück.


Konfigurieren

1. Legen Sie die Inbound Webhook URL fest

Dashboard → Einstellungen → Telefonnummern → [Nummer] → Inbound Webhook URL.

Fügen Sie Ihren HTTPS-Endpunkt ein. Save. Finn pingt es einmal mit einem {"ping": true} Körper, um die Erreichbarkeit zu überprüfen.

Über API

curl https://api.hirefinn.ai/v1/phone-numbers/ph_1234 \
  -X PATCH \
  -H "Authorization: Bearer $FINN_API_KEY" \
  -d '{ "inbound_webhook_url": "https://your-app.com/finn/inbound" }'

2. Setzen Sie einen Fallback-Agenten

Konfigurieren Sie einen Standard-Finn für diese Nummer - verwendet, wenn Ihr Webhook ausfällt, Fehler macht oder eine ungültige Antwort zurückgibt.


Nutzlastanforderung

Finn POSTs zu Ihrer URL mit:

{
  "session_id": "ws_2H4abc",
  "request_type": "inbound",
  "phone_number_id": "ph_1234",
  "channel": "pstn",
  "from": {
    "phone": "+919876543210",
    "country": "IN",
    "carrier": "Airtel"
  },
  "to": {
    "phone": "+918765432100",
    "country": "IN"
  },
  "received_at": "2026-05-22T14:30:00Z",
  "metadata": {}
}

Für WhatsApp-Anrufe verwendet der Block from WhatsApp-spezifische Felder:

"from": {
  "wa_id": "919876543210",
  "display_name": "Priya M",
  "profile_pic_url": "https://..."
},
"channel": "whatsapp"

Antwort

Geben Sie einen JSON-Körper innerhalb von 500 ms zurück und beschreiben Sie, wie Sie den Anruf weiterleiten:

{
  "finn_id": "fn_def456",
  "language": "hi-IN",
  "variables": {
    "customer_name": "Priya M",
    "account_tier": "premium",
    "last_order_id": "ord_99831",
    "preferred_agent": "Aria"
  },
  "knowledge_base_ids": ["kb_general", "kb_premium_perks"],
  "metadata": {
    "campaign_tag": "premium-support-q2",
    "ab_cohort": "B"
  },
  "recording_enabled": true,
  "max_call_duration_seconds": 600
}

Feldreferenz

| Erforderlich? | Notizen | |---------- | finn_id | Ja | Welcher Agent antwortet. Muss zu deiner Org gehören | language | Nein | Überschreiben Sie die Standardsprache des Agenten. en-US, hi-IN, es-ES usw. | | variables | Nein | Freiform Key/Value Bag. Verfügbar im Prompt als {variable_name}. | | knowledge_base_ids | Nein | Überschreiben Sie, welche KBs für diesen Aufruf geladen werden. | | metadata | Nein | Angefügt an den Anrufaufzeichnung und Post-Call-Webhook. Verwenden Sie für Ihr eigenes Analytics-Tagging. | | recording_enabled | Nein | Überschreiben Sie den Agent Default. | | max_call_duration_seconds | Nein | Hard Cap. Standard ist 1800 (30 min). |

Ablehnung des Anrufs

{ "action": "reject", "reason": "blocked_caller" }

Finn beendet den Anruf mit einer konfigurierten ausgehenden Nachricht ("Diese Nummer ist nicht mehr in Betrieb"). Verwenden Sie für DNC Durchsetzung, gesperrte Konten oder After-Hours Hangups.

Sofortige Übertragung

{ "action": "transfer", "to": "+918888888888", "reason": "vip_route" }

Überspringen Sie den KI-Agenten vollständig - Route direkt zu einem Menschen. Nützlich für VIP / Eskalationsstufen.


Durchführungsbeispiel (Node)

import express from "express";

const app = express();
app.use(express.json());

app.post("/finn/inbound", async (req, res) => {
  const { from, to, channel } = req.body;

  // 1. Look up caller in CRM (must be fast — DB index by phone)
  const phone = from.phone ?? `+${from.wa_id}`;
  const customer = await crm.findByPhone(phone);

  // 2. Block known DNC
  if (customer?.dnc) {
    return res.json({ action: "reject", reason: "dnc" });
  }

  // 3. VIP → straight to human
  if (customer?.tier === "vip") {
    return res.json({
      action: "transfer",
      to: process.env.VIP_DESK_NUMBER!,
      reason: "vip_route",
    });
  }

  // 4. Localized agent based on caller country
  const language = from.country === "IN" ? "hi-IN" : "en-US";

  // 5. Pick agent + load context
  return res.json({
    finn_id: customer?.tier === "premium"
      ? "fn_premium_aria"
      : "fn_standard_aria",
    language,
    variables: {
      customer_name: customer?.name ?? "there",
      account_tier: customer?.tier ?? "standard",
      last_order_id: customer?.last_order_id ?? "",
    },
    knowledge_base_ids:
      customer?.tier === "premium" ? ["kb_general", "kb_premium"] : ["kb_general"],
    metadata: { ab_cohort: customer?.ab_cohort ?? "A" },
  });
});

app.listen(3000);

Signaturprüfung

Gleiches Schema wie Post-Call-Webhooks - HMAC-SHA256 über den Rohkörper, Header X-Finn-Signature.

const sig = req.headers["x-finn-signature"] as string;
const ok = verifyFinnSignature(rawBody, sig, process.env.FINN_INBOUND_SECRET!);
if (!ok) return res.status(401).send("bad signature");

Siehe Post-Call Webhooks für die vollständige Verifizierungsdurchführung].


Leistungsanforderungen

Dies ist auf dem * heißen Pfad * - der Anrufer hört Klingelton, während er auf Ihre Antwort wartet.

| Metrisch | Ziel | |------- | Reaktionszeit | < 500ms (p99) | | Timeout | 1000ms | | Fallback auf Timeout | Default Agent auf der Telefonnummer konfiguriert | Fallback auf 5xx | Default Agent | Fallback auf ungültiges JSON | Default Agent + Error protokolliert |

Tipps zum Schlagen < 500ms

  • Cache CRM Lookups nach Telefonnummer für 5 Minuten
  • ** Verwenden Sie eine colocated Datenbank ** - Webhook von us-East, DB in us-West = 80ms pro Weg
  • Pre-Compute-Routing-Entscheidungen - Speichern Sie die Antwort auf dem Kundendatensatz, entscheiden Sie nicht live
  • **Skip nicht-essentielle Anreicherung ** auf dem Inbound Hop - schieben Sie diese Arbeit zum Post-Call-Webhook

Caller Prescreening

Die meisten Apps verwenden den Inbound-Webhook für eines dieser Muster:

| Muster | Use Case | |------- | Lookup + personalisieren | Pull Customer Record, Pass Name + Tier als Variablen | | **DNC Durchsetzung ** | Anrufe von blockierten Nummern ablehnen | | **VIP Routing ** | Skip Agent, direkt auf den menschlichen Schreibtisch übertragen | | Spracherkennung | Wählen Sie hi-IN für Indien, en-US für US-Anrufer | | A/B-Tests | Route 50% der Anrufe zu einer neuen Agentenversion | | Nach-Stunden-Routing | Andere Agenten (oder Voicemail) außerhalb der Geschäftszeiten | | Kampagnen-Tracking | Tag-Anrufe von bestimmten Tracking-Nummern mit einer Kampagnen-ID | | Mehrmieter SaaS | Weg zum Mieter, dessen Nummer gewählt wurde |


Prüfung

Verwenden Sie den Finn CLI, um eingehende Anrufe ohne einen echten PSTN-Ring zu simulieren:

finn inbound simulate \
  --phone-number-id ph_1234 \
  --from +919876543210 \
  --webhook-url https://your-app.com/finn/inbound

Die Ausgabe zeigt Ihre Endpunktantwort, Latenz und den aufgelösten Agent + Variablen an. CI-freundlich.


Seeteufel

| Symptom | Fix | |------- | Anrufe fallen immer auf den Standardagenten zurück | Ihr Endpunkt ist > 500ms. Überprüfen sie das webhook-protokoll von Finn für das timing. | Der anrufer hört 2-3 schweigen, bevor der agent spricht ihr endpunkt ist langsam, aber unter timeout. Optimieren Sie auf < 200ms. | | Variablen, die nicht in Agentensprache erscheinen | Mismatch zwischen promptem Platzhalter {customer_name} und Webhook-Schlüssel customerName. Verwenden Sie snake case beide Seiten. | | Falscher Agent antwortete | Ihr Endpunkt gab einen finn_id zurück, der zu einer anderen Organisation gehört. Überprüfe das Eigentum. | | action: reject nicht geehrt | Überprüfen Sie reason ist eine Zeichenfolge, Antwort JSON ist gültig. Ungültige Antworten → Fallback


Was this page helpful?

Still stuck or have feedback?

Email [email protected] or use the chat bubble in the bottom-right corner — it's a Finn that knows the Academy cold.