Sign inGet Started

Anwendungsdaten in einer Sprachsequenz verwenden

Verwenden Sie voice.webhook, wenn Ihre Anwendung Daten enthält, die der Anruf benötigt, etwa einen Bestellstatus, ein Team oder eine Terminbestätigung. Der Schritt gibt diese Daten über success zurück, und ein späterer Branch-Schritt wählt anhand dieser Daten den Pfad.

Antwort definieren

Setzen Sie config.output_schema auf ein Objektschema für die zurückgegebenen Daten. Der Schritt hat zwei Ausgänge: success liefert Daten in diesem Schema, und failure behandelt technische Probleme. Ohne Konfiguration ist die Ausgabe ein leeres Objekt.

Die Eingabe enthält eine statische HTTPS url und optionale Objektdaten data. Für die Daten sind ein literales Objekt, $literal oder ein vollständiges Objekt per $expr möglich. Dynamische URLs, eigene Header und Anmeldedaten werden nicht unterstützt.

Anfragen prüfen

Bird signiert jede Anfrage, auch Fortsetzungen, mit dem Callback-Secret Ihres Workspace und verwendet dafür Standard Webhooks-Header: webhook-id, webhook-timestamp und webhook-signature. Die Signatur deckt die ID, den Zeitstempel und den exakten Body ab. In den 24 Stunden nach einer Rotation des Secrets enthält webhook-signature pro aktivem Secret einen v1,-Eintrag, sodass jedes der beiden Secrets die Prüfung besteht. Es kann etwa eine Minute dauern, bis Anrufe mit dem neuen Secret signieren. Akzeptieren Sie das vorherige Secret daher weiter, bis die Überlappung endet. Ihre Antwort wird nicht signiert: Bird prüft das TLS-Zertifikat Ihres Empfängers, und die HTTPS-Verbindung authentifiziert, was er zurückgibt.

Prüfen Sie die Header vor dem Parsen über den unveränderten Body mit der Verify-Funktion einer Standard-Webhooks-Bibliothek. webhooks.unwrap in den SDKs parst Plattformereignisse und ist nicht für diese Anfragen gedacht. Rotieren Sie das Secret zuerst unter Webhooks → Direct callbacks, da das ursprüngliche Secret nie angezeigt wird. Die Signatur belegt, dass jemand mit Ihrem Workspace-Secret die Anfrage signiert hat. Ihre SMS-Callback-Empfänger haben dasselbe Secret und können ebenfalls signieren. Hinterlegen Sie es daher nur auf Empfängern, denen Sie vertrauen. Wer die Sequenzen des Workspace bearbeiten darf, legt die URL und data fest. Prüfen Sie, ob target_url Ihre eigene URL ist, damit Sie eine Anfrage ablehnen, die Bird für einen anderen Empfänger signiert hat, und autorisieren Sie geschäftliche Aktionen in Ihrem Empfänger. Die Autorisierung des Kunden wird nie weitergeleitet.

Webhook-Anfragen von Sequenzen legen kein Client-Zertifikat vor, auch wenn Ihr Workspace mTLS erzwingt. Konfigurieren Sie den Empfänger so, dass er Verbindungen ohne Client-Zertifikat annimmt, und authentifizieren Sie stattdessen die signierte Anfrage.

Vergleichen Sie den signierten webhook-timestamp, einen Unix-Zeitstempel in Sekunden, mit einer synchronisierten Serveruhr. Lehnen Sie Anfragen ab, die mehr als fünf Minuten in der Vergangenheit oder Zukunft liegen. Deduplizieren Sie anhand von webhook-id, bevor Sie Nebeneffekte auslösen. Speichern Sie ID und Ergebnis nach Möglichkeit atomar zusammen mit der Aktion, und geben Sie bei einer wiederholten Anfrage das gespeicherte Ergebnis zurück. Jede Fortsetzung hat eine eigene ID. Verwenden Sie einen separaten geschäftlichen Idempotenzschlüssel, wenn verschiedene Anfragen dieselbe Aktion nicht wiederholen dürfen.

Daten zurückgeben

Der Empfänger gibt diese geschlossene Antwortstruktur zurück:

Codebeispiel
{
  "schema_version": 1,
  "type": "outcome",
  "output": { "status": "confirmed", "message": "Your appointment is confirmed." }
}

output muss dem konfigurierten Schema entsprechen. Die Antwort liefert Daten, keinen Port, keine Knoten-ID und keine neuen Befehle. Eine Fortsetzung ist {"schema_version":1,"type":"continue","url":"https://example.com/voice/next"} auf dem kanonischen Origin der ursprünglichen URL.

Um anhand der Daten zu verzweigen, verbinden Sie success mit einem logic.branch-Schritt mit Fällen wie steps.decision.output.status == 'confirmed'. Deklarieren Sie das Feld im Schema als String-enum, damit der Empfänger nur diese Werte zurückgeben kann.

Die Anfrage enthält die Identität von Run, Session und Anruf, die Identität der zugelassenen Sequenz und des Knotens, Ihr materialisiertes data sowie results. Legen Sie geschäftliche Eingaben in data ab. Ein direktes privates Gather-Ergebnis kann einmal in results erscheinen, und abgeschlossene Aufnahmen enthalten eine ID, sofern verfügbar. Diese Beobachtungen sind nicht automatisch als Ausdrucksfelder verfügbar.

Die Anfrage an den Empfänger lesen

Ein Testlauf eines Entwurfs sendet diese Struktur. Die IDs und Zeitstempel unten sind fiktiv. Die tatsächliche Anfrage verwendet den zugelassenen Run und das aktuelle Vorkommen des Knotens:

Codebeispiel
{
  "schema_version": 1,
  "method": "POST",
  "target_url": "https://example.com/decision",
  "run_id": "vsr_01k5yb7p000000000000000000",
  "sequence": {
    "id": "vsq_01k5yb7p000000000000000000",
    "version_id": null,
    "draft_revision": 1,
    "entry_node_id": "start",
    "mode": "test"
  },
  "session_id": "vcs_01k5yb7p000000000000000000",
  "call": { "id": "vcl_01k5yb7p000000000000000000", "orig": null, "dest": null },
  "node": { "id": "decision", "occurrence_id": "00000000-0000-4000-8000-000000000001" },
  "data": { "appointment_id": "appointment_123" },
  "results": []
}

Bei einem veröffentlichten Run identifiziert version_id die ausgewählte Version, und draft_revision ist null. Bei einem Anruf, der eine Inline-Definition ausgeführt hat, sind id, version_id und draft_revision alle null. mode kann test oder production sein. Ursprung und Ziel verwenden nullbare Objekte für Anrufbeteiligte. Prüfen Sie die Signatur, bevor Sie diesen Identitätsfeldern vertrauen.

Eine Gather-Beobachtung in results enthält type: "gather", node_id, die UUID command_id, digits und reason. Eine Aufnahme-Beobachtung enthält type: "recording", die UUID command_id, state und, sofern verfügbar, eine recording_id. Verwenden Sie private Ziffern nur für die vorgesehene Anfrage. Sie werden nicht zu gespeicherten Ausdrucksausgaben. Fortsetzungsanfragen behalten dasselbe Vorkommen des Knotens bei, wobei bereits zugestellte Beobachtungen aus results entfernt sind.

Fehler behandeln

Ein technisches Ergebnis verwendet den Port failure mit {"code":"webhook_unavailable"} oder {"code":"webhook_invalid_response"}. Ist dieser Port verbunden, folgt der Run dem Wiederherstellungspfad. Ist er nicht verbunden, schlägt der Run fehl. Ein nicht verbundenes success beendet den Run regulär. Live-Webhook-Anfragen haben eine Frist von drei Sekunden und werden nicht automatisch erneut versucht. Die Vorschau sendet keine Anfrage.

Die Frist von drei Sekunden schließt das Lesen des Signaturgeheimnisses ein. Verbinden Sie failure mit einem Wiederherstellungspfad, damit der Anruf weiterlaufen kann, wenn der Empfänger nicht erreichbar ist oder eine ungültige Antwort zurückgibt. Eine Anfrage mit Zeitüberschreitung kann beim Empfänger bereits eine Aktion ausgelöst haben.

Behandeln Sie data, die Anrufidentität und Gather-Ziffern als privat. Beschränken Sie den Zugriff auf den Empfänger und das Geheimnis, protokollieren Sie keine Bodys oder Geheimnisse, und speichern Sie Eingaben von Anrufern nur so lange, wie Ihre Anwendung sie benötigt. Setzen Sie keine privaten Daten oder Zugangsdaten in URLs, denn der Anruf-Trace speichert die vollständige URL einschließlich des Querystrings. Die erstellte URL, die erstellten Daten und die validierte Ausgabe werden im Run-Verlauf gespeichert. Flüchtige Gather-Ziffern sind von der erfassten Schritteingabe ausgenommen. Geben Sie nur Daten zurück, die die Sequenz benötigt.

Lesen Sie zurückgegebene Daten unter steps.decision.output und technische Fehler unter steps.decision.error.code. Wenn beide Pfade zusammenlaufen, prüfen Sie den Wrapper mit has(steps.decision.output) oder has(steps.decision.error), bevor Sie ihn verwenden. Ein HTTP 200 von Ihrem Empfänger bedeutet erst dann ein gültiges Ergebnis, wenn sein Body den Vertrag erfüllt.

Weiter mit der Dokumentation, Anleitungen und Beispielen zu diesem Thema.