Sign inGet Started

Creare una chiamata vocale

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.

Usa POST /v1/voice/calls per chiamare un numero di telefono e avviare una sequenza pubblicata, o una definizione di sequenza inviata con la richiesta, quando il destinatario risponde. La richiesta effettua una chiamata reale; si applicano i normali costi di chiamata.

Anteprima CLI e MCP: Queste interfacce richiedono un client compatibile. Verifica che il server MCP esponga voice_calls_create, oppure esegui bird voice --help per elencare i comandi della tua CLI. Cerca versioni più recenti con bird update --check e consulta Installazione di CLI. Se lo strumento o il comando non è disponibile, usa l'API HTTP o gli SDK.

Nell'anteprima, CLI e MCP preparano la stessa chiamata affinché una persona la esamini e la esegua nel browser. L'agente riceve il risultato di accettazione registrato dopo che la persona esegue la richiesta.

Prima di iniziare

Prepara queste risorse nello stesso spazio di lavoro:

  • Una sequenza da eseguire: una sequenza abilitata, non archiviata, con una pubblicazione attiva creata nella dashboard, oppure una definizione completa inviata con la richiesta.
  • Una chiave API per le richieste HTTP, oppure un login OAuth per CLI e MCP, con entrambe le autorizzazioni voice_management:write e voice:write.
  • Un numero chiamante che lo spazio di lavoro può presentare, ad esempio un caller ID di proprietà o verificato, e un paese di destinazione abilitato. Preferisci un numero nel paese del destinatario: alcune reti mobili rifiutano una chiamata che presenta un caller ID estero.
  • Un destinatario che controlli per la prima chiamata.

L'oggetto sequence accetta esattamente uno tra sequence.id o sequence.definition. Entrambi richiedono anche entry_node_id, lo step Start call da cui inizia la chiamata, e trigger_data, un oggetto conforme allo schema dati di quell'entry. Usa {} quando l'entry accetta dati vuoti. Il riferimento Create Call documenta i limiti della richiesta e il timeout di squillo opzionale.

Chiamare una sequenza creata nella dashboard

Usa sequence.id per eseguire una sequenza che hai creato e pubblicato nella dashboard. Create Call esegue sempre la pubblicazione attiva.

  1. Apri la sequenza in Sequences.
  2. In How to run this sequence, seleziona More details accanto a Create a call.
  3. Se la sequenza ha più entry, scegli il Call trigger da cui partire.
  4. Copia la richiesta. Contiene l'ID della sequenza e l'ID dell'entry.

Salva il corpo della richiesta come call.json, sostituendo i numeri di esempio con i tuoi:

Esempio di codice
{
  "from": "+12025550100",
  "to": "+12025550101",
  "sequence": {
    "id": "YOUR_SEQUENCE_ID",
    "entry_node_id": "YOUR_ENTRY_NODE_ID",
    "trigger_data": {}
  }
}

Compila trigger_data con i campi dichiarati dall'entry, inclusi oggetti annidati e array. Create Call non accetta versioni storiche, bozze o modalità di test. Per testare una bozza salvata, usa i controlli Effettua una chiamata della dashboard.

Eseguire una sequenza inline

Usa sequence.definition per inviare una sequenza completa con la chiamata. Bird la esegue una sola volta senza salvarla, quindi la chiamata non ha un ID di sequenza. Una definizione inline è adatta ai flussi che la tua applicazione genera per ogni chiamata.

Una definizione inline deve superare gli stessi controlli della pubblicazione di una sequenza. La sua esecuzione può eseguire al massimo 16 comandi, inclusi i prompt di raccolta; una chiamata che ne richiede un 17° termina con l'errore di trace call_limit. Il riferimento dei nodi elenca ogni passaggio utilizzabile, con i relativi campi e risultati. Per partire da un flusso funzionante, costruiscilo e pubblicalo nella dashboard, apri la sequenza e seleziona Copy JSON su Definition JSON sotto Published version.

Questo call.json chiede al destinatario di premere 1 per gli orari di apertura o 2 per le indicazioni stradali. Il silenzio e qualsiasi altro tasto terminano l'esecuzione con i rispettivi motivi di uscita:

Esempio di codice
{
  "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": {} }
        }
      ]
    }
  }
}

Il campo connections di ogni nodo mappa un esito al nodo successivo. Il campo matches del menu elenca le scelte disponibili e connections usa gli stessi nomi insieme agli esiti predefiniti timeout e fallback.

Personalizzare una sequenza inline

Dichiara i campi che invii nel campo data_schema dell'entry, poi leggili come trigger.data.<field> in un valore $expr. Questa chiamata saluta il destinatario per nome e conferma o segnala il suo appuntamento:

Esempio di codice
{
  "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" } }
          }
        }
      ]
    }
  }
}

I campi status e reason di ogni uscita distinguono una conferma, una richiesta di assistenza e nessuna risposta. Un oggetto trigger_data che non corrisponde a data_schema non supera la validazione, con la sua posizione indicata in /sequence/trigger_data, e nessuna chiamata viene effettuata.

Inviare la richiesta

Scegli uno dei metodi di richiesta seguenti per il call.json che hai salvato.

Scegli una chiave di idempotenza univoca e nuova per questa chiamata. Conserva la chiave e l'input originale per i tentativi successivi o il recupero della conferma. Scegli un'altra chiave quando intendi effettuare una nuova chiamata separata, dopo aver risolto qualsiasi esito sconosciuto della chiamata originale.

Per gli esempi shell, imposta IDEMPOTENCY_KEY sul valore scelto prima dell'invio. Gli esempi si interrompono se il valore non è impostato o è vuoto; non generano un'altra chiave quando vengono ripetuti.

Per HTTP, imposta BIRD_API_KEY sulla tua chiave e BIRD_API_URL sul relativo URL base regionale, ad esempio https://eu1.platform.bird.com per una chiave eu1, quindi invia la richiesta:

Esempio di codice
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.json

Per l'anteprima di CLI, accedi con entrambe le autorizzazioni in scrittura e prepara la chiamata usando lo stesso file:

Esempio di codice
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}"

Il comando stampa un link di revisione nel browser e attende il completamento. Apri il link, verifica chiamante, destinatario, sequenza e dati dell'entry, quindi esegui la richiesta tu stesso. Preparare la richiesta non effettua la chiamata. Aggiungi --dry-run per ispezionare la richiesta CLI senza creare una conferma. Se la conferma scade, viene annullata o termina senza un risultato registrato, il comando esce con 5; segui la guida ai tentativi successivi prima di effettuare un'altra richiesta.

Per l'anteprima di MCP, chiama voice_calls_create con i campi di call.json e un idempotency_key obbligatorio. Sostituisci <unique-key-for-this-request-reuse-for-retries> con la chiave scelta:

Esempio di codice
{
  "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>"
}

Segui il link di revisione nel browser restituito per eseguire la richiesta. Sull'endpoint dinamico MCP, seleziona voice_calls_create tramite execute. Il consenso OAuth concede le autorizzazioni dello spazio di lavoro; la revisione nel browser esegue questa specifica chiamata.

Una risposta 202 Accepted conferma l'ammissione. La sequenza inizia dopo che il destinatario risponde. Pubblicare una versione più recente dopo l'accettazione non modifica la definizione selezionata né i dati dell'entry di questa chiamata.

Leggere il risultato di accettazione

Conserva id, initial_leg_id e sequence.run_id della risposta per la correlazione. Il campo id di primo livello identifica la chiamata tra le sue leg; initial_leg_id identifica la prima leg.

La risposta è uno snapshot di accettazione immutabile. I campi started_at e ended_at sono null, i booleani di osservazione sono false e parties è vuoto. Questi campi descrivono l'accettazione, quindi non diventano un report di stato in tempo reale quando ripeti la richiesta.

Apri le Runs della sequenza per controllare l'avanzamento. Una chiamata inline non appartiene a nessuna sequenza, quindi segui la sua leg; se fallisce prima che la leg venga registrata, non c'è ancora modo di ispezionarla. Quando esiste un record della leg, usa GET /v1/voice/legs/{leg_id} con initial_leg_id, oppure controlla il registro chiamate. La lettura delle leg richiede il permesso voice:read, incluso in voice:write.

Una leg con status rejected è stata rifiutata prima della connessione, quindi la sua sequenza non è stata eseguita. Senza un motivo di rifiuto, l'estremità remota ha declinato la chiamata; vedi Chiamate rifiutate.

Con CLI, bird voice calls get YOUR_CALL_ID mostra la chiamata e le sue parti. bird voice legs trace YOUR_LEG_ID mostra quali passi sono stati eseguiti, le cifre raccolte a meno che il gather sia privato, e lo stato e il motivo dell'uscita. La traccia è disponibile poco dopo la fine della chiamata; fino a quel momento il comando restituisce un errore, quindi riprovare. La sequenza di un leg rifiutato non è mai stata eseguita, quindi potrebbe non avere traccia.

L'accettazione non garantisce la composizione, una risposta o un record di chiamata leggibile. Una chiamata che fallisce prima della registrazione può comparire nella cronologia delle esecuzioni senza un record di leg. Una chiamata con risposta inoltre non dimostra che la sequenza abbia completato l'operazione di business prevista.

Gestire errori e tentativi successivi

Per le richieste HTTP dirette, l'idempotenza è opzionale. Senza chiave, ogni richiesta accetta un nuovo tentativo di chiamata. Gli SDK generano una chiave per i tentativi automatici. Per proteggere i tentativi successivi tra chiamate separate o richieste HTTP dirette, fornisci una chiave al primo tentativo e riutilizzala con gli stessi byte della richiesta originale. Consulta la guida all'idempotenza.

Una ripetizione identica entro tre ore restituisce l'accettazione originale e Idempotency-Replay: true. Un input modificato con la stessa chiave restituisce 409. Autorizzazione e permessi sul numero chiamante vengono verificati nuovamente in fase di ripetizione. Dopo la finestra di ripetizione, la chiave può ammettere una nuova chiamata: riconcilia il risultato originale prima di reinviare.

Per CLI e MCP, fornisci la chiave di idempotenza al primo tentativo. Ripetere la stessa richiesta e chiave con lo stesso grant OAuth restituisce la conferma esistente finché il relativo record è conservato. Conserva l'input originale e l'ID della conferma. Cambiare la chiave può preparare un'altra chiamata fatturabile.

Se il comando CLI viene interrotto, riprendi con l'input originale, la chiave e l'ID della conferma restituito:

Esempio di codice
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_ID

Per MCP, ripeti gli argomenti originali del tool, incluso lo stesso idempotency_key, insieme allo stato della richiesta restituito. Lo stato identifica la conferma e non sostituisce quegli argomenti. In alternativa, ripeti lo stesso tool e gli stessi argomenti con l'ID restituito nei metadati della richiesta bird/confirmation-id. Con MCP dinamico, ripeti la stessa richiesta execute e inserisci quei metadati. Il ripristino legge la conferma originale e restituisce il risultato registrato al completamento.

Una conferma di Create Call scade dopo 90 minuti. Una conferma pending o expired senza risultato non dimostra che la chiamata non sia mai stata effettuata. Esamina l'esecuzione della sequenza originale e qualsiasi record di leg prima di decidere di effettuare un'altra chiamata; non creare una nuova chiave per risolvere un esito sconosciuto. Una conferma completata con risultato 202 dimostra l'accettazione: procedi con i controlli di accettazione per stabilire l'esito della chiamata.

SintomoCosa verificare
400 o 422Leggi i dettagli dei campi nell'errore. Verifica formato del numero, idoneità e proprietà del numero chiamante, ID di sequenza e di entry, oggetto dati esplicito e limiti della richiesta.
401 o 403Verifica la chiave API o il login OAuth, entrambe le autorizzazioni in scrittura richieste e l'accesso allo spazio di lavoro.
404Verifica che la sequenza appartenga allo spazio di lavoro selezionato e che la creazione di chiamate sia disponibile sul servizio regionale.
409Verifica se si tratta di un tentativo con corpo modificato o di una sequenza di produzione attiva non disponibile. Pubblica o riprendi secondo necessità prima di avviare una nuova chiamata.
429Rispetta le indicazioni sui tentativi nella risposta. Se hai fornito una chiave, riutilizzala per lo stesso tentativo di chiamata.
Accettata, poi fallitaEsamina l'esecuzione e qualsiasi record di leg per destinazione, limiti, saldo o errori di runtime prima di decidere di effettuare un'altra chiamata.

Passaggi successivi

Continua con la documentazione, le guide e gli esempi per questo argomento.