Canal personnalisé

Connectez un canal de texte externe à un agent ElevenLabs avec des webhooks

Présentation

Custom Channel connecte un système de messagerie externe à un agent ElevenLabs. Envoyez les messages des utilisateurs à un webhook ElevenLabs, puis recevez les réponses de l’agent sur votre propre endpoint HTTPS.

Custom Channel est en version alpha.
Custom Channel n’est pas disponible pour les agents ou les Workspaces utilisant le mode zéro rétention.

Fonctionnalités

FonctionnalitéPrise en charge
Mode zéro rétention (ZRM)Non pris en charge, indisponible pour les Workspaces et agents ZRM
Pièces jointes dans les messagesNon prises en charge, les messages sont uniquement textuels

Configuration

1

Ouvrir Custom Channel

Ouvrez votre agent, sélectionnez Channels, choisissez Custom Channel, puis cliquez sur Add trigger.

2

Configurer le déclencheur

Sélectionnez une connexion existante ou créez-en une, puis saisissez l’URL du webhook de réponse.

3

Copier les identifiants

Cliquez sur Add, puis copiez l’URL du webhook entrant, le secret entrant et le secret de signature sortant.

4

Configurer votre service

Envoyez les messages des utilisateurs à l’URL du webhook entrant avec le secret entrant dans X-Webhook-Secret. Utilisez le secret de signature sortant pour vérifier chaque réponse.

Envoyer un message

Envoyez une requête POST à l’URL du webhook générée :

POST /v1/convai/api-integrations/custom_channel/triggers/{trigger_connection_id}/async_message
X-Webhook-Secret: <inbound-secret>
Content-Type: application/json
{
"data": {
"type": "user_message",
"text": "Where is my order?",
"user_identifier": "customer_8427"
},
"user_message_id": "msg_01k1e6z3f4t8n9c2",
"dynamic_variables": {
"order_id": "order_72491"
}
}
ChampObligatoireDescription
data.typeOuiDoit être user_message.
data.textOuiMessage utilisateur non vide.
data.user_identifierNonIdentifiant de l’utilisateur externe.
user_message_idOuiClé d’idempotence non vide fournie par votre système.
conversation_idNonIncluez l’ID renvoyé pour poursuivre une conversation. Omettez-le pour en commencer une nouvelle.
dynamic_variablesNonVariables dynamiques fournies à l’agent pour ce tour.

ElevenLabs renvoie 202 Accepted avant de traiter le tour :

{
"conversation_id": "conv_01k1e72d4x8p6v3m",
"status": "queued"
}

Pour poursuivre la conversation, envoyez une autre requête avec ce conversation_id et un nouveau user_message_id.

Recevoir les réponses

ElevenLabs envoie une requête POST à l’URL du webhook de réponse après chaque tour :

{
"version": "1",
"conversation_id": "conv_01k1e72d4x8p6v3m",
"user_message_ids": ["msg_01k1e6z3f4t8n9c2"],
"status": "completed",
"data": [
{
"type": "agent_response",
"event": {
"agent_response": "Your order is scheduled to arrive tomorrow.",
"response_id": "9f2c1a7e-4b3d-4e8a-9c1f-2d6b8e0a5f31",
"event_id": 4
}
},
{
"type": "agent_tool_response",
"event": {
"tool_name": "end_call",
"tool_call_id": "toolu_01k1e70r4b8y",
"tool_type": "system",
"event_id": 4,
"is_called": true,
"is_error": false,
"is_blocked": false,
"status": "success"
}
}
],
"error": null
}

Si le traitement échoue, status est défini sur failed, data sur [] et error contient une description.

data répertorie les événements dans l’ordre des tours. Chaque élément comporte un type et un event :

  • agent_response contient une réponse de l’agent. response_id identifie cette réponse de manière unique, tandis que event_id l’associe à un tour. Concaténez les valeurs agent_response si votre canal affiche une bulle de texte par tour.
  • agent_tool_response signale le résultat d’un outil et partage l’event_id du tour. Son status est success, error, blocked ou skipped. Une réponse avec tool_type: "system", tool_name: "end_call" et status: "success" signifie que l’agent a mis fin à la conversation.

Plusieurs messages entrants peuvent être regroupés en un seul tour. user_message_ids répertorie les ID des messages utilisateur auxquels cette réponse répond.

Vérifier les signatures des réponses

Chaque réponse comprend un en-tête ElevenLabs-Signature :

t=1753876800,v0=<hex-digest>

Le condensat est une signature HMAC-SHA256 sur {timestamp}.{raw_request_body} utilisant le secret de signature sortant. Vérifiez le corps brut avant d’analyser le JSON et rejetez les horodatages obsolètes.

import hashlib
import hmac
import time
def verify_signature(raw_body: bytes, header: str, secret: str) -> None:
values = dict(part.split("=", 1) for part in header.split(","))
timestamp = values["t"]
if abs(time.time() - int(timestamp)) > 30 * 60:
raise ValueError("Stale webhook signature")
expected = hmac.new(
secret.encode(),
timestamp.encode() + b"." + raw_body,
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, values["v0"]):
raise ValueError("Invalid webhook signature")

Comportement de livraison

ElevenLabs effectue trois tentatives de livraison en cours de traitement, environ à 0, 0,5 et 2 secondes. Une réponse 2xx confirme que la livraison a réussi.

La taille des corps de requête est limitée à 256 KiB.