Criar uma chamada de voz
Warning: Voice sequences are in preview. Steps, entry data, and the sequence definition format can change in ways that break existing sequences and API requests.
Use POST /v1/voice/calls para ligar para um número de telefone e iniciar uma sequência publicada, ou uma definição de sequência enviada com a solicitação, quando o destinatário atender. A solicitação realiza uma chamada real; as tarifas normais de chamada se aplicam.
Prévia de CLI e MCP: Estas interfaces exigem um cliente compatível. Verifique se o servidor MCP disponibiliza voice_calls_create, ou execute bird voice --help para listar os comandos da sua CLI. Verifique se há versões mais recentes com bird update --check e consulte Instalação da CLI. Se a ferramenta ou o comando não estiver disponível, use a API HTTP ou os SDKs.
No preview, CLI e MCP preparam a mesma chamada para uma pessoa revisar e executar no navegador. O agente recebe o resultado de aceitação registrado depois que a pessoa executa a solicitação.
Antes de começar
Prepare estes recursos no mesmo espaço de trabalho:
- Uma sequência para executar: uma sequência habilitada e não arquivada com uma publicação ativa criada no painel, ou uma definição completa enviada com a solicitação.
- Uma chave API para solicitações HTTP, ou um login OAuth para CLI e MCP, com ambas as permissões
voice_management:writeevoice:write. - Um número de chamada que o espaço de trabalho pode apresentar, como um caller ID próprio ou verificado, e um país de destino habilitado. Prefira um número do país do destinatário: algumas redes móveis recusam uma chamada que apresenta um caller ID estrangeiro.
- Um destinatário que você controla para a primeira chamada.
O objeto sequence aceita exatamente um entre sequence.id ou sequence.definition. Ambos também precisam de entry_node_id, o passo Start call em que a chamada começa, e trigger_data, um objeto correspondente ao esquema de dados dessa entrada. Use {} quando a entrada aceitar dados vazios. A referência do Create Call documenta os limites de solicitação e o tempo limite de toque opcional.
Chamar uma sequência criada no painel
Use sequence.id para executar uma sequência que você criou e publicou no painel. Create Call sempre executa a publicação ativa.
- Abra a sequência em Sequences.
- Em How to run this sequence, selecione More details ao lado de Create a call.
- Se a sequência tem várias entradas, escolha o Call trigger para iniciar.
- Copie a solicitação. Ela contém o ID da sequência e o ID de entrada.
Salve o corpo da solicitação como call.json, substituindo os números de exemplo pelos seus:
{
"from": "+12025550100",
"to": "+12025550101",
"sequence": {
"id": "YOUR_SEQUENCE_ID",
"entry_node_id": "YOUR_ENTRY_NODE_ID",
"trigger_data": {}
}
}Preencha trigger_data com os campos que a entrada declara, incluindo objetos e arrays aninhados. Create Call não aceita versões históricas, rascunhos nem modo de teste. Para testar um rascunho salvo, use os controles Fazer uma chamada do painel.
Executar uma sequência inline
Use sequence.definition para enviar uma sequência completa com a chamada. Bird a executa uma vez e não a salva, então a chamada não tem ID de sequência. Uma definição inline é adequada para fluxos que sua aplicação gera por chamada.
Uma definição inline deve passar pelas mesmas verificações que a publicação de uma sequência. Sua execução pode rodar no máximo 16 comandos, incluindo prompts de coleta; uma chamada que precisar de um 17º termina com o erro de trace call_limit. A referência de nós lista cada etapa disponível, com seus campos e resultados. Para partir de um fluxo funcional, construa e publique-o no dashboard, abra a sequência e selecione Copy JSON em Definition JSON sob Published version.
Este call.json pede ao destinatário que pressione 1 para horário de funcionamento ou 2 para direções. Silêncio e qualquer outra tecla encerram a execução com seus próprios motivos de saída:
{
"from": "+12025550100",
"to": "+12025550101",
"sequence": {
"entry_node_id": "start",
"trigger_data": {},
"definition": {
"schema_version": 1,
"expression_environment": "bird.cel.v1",
"nodes": [
{
"id": "start",
"type": "trigger.start_call",
"type_version": 1,
"config": {},
"input": {},
"connections": { "event": { "node_id": "menu", "port": "input" } }
},
{
"id": "menu",
"type": "voice.gather",
"type_version": 1,
"config": {},
"input": {
"prompts": [
{
"type": "say",
"text": "Press 1 for opening hours, or 2 for directions.",
"language": "en"
}
],
"max_digits": 1,
"timeout_seconds": 5,
"inter_digit_timeout_seconds": 2,
"finish_on_key": "#",
"private": false,
"matches": { "hours": "1", "directions": "2" }
},
"connections": {
"hours": { "node_id": "hours", "port": "input" },
"directions": { "node_id": "directions", "port": "input" },
"timeout": { "node_id": "no_input", "port": "input" },
"fallback": { "node_id": "other_input", "port": "input" }
}
},
{
"id": "hours",
"type": "voice.say",
"type_version": 1,
"config": {},
"input": { "text": "We are open Monday through Friday, nine to five.", "language": "en" },
"connections": { "next": { "node_id": "done", "port": "input" } }
},
{
"id": "directions",
"type": "voice.say",
"type_version": 1,
"config": {},
"input": {
"text": "Find directions on your appointment confirmation.",
"language": "en"
},
"connections": { "next": { "node_id": "done", "port": "input" } }
},
{
"id": "done",
"type": "logic.exit",
"type_version": 1,
"config": { "status": "succeeded", "reason": "information_played" },
"input": { "output": {} }
},
{
"id": "no_input",
"type": "logic.exit",
"type_version": 1,
"config": { "status": "succeeded", "reason": "no_input" },
"input": { "output": {} }
},
{
"id": "other_input",
"type": "logic.exit",
"type_version": 1,
"config": { "status": "succeeded", "reason": "unrecognized_input" },
"input": { "output": {} }
}
]
}
}
}O connections de cada nó mapeia um resultado para o próximo nó. O matches do menu nomeia suas opções, e connections usa os mesmos nomes junto com os resultados integrados timeout e fallback.
Personalizar uma sequência inline
Declare os campos que você envia no data_schema da entrada e leia-os como trigger.data.<field> em um valor $expr. Esta chamada cumprimenta o destinatário pelo nome e confirma ou sinaliza o compromisso:
{
"from": "+12025550100",
"to": "+12025550101",
"sequence": {
"entry_node_id": "start",
"trigger_data": {
"appointment_id": "apt_2048",
"customer_name": "Sam",
"appointment_time": "Tuesday at 10 AM"
},
"definition": {
"schema_version": 1,
"expression_environment": "bird.cel.v1",
"nodes": [
{
"id": "start",
"type": "trigger.start_call",
"type_version": 1,
"config": {
"data_schema": {
"type": "object",
"additionalProperties": false,
"required": ["appointment_id", "customer_name", "appointment_time"],
"properties": {
"appointment_id": { "type": "string", "minLength": 1 },
"customer_name": { "type": "string", "minLength": 1 },
"appointment_time": { "type": "string", "minLength": 1 }
}
}
},
"input": {},
"connections": { "event": { "node_id": "confirm_menu", "port": "input" } }
},
{
"id": "confirm_menu",
"type": "voice.gather",
"type_version": 1,
"config": {},
"input": {
"prompts": [
{
"type": "say",
"text": {
"$template": [
"Hello ",
{ "$expr": "trigger.data.customer_name" },
". Press 1 to confirm your appointment on ",
{ "$expr": "trigger.data.appointment_time" },
", or 2 if you need help."
]
},
"language": "en"
}
],
"max_digits": 1,
"timeout_seconds": 7,
"inter_digit_timeout_seconds": 2,
"finish_on_key": null,
"private": false,
"matches": { "confirm": "1", "help": "2" }
},
"connections": {
"confirm": { "node_id": "confirmed", "port": "input" },
"help": { "node_id": "help_requested", "port": "input" },
"timeout": { "node_id": "no_response", "port": "input" },
"fallback": { "node_id": "no_response", "port": "input" }
}
},
{
"id": "confirmed",
"type": "logic.exit",
"type_version": 1,
"config": { "status": "succeeded", "reason": "appointment_confirmed" },
"input": {
"output": { "appointment_id": { "$expr": "trigger.data.appointment_id" } }
}
},
{
"id": "help_requested",
"type": "logic.exit",
"type_version": 1,
"config": { "status": "succeeded", "reason": "appointment_help_requested" },
"input": {
"output": { "appointment_id": { "$expr": "trigger.data.appointment_id" } }
}
},
{
"id": "no_response",
"type": "logic.exit",
"type_version": 1,
"config": { "status": "failed", "reason": "appointment_no_response" },
"input": {
"output": { "appointment_id": { "$expr": "trigger.data.appointment_id" } }
}
}
]
}
}
}O status e o reason de cada saída separam uma confirmação, um pedido de ajuda e a ausência de resposta. Um objeto trigger_data que não corresponde a data_schema falha na validação, com sua localização em /sequence/trigger_data, e nenhuma chamada é feita.
Enviar a solicitação
Escolha um método de solicitação abaixo para o call.json que você salvou.
Escolha uma chave de idempotência única e nova uma vez para esta chamada pretendida. Mantenha essa chave e a entrada original para novas tentativas ou recuperação de confirmação. Escolha outra chave quando pretender fazer uma nova chamada separada, após resolver qualquer resultado desconhecido da chamada original.
Para os exemplos de shell, defina IDEMPOTENCY_KEY com o valor escolhido antes de enviar. Os exemplos param se a variável estiver indefinida ou vazia; eles não geram outra chave quando repetidos.
Para HTTP, defina BIRD_API_KEY com sua chave e BIRD_API_URL com a URL base regional correspondente, como https://eu1.platform.bird.com para uma chave eu1, e então envie a solicitação:
curl --request POST "$BIRD_API_URL/v1/voice/calls" \
--header "Authorization: Bearer $BIRD_API_KEY" \
--header 'Content-Type: application/json' \
--header "Idempotency-Key: ${IDEMPOTENCY_KEY:?Set IDEMPOTENCY_KEY to the saved key for this intended call}" \
--data-binary @call.jsonPara o preview de CLI, faça login com ambas as permissões de escrita e prepare a chamada usando o mesmo arquivo:
bird auth login --scope voice_management:write --scope voice:write
bird voice calls create --body-file call.json \
--idempotency-key "${IDEMPOTENCY_KEY:?Set IDEMPOTENCY_KEY to the saved key for this intended call}"O comando imprime um link de revisão no navegador e aguarda a conclusão. Abra o link, verifique o chamador, o destinatário, a sequência e os dados de entrada, e execute a solicitação você mesmo. Preparar a solicitação não faz a chamada. Adicione --dry-run para inspecionar a solicitação CLI sem criar uma confirmação. Se a confirmação expirar, for cancelada ou terminar sem um resultado registrado, o comando encerra com 5; siga a orientação de nova tentativa antes de fazer outra solicitação.
Para o preview de MCP, chame voice_calls_create com os campos de call.json e um idempotency_key obrigatório. Substitua <unique-key-for-this-request-reuse-for-retries> pela chave escolhida:
{
"from": "+12025550100",
"to": "+12025550101",
"sequence": {
"id": "YOUR_SEQUENCE_ID",
"entry_node_id": "YOUR_ENTRY_NODE_ID",
"trigger_data": {}
},
"idempotency_key": "<unique-key-for-this-request-reuse-for-retries>"
}Siga o link de revisão no navegador retornado para executar a solicitação. No endpoint dinâmico MCP, selecione voice_calls_create por meio de execute. O consentimento OAuth concede permissões do espaço de trabalho; a revisão no navegador executa esta chamada específica.
Uma resposta 202 Accepted confirma a admissão. A sequência começa depois que o destinatário atende. Publicar uma versão mais recente após a aceitação não altera a definição selecionada nem os dados de entrada desta chamada.
Ler o resultado da aceitação
Guarde id, initial_leg_id e sequence.run_id da resposta para correlação. O id de nível superior identifica a chamada em todas as suas pernas; initial_leg_id identifica a primeira perna.
A resposta é um snapshot imutável de aceitação. Seus campos started_at e ended_at são null, os booleanos de observação são false e parties está vazio. Esses campos descrevem a aceitação, portanto não se tornam um relatório de status em tempo real quando você reenvia a solicitação.
Abra Runs da sequência para inspecionar o progresso. Uma chamada inline não pertence a nenhuma sequência, então acompanhe seu leg; se ela falhar antes de o leg ser registrado, ainda não há como inspecioná-la. Quando um registro de leg existir, use GET /v1/voice/legs/{leg_id} com initial_leg_id, ou inspecione o registro de chamadas. A leitura de legs requer a permissão voice:read, que voice:write inclui.
Um leg com status rejected foi recusado antes de conectar, então sua sequência não foi executada. Sem um motivo de rejeição, o lado remoto recusou a chamada; consulte Chamadas rejeitadas.
Com o CLI, bird voice calls get YOUR_CALL_ID mostra a chamada e suas partes. bird voice legs trace YOUR_LEG_ID mostra quais etapas foram executadas, os dígitos coletados (a menos que o gather seja privado) e o status e motivo da saída. O trace fica pronto logo após o fim da chamada; até lá o comando retorna um erro, então tente novamente. A sequência de um leg rejeitado nunca foi executada, então pode não ter trace.
A aceitação não garante discagem, atendimento nem um registro de chamada legível. Uma chamada que falha antes do registro pode aparecer no histórico de execução sem um registro de perna. Uma chamada atendida também não comprova que a sequência concluiu a tarefa de negócio pretendida.
Tratar erros e novas tentativas
Para solicitações HTTP diretas, a idempotência é opcional. Sem uma chave, cada solicitação aceita uma nova tentativa de chamada. Os SDKs geram uma chave para novas tentativas automáticas. Para proteger novas tentativas em chamadas separadas ou solicitações HTTP diretas, forneça uma chave na primeira tentativa e reutilize-a com os bytes exatos da solicitação original. Consulte o guia de idempotência.
Uma repetição idêntica dentro de três horas retorna a aceitação original e Idempotency-Replay: true. Entrada alterada com essa chave retorna 409. Autorização e permissão de número de chamada são verificadas novamente na repetição. Após a janela de repetição, a chave pode admitir uma nova chamada, então concilie o resultado original antes de reenviar.
Para CLI e MCP, forneça a chave de idempotência na primeira tentativa. Repetir a mesma solicitação e chave com a mesma concessão OAuth retorna a confirmação existente enquanto seu registro é mantido. Mantenha a entrada original e o ID de confirmação. Alterar a chave pode preparar outra chamada faturável.
Se o comando CLI for interrompido, retome com a entrada original, a chave e o ID de confirmação retornado:
bird voice calls create --body-file call.json \
--idempotency-key "${IDEMPOTENCY_KEY:?Set IDEMPOTENCY_KEY to the saved key for this intended call}" \
--confirmation-id YOUR_CONFIRMATION_IDPara MCP, repita os argumentos originais da ferramenta, incluindo o mesmo idempotency_key, junto com o estado de solicitação retornado. O estado identifica a confirmação e não substitui esses argumentos. Como alternativa, repita a mesma ferramenta e argumentos com o ID retornado nos metadados de solicitação bird/confirmation-id. Com MCP dinâmico, repita a mesma solicitação execute e inclua esses metadados nela. Retomar lê a confirmação original e retorna o resultado registrado quando concluído.
Uma confirmação de Create Call expira após 90 minutos. Uma confirmação pending ou expired sem resultado não prova que a chamada nunca foi feita. Inspecione a execução da sequência original e qualquer registro de perna de chamada antes de decidir fazer outra chamada; não crie uma chave nova para resolver um resultado desconhecido. Uma confirmação concluída com resultado 202 prova a aceitação, então prossiga com as verificações de aceitação para determinar o resultado da chamada.
| Sintoma | O que verificar |
|---|---|
400 ou 422 | Leia os detalhes de campo do erro. Verifique o formato do número, a elegibilidade e a propriedade do número de chamada, os IDs de sequência e entrada, o objeto de dados explícito e os limites da solicitação. |
401 ou 403 | Verifique sua chave API ou login OAuth, ambas as permissões de escrita obrigatórias e o acesso ao espaço de trabalho. |
404 | Verifique se a sequência pertence ao espaço de trabalho selecionado e se a criação de chamadas está disponível no serviço regional. |
409 | Verifique se houve uma nova tentativa com corpo alterado ou se a sequência ativa de produção está indisponível. Publique ou retome conforme necessário antes de iniciar uma nova chamada. |
429 | Respeite a orientação de nova tentativa da resposta. Se você forneceu uma chave, reutilize-a para a mesma tentativa de chamada. |
| Aceita, depois falhou | Inspecione a execução e qualquer registro de perna em busca de destino, limites, saldo ou falhas de runtime antes de decidir fazer outra chamada. |
Próximos passos
Recursos relacionados
Continue com a documentação, guias e exemplos sobre este tópico.