Sign inGet Started

Membuat panggilan suara

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.

Gunakan POST /v1/voice/calls untuk menelepon nomor telepon dan memulai sequence yang dipublikasikan, atau definisi sequence yang dikirim bersama permintaan, saat penerima mengangkat. Permintaan ini melakukan panggilan nyata; biaya panggilan normal berlaku.

Pratinjau CLI dan MCP: Antarmuka ini memerlukan klien yang kompatibel. Pastikan server MCP Anda menyediakan voice_calls_create, atau jalankan bird voice --help untuk menampilkan perintah di CLI Anda. Periksa rilis yang lebih baru dengan bird update --check dan lihat Instalasi CLI. Jika tool atau perintah tidak tersedia, gunakan API HTTP atau SDK.

Dalam pratinjau, CLI dan MCP menyiapkan panggilan yang sama agar seseorang dapat meninjau dan menjalankannya di browser. Agen menerima hasil penerimaan yang tercatat setelah orang tersebut menjalankan permintaan.

Sebelum Anda mulai

Siapkan sumber daya berikut di workspace yang sama:

  • Sequence yang akan dijalankan: sequence yang aktif dan tidak diarsipkan dengan publikasi aktif yang dibuat di dashboard, atau definisi lengkap yang dikirim bersama permintaan.
  • Kunci API untuk permintaan HTTP, atau login OAuth untuk CLI dan MCP, dengan izin voice_management:write dan voice:write.
  • Nomor pemanggil yang boleh ditampilkan workspace, seperti caller ID milik sendiri atau terverifikasi, dan negara tujuan yang diaktifkan. Gunakan nomor di negara penerima: beberapa jaringan seluler menolak panggilan yang menampilkan caller ID asing.
  • Penerima yang Anda kontrol untuk panggilan pertama.

Objek sequence menerima tepat satu dari sequence.id atau sequence.definition. Keduanya juga memerlukan entry_node_id, langkah Start call tempat panggilan dimulai, dan trigger_data, objek yang sesuai dengan skema data entri tersebut. Gunakan {} jika entri menerima data kosong. Referensi Create Call mendokumentasikan batas permintaan dan waktu tunggu dering opsional.

Memanggil sequence yang dibuat di dashboard

Gunakan sequence.id untuk menjalankan sequence yang Anda buat dan publikasikan di dashboard. Create Call selalu menjalankan publikasi aktifnya.

  1. Buka sequence di Sequences.
  2. Di bagian How to run this sequence, pilih More details di samping Create a call.
  3. Jika sequence memiliki beberapa entry, pilih Call trigger yang akan dimulai.
  4. Salin permintaan tersebut. Permintaan berisi sequence ID dan entry ID.

Simpan body permintaan sebagai call.json, ganti nomor contoh dengan nomor Anda sendiri:

Contoh kode
{
  "from": "+12025550100",
  "to": "+12025550101",
  "sequence": {
    "id": "YOUR_SEQUENCE_ID",
    "entry_node_id": "YOUR_ENTRY_NODE_ID",
    "trigger_data": {}
  }
}

Isi trigger_data dengan field yang dideklarasikan entry, termasuk objek dan array bersarang. Create Call tidak menerima versi historis, draf, atau mode pengujian. Untuk menguji draf tersimpan, gunakan kontrol Place a call di dashboard.

Menjalankan sequence inline

Gunakan sequence.definition untuk mengirim sequence lengkap bersama panggilan. Bird menjalankannya sekali dan tidak menyimpannya, sehingga panggilan tidak memiliki sequence ID. Definisi inline cocok untuk alur yang dihasilkan aplikasi Anda per panggilan.

Definisi inline harus lolos pemeriksaan yang sama seperti saat memublikasikan sequence. Eksekusinya dapat menjalankan maksimal 16 perintah, termasuk prompt gather; panggilan yang membutuhkan perintah ke-17 berakhir dengan trace error call_limit. Referensi node mencantumkan setiap langkah yang dapat Anda gunakan, beserta field dan outcome-nya. Untuk memulai dari flow yang sudah berjalan, buat dan publikasikan di dashboard, buka sequence tersebut, lalu pilih Copy JSON pada Definition JSON di bawah Published version.

call.json ini meminta penerima menekan 1 untuk jam buka atau 2 untuk petunjuk arah. Diam dan tombol lainnya mengakhiri run dengan alasan keluar masing-masing:

Contoh kode
{
  "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": {} }
        }
      ]
    }
  }
}

connections setiap node memetakan hasil ke node berikutnya. matches menu menamai pilihan-pilihannya, dan connections menggunakan nama yang sama bersama hasil bawaan timeout dan fallback.

Personalisasi sequence inline

Deklarasikan field yang Anda kirim di data_schema entry, lalu baca sebagai trigger.data.<field> dalam nilai $expr. Panggilan ini menyapa penerima berdasarkan nama dan mengonfirmasi atau menandai janji temu mereka:

Contoh kode
{
  "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" } }
          }
        }
      ]
    }
  }
}

status dan reason setiap exit memisahkan konfirmasi, permintaan bantuan, dan tanpa respons. Objek trigger_data yang tidak cocok dengan data_schema gagal validasi, dengan lokasinya di bawah /sequence/trigger_data, dan panggilan tidak dilakukan.

Kirim permintaan

Pilih satu metode permintaan di bawah untuk call.json yang Anda simpan.

Pilih kunci idempotensi yang baru dan unik sekali untuk panggilan yang dimaksud ini. Simpan kunci tersebut dan input asli untuk percobaan ulang atau pemulihan konfirmasi. Pilih kunci lain jika Anda bermaksud melakukan panggilan baru yang terpisah, setelah menyelesaikan hasil yang tidak diketahui dari panggilan asli.

Untuk contoh shell, atur IDEMPOTENCY_KEY ke nilai pilihan Anda sebelum mengirim. Contoh akan berhenti jika nilainya tidak diatur atau kosong; contoh tidak menghasilkan kunci lain jika diulang.

Untuk HTTP, atur BIRD_API_KEY ke kunci Anda dan BIRD_API_URL ke URL basis regional-nya, misalnya https://eu1.platform.bird.com untuk kunci eu1, lalu kirim permintaan:

Contoh kode
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

Untuk pratinjau CLI, masuk dengan kedua izin tulis dan siapkan panggilan menggunakan file yang sama:

Contoh kode
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}"

Perintah mencetak tautan tinjauan browser dan menunggu penyelesaian. Buka tautan tersebut, periksa pemanggil, penerima, sequence, dan data entry, lalu jalankan permintaan sendiri. Menyiapkan permintaan tidak melakukan panggilan. Tambahkan --dry-run untuk memeriksa permintaan CLI tanpa membuat konfirmasi. Jika konfirmasi kedaluwarsa, dibatalkan, atau berakhir tanpa hasil tercatat, perintah keluar dengan 5; ikuti panduan percobaan ulang sebelum membuat permintaan lain.

Untuk pratinjau MCP, panggil voice_calls_create dengan field dari call.json dan idempotency_key yang wajib. Ganti <unique-key-for-this-request-reuse-for-retries> dengan kunci pilihan Anda:

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

Ikuti tautan tinjauan browser yang dikembalikan untuk menjalankan permintaan. Pada endpoint MCP dinamis, pilih voice_calls_create melalui execute. Persetujuan OAuth memberikan izin workspace; tinjauan browser menjalankan panggilan spesifik ini.

Respons 202 Accepted mengonfirmasi penerimaan. Sequence dimulai setelah penerima menjawab. Mempublikasikan versi yang lebih baru setelah penerimaan tidak mengubah definisi atau data entry yang dipilih untuk panggilan ini.

Baca hasil penerimaan

Simpan id, initial_leg_id, dan sequence.run_id dari respons untuk korelasi. id tingkat atas mengidentifikasi panggilan di seluruh leg-nya; initial_leg_id mengidentifikasi leg pertamanya.

Respons adalah snapshot penerimaan yang tidak dapat diubah. started_at dan ended_at-nya bernilai null, boolean observasi bernilai false, dan parties kosong. Field-field ini menjelaskan penerimaan, sehingga tidak menjadi laporan status langsung saat Anda memutar ulang permintaan.

Buka Runs pada sequence untuk memeriksa progres. Panggilan inline tidak termasuk dalam sequence mana pun, jadi ikuti leg-nya; jika gagal sebelum leg-nya terdaftar, belum ada cara untuk memeriksanya. Setelah catatan leg tersedia, gunakan GET /v1/voice/legs/{leg_id} dengan initial_leg_id, atau periksa call log. Membaca leg memerlukan izin voice:read, yang sudah tercakup dalam voice:write.

Leg dengan status rejected ditolak sebelum terhubung, sehingga sequence-nya tidak berjalan. Tanpa alasan penolakan, ujung lain menolak panggilan tersebut; lihat Rejected calls.

Dengan CLI, bird voice calls get YOUR_CALL_ID menampilkan panggilan dan pihak-pihaknya. bird voice legs trace YOUR_LEG_ID menampilkan langkah mana yang dijalankan, digit yang dikumpulkan kecuali gather bersifat privat, serta status dan alasan exit. Trace tersedia tak lama setelah panggilan berakhir; sebelum itu perintah mengembalikan error, jadi coba lagi. Sequence dari leg yang ditolak tidak pernah berjalan, sehingga mungkin tidak memiliki trace.

Penerimaan tidak menjamin pemanggilan, jawaban, atau catatan panggilan yang dapat dibaca. Panggilan yang gagal sebelum registrasi mungkin muncul di riwayat run tanpa catatan leg. Panggilan yang dijawab juga tidak membuktikan bahwa sequence menyelesaikan tugas bisnis yang dimaksud.

Menangani kesalahan dan percobaan ulang

Untuk permintaan HTTP langsung, idempotensi bersifat opsional. Tanpa kunci, setiap permintaan menerima percobaan panggilan baru. SDK menghasilkan kunci untuk percobaan ulang otomatis. Untuk melindungi percobaan ulang lintas panggilan terpisah atau permintaan HTTP langsung, berikan kunci pada percobaan pertama dan gunakan kembali dengan byte permintaan asli yang sama persis. Lihat panduan idempotensi.

Pengulangan identik dalam tiga jam mengembalikan penerimaan asli dan Idempotency-Replay: true. Input yang diubah dengan kunci tersebut mengembalikan 409. Otorisasi dan izin nomor pemanggil diperiksa kembali saat pengulangan. Setelah jendela pengulangan, kunci dapat menerima panggilan baru, jadi rekonsiliasi hasil asli sebelum mengirim ulang.

Untuk CLI dan MCP, berikan kunci idempotensi pada percobaan pertama. Mengulangi permintaan dan kunci yang sama dengan grant OAuth yang sama mengembalikan konfirmasi yang ada selama catatannya masih disimpan. Simpan input asli dan ID konfirmasi. Mengubah kunci dapat menyiapkan panggilan berbayar lain.

Jika perintah CLI terputus, lanjutkan dengan input asli, kunci, dan ID konfirmasi yang dikembalikan:

Contoh kode
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

Untuk MCP, ulangi argumen tool asli, termasuk idempotency_key yang sama, bersama dengan state permintaan yang dikembalikan. State mengidentifikasi konfirmasi dan tidak menggantikan argumen tersebut. Alternatifnya, ulangi tool dan argumen yang sama dengan ID yang dikembalikan di metadata permintaan bird/confirmation-id. Dengan MCP dinamis, ulangi permintaan execute yang sama dan letakkan metadata tersebut di dalamnya. Melanjutkan membaca konfirmasi asli dan mengembalikan hasil tercatatnya setelah selesai.

Konfirmasi Create Call kedaluwarsa setelah 90 menit. Konfirmasi pending atau expired tanpa hasil tidak membuktikan panggilan tidak pernah dijalankan. Periksa run sequence asli dan catatan call-leg sebelum memutuskan untuk melakukan panggilan lain; jangan membuat kunci baru untuk menyelesaikan hasil yang tidak diketahui. Konfirmasi selesai dengan hasil 202 membuktikan penerimaan, jadi lanjutkan dengan pemeriksaan penerimaan untuk mengetahui hasil panggilan.

GejalaYang perlu diperiksa
400 atau 422Baca detail field kesalahan. Periksa format nomor, kelayakan dan kepemilikan nomor pemanggil, sequence dan entry ID, objek data eksplisit, dan batas permintaan.
401 atau 403Periksa kunci API atau login OAuth Anda, kedua izin tulis yang diperlukan, dan akses workspace.
404Periksa apakah sequence milik workspace yang dipilih dan pembuatan panggilan tersedia di layanan regional.
409Periksa apakah ada percobaan ulang dengan body yang diubah atau sequence produksi aktif yang tidak tersedia. Publikasikan atau lanjutkan sesuai kebutuhan sebelum memulai panggilan baru.
429Patuhi panduan percobaan ulang dari respons. Jika Anda memberikan kunci, gunakan kembali untuk percobaan panggilan yang sama.
Diterima, lalu gagalPeriksa run dan catatan leg untuk tujuan, batas, saldo, atau kegagalan runtime sebelum memutuskan untuk melakukan panggilan lain.

Langkah selanjutnya

Lanjutkan dengan dokumentasi, panduan, dan contoh untuk topik ini.