Canal personalizado

Conecte um canal de texto externo a um agente ElevenLabs com webhooks

Visão geral

O Canal personalizado conecta um sistema de mensagens externo a um agente da ElevenLabs. Envie mensagens de usuários para um webhook da ElevenLabs e receba as respostas do agente no seu próprio endpoint HTTPS.

O Canal personalizado está em alfa.
O Canal personalizado não está disponível para agentes ou espaços de trabalho que usam o modo de retenção zero.

Recursos

RecursoSuporte
Modo de retenção zero (ZRM)Não compatível — indisponível para espaços de trabalho e agentes ZRM
Anexos em mensagensNão compatível — as mensagens contêm apenas texto

Configuração

1

Abrir o Canal personalizado

Abra seu agente, selecione Canais, escolha Canal personalizado e clique em Adicionar gatilho.

2

Configurar o gatilho

Selecione uma conexão existente ou crie uma e insira a URL do webhook de resposta.

3

Copiar as credenciais

Clique em Adicionar e copie a URL do webhook de entrada, o Segredo de entrada e o Segredo de assinatura de saída.

4

Configurar seu serviço

Envie mensagens de usuários para a URL do webhook de entrada com o segredo de entrada em X-Webhook-Secret. Use o segredo de assinatura de saída para verificar cada resposta.

Enviar uma mensagem

Envie uma solicitação POST para a URL do webhook gerada:

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"
}
}
CampoObrigatórioDescrição
data.typeSimDeve ser user_message.
data.textSimMensagem do usuário não vazia.
data.user_identifierNãoIdentificador do usuário externo.
user_message_idSimChave de idempotência não vazia fornecida pelo seu sistema.
conversation_idNãoInclua o ID retornado para continuar uma conversa. Omita-o para iniciar uma nova conversa.
dynamic_variablesNãoVariáveis dinâmicas fornecidas ao agente neste turno.

A ElevenLabs retorna 202 Accepted antes de processar o turno:

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

Para continuar a conversa, envie outra solicitação com esse conversation_id e um novo user_message_id.

Receber respostas

A ElevenLabs envia uma solicitação POST para a URL do webhook de resposta após cada turno:

{
"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
}

Se o processamento falhar, status será failed, data será [] e error conterá uma descrição.

data lista os eventos na ordem dos turnos. Cada item tem um type e um event:

  • agent_response contém uma fala do agente. response_id identifica a fala de forma exclusiva, enquanto event_id a associa a um turno. Una os valores de agent_response se o seu canal exibir uma bolha de texto por turno.
  • agent_tool_response informa o resultado de uma ferramenta e compartilha o event_id do turno. Seu status pode ser success, error, blocked ou skipped. Uma resposta com tool_type: "system", tool_name: "end_call" e status: "success" significa que o agente encerrou a conversa.

Várias mensagens de entrada podem ser agrupadas em um único turno. user_message_ids lista os IDs das mensagens de usuários às quais esta resposta está respondendo.

Verificar assinaturas das respostas

Cada resposta inclui um cabeçalho ElevenLabs-Signature:

t=1753876800,v0=<hex-digest>

O resumo é uma assinatura HMAC-SHA256 sobre {timestamp}.{raw_request_body} usando o segredo de assinatura de saída. Verifique o corpo bruto antes de analisar o JSON e rejeite timestamps antigos.

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")

Comportamento de entrega

A ElevenLabs faz três tentativas de entrega em andamento, aproximadamente aos 0, 0,5 e 2 segundos. Uma resposta 2xx indica que a entrega foi bem-sucedida.

Os corpos das solicitações são limitados a 256 KiB.