---
title: "Utiliser les données d’une application dans une séquence vocale"
description: "Demandez des données typées à un récepteur HTTPS pendant un appel, créez une branche selon ces données dans une étape ultérieure, gérez explicitement les échecs techniques et séparez les réponses privées des données d’appel conservées."
canonical: "https://bird.com/fr-fr/documentation/guides/voice/sequences/code/webhooks"
---

# Utiliser les données d’une application dans une séquence vocale

Utilisez `voice.webhook` lorsque votre application détient des données dont l’appel a besoin : l’état d’une commande, une équipe ou la confirmation d’un rendez-vous. L’étape renvoie ces données sur `success`, puis une étape Branch ultérieure choisit le chemin à partir de celles-ci.

## Définir la réponse

Définissez `config.output_schema` sur un schéma d’objet pour les données renvoyées. L’étape a deux sorties : `success` transporte des données conformes à ce schéma et `failure` gère les problèmes techniques. Sans configuration, la sortie est un objet vide.

L’entrée contient une `url` HTTPS statique et un objet `data` facultatif. Les données acceptent un objet littéral, `$literal` ou un `$expr` portant sur l’objet entier. Les URL dynamiques, les en-têtes personnalisés et les identifiants ne sont pas pris en charge.

## Vérifier les requêtes

Bird signe chaque requête, continuations comprises, avec le secret de rappel de votre espace de travail au moyen d’en-têtes [Standard Webhooks](https://www.standardwebhooks.com/) : `webhook-id`, `webhook-timestamp` et `webhook-signature`. La signature couvre l’ID, l’horodatage et le corps exact. Pendant les 24 heures qui suivent une rotation du secret, `webhook-signature` contient une entrée `v1,` par secret actif, si bien que l’un ou l’autre secret permet la vérification. Les appels peuvent mettre environ une minute à signer avec le nouveau secret : continuez donc d’accepter l’ancien jusqu’à la fin de la période de chevauchement. Votre réponse n’est pas signée : Bird valide le certificat TLS de votre récepteur, et la connexion HTTPS authentifie ce qu’il renvoie.

Vérifiez les en-têtes sur le corps brut avec l’appel verify d’une bibliothèque Standard Webhooks avant toute analyse. La méthode `webhooks.unwrap` des SDK analyse les événements de la plateforme et ne convient pas à ces requêtes. Faites d’abord une rotation du secret sous **Webhooks → Direct callbacks**, car le secret initial n’est jamais affiché. La signature prouve qu’un détenteur du secret de votre espace de travail a signé la requête. Vos récepteurs de rappel SMS détiennent le même secret et peuvent aussi signer : ne le confiez donc qu’à des récepteurs de confiance. Toute personne autorisée à modifier les séquences de l’espace de travail choisit l’URL et `data`. Vérifiez que `target_url` correspond à votre propre URL afin de refuser une requête Bird signée pour un autre récepteur, et autorisez les actions métier dans votre récepteur. L’autorisation du client n’est jamais transmise.

Les requêtes webhook des séquences ne présentent pas de certificat client, même lorsque votre espace de travail impose le mTLS. Configurez le récepteur pour qu’il accepte une connexion sans certificat client et authentifiez plutôt la requête signée.

Comparez le `webhook-timestamp` signé, un horodatage Unix en secondes, à l’horloge synchronisée d’un serveur. Rejetez les requêtes datées de plus de cinq minutes dans le passé ou dans le futur. Dédupliquez sur `webhook-id` avant d’exécuter des effets de bord. Si possible, enregistrez l’ID et le résultat de façon atomique avec l’action, puis renvoyez le résultat enregistré pour une requête répétée. Chaque continuation possède son propre ID. Utilisez une clé d’idempotence métier distincte si des requêtes différentes ne doivent pas répéter la même action.

## Renvoyer des données

Le récepteur renvoie une réponse de forme fermée :

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

`output` doit correspondre au schéma configuré. La réponse renvoie des données, et non un port, un ID de nœud ou de nouvelles commandes. Une continuation est `{"schema_version":1,"type":"continue","url":"https://example.com/voice/next"}` sur l’origine canonique de l’URL d’origine.

Pour router selon les données, connectez `success` à une étape `logic.branch` avec des cas tels que `steps.decision.output.status == 'confirmed'`. Déclarez le champ comme une chaîne `enum` dans le schéma afin que le récepteur ne puisse renvoyer que ces valeurs.

La requête contient l’identité de l’exécution, de la session et de l’appel, l’identité de la séquence admise et du nœud, votre `data` matérialisé et `results`. Placez les entrées métier dans `data`. Un résultat Gather privé direct peut apparaître une seule fois dans `results`, et les enregistrements finalisés portent un ID lorsqu’il est disponible. Ces observations ne deviennent pas automatiquement des champs d’expression.

## Lire la requête reçue par le récepteur

Une exécution de test d’un brouillon envoie cette structure. Les ID et horodatages ci-dessous sont fictifs. La requête réelle utilise l’exécution admise et l’occurrence actuelle du nœud :

```json
{
  "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": []
}
```

Pour une exécution publiée, `version_id` identifie la version sélectionnée et `draft_revision` vaut null. Pour un appel qui a exécuté une [définition inline](/docs/guides/voice/create-calls), `id`, `version_id` et `draft_revision` valent tous null. `mode` peut valoir `test` ou `production`. L’origine et la destination utilisent des objets de partie d’appel pouvant être null. Vérifiez la signature avant de vous fier à ces champs d’identité.

Une observation Gather dans `results` contient `type: "gather"`, `node_id`, l’UUID `command_id`, `digits` et `reason`. Une observation d’enregistrement contient `type: "recording"`, l’UUID `command_id`, `state` et un `recording_id` lorsqu’il est disponible. Utilisez les chiffres privés uniquement pour la requête prévue : ils ne deviennent pas des sorties d’expression conservées. Les requêtes de continuation conservent la même occurrence de nœud, et les observations déjà transmises sont retirées de `results`.

## Gérer les échecs

Un échantillon technique utilise le port `failure` avec `{"code":"webhook_unavailable"}` ou `{"code":"webhook_invalid_response"}`. Un échec connecté suit le chemin de reprise, tandis qu’un échec non connecté fait échouer l’exécution. Un `success` non connecté termine l’exécution normalement. Les requêtes webhook réelles ont un délai de trois secondes et ne font l’objet d’aucune nouvelle tentative automatique. L’aperçu n’envoie aucune requête.

Le délai de trois secondes inclut la lecture du secret de signature. Connectez `failure` à un chemin de reprise pour que l’appel puisse continuer lorsque le récepteur est indisponible ou renvoie une réponse invalide. Une requête expirée peut déjà avoir déclenché un effet de bord chez le récepteur.

Traitez `data`, l’identité de l’appel et les chiffres Gather comme des données privées. Restreignez l’accès au récepteur et au secret, évitez de journaliser les corps de requête ou les secrets, et ne conservez les saisies de l’appelant que le temps nécessaire à votre application. Ne placez ni données privées ni identifiants dans les URL : la trace de l’appel conserve l’URL complète, y compris sa chaîne de requête. L’URL et les données configurées ainsi que la sortie validée sont conservées dans l’historique d’exécution. Les chiffres Gather transitoires sont exclus de l’entrée d’étape capturée. Ne renvoyez que les données dont la séquence a besoin.

Lisez les données renvoyées dans `steps.decision.output` et les erreurs techniques dans `steps.decision.error.code`. Si les deux chemins se rejoignent, vérifiez l’enveloppe avec `has(steps.decision.output)` ou `has(steps.decision.error)` avant de l’utiliser. Un HTTP 200 renvoyé par votre récepteur ne garantit pas un résultat valide tant que son corps ne respecte pas le contrat.

## Related resources

- [Voice sequences](/docs/guides/voice/sequence-builder) (docs)
