---
title: "Lakukan panggilan keluar (API)"
description: "Picu panggilan keluar berbasis AI dari kode Anda sendiri — untuk survei, tindak lanjut, atau alur konfirmasi."
---

Panggilan keluar memungkinkan Anda memberikan nomor tujuan dan konfigurasi
agen ke ThunderPhone, lalu AI melakukan panggilan atas nama Anda.
Kasus penggunaan umum:

- Konfirmasi janji temu
- Panggilan balik survei
- Tindak lanjut "percobaan kedua" setelah panggilan terlewat
- Notifikasi bergaya pengiriman

<Note>
  Memanggil seluruh daftar? Fitur
  [**Kampanye**](/id/guides/outbound-campaigns) di dashboard
  (`/dashboard/campaigns`) menerima CSV kontak dan menangani
  jendela panggilan yang mempertimbangkan zona waktu, konkurensi, serta kebijakan
  percobaan ulang untuk Anda. Panduan ini membahas panggilan programatis tunggal.
</Note>

## Prasyarat

<Steps>
  <Step title="Pilih nomor yang diaktifkan untuk panggilan keluar">
    Gunakan nomor yang Anda miliki melalui
    [koneksi VoIP](/api-reference/voip-connections), atau minta izin
    untuk menggunakan nomor ThunderPhone Anda untuk panggilan keluar dari halaman Phone Numbers.
    Nomor ThunderPhone awalnya hanya untuk panggilan masuk. ThunderPhone meninjau setiap
    permintaan secara manual; setelah disetujui, nomor tersebut dapat melakukan panggilan hingga
    batas harian yang disetujui (diatur ulang pada 00:00 UTC) dan menjalankan kampanye, dan Anda
    dapat meminta batas yang lebih tinggi. Nomor VoIP pelanggan tidak memiliki batas harian, sehingga kami merekomendasikan
    nomor tersebut untuk panggilan keluar. Lihat
    [Bawa nomor Anda sendiri](/id/guides/bring-your-own-numbers).
  </Step>
  <Step title="Buat agen">
    Prompt bernuansa panggilan keluar umumnya dimulai dengan agen
    memperkenalkan dirinya dan tujuannya — "Halo, ini Acme yang menelepon untuk
    mengonfirmasi janji temu Anda besok pukul 15.00…" Atur
    `outbound_speak_order` ke `agent_first` (default).
  </Step>
  <Step title="Pertahankan saldo positif">
    Panggilan keluar mengembalikan `402 Payment Required` jika saldo ≤
    `$0.00`. Isi ulang atau aktifkan isi ulang otomatis di
    **Organization → Billing Settings** pada dasbor. Kunci `sk_live_`
    Anda dapat memeriksa saldo dengan
    [`GET /v1/billing`](/api-reference/billing#get-billing-account), tetapi
    tidak dapat mengisi ulang atau mengubah isi ulang otomatis.
  </Step>
</Steps>

## Lakukan panggilan dengan agen tersimpan

Cara paling sederhana — rujuk agen berdasarkan ID:

```bash
curl -X POST https://api.thunderphone.com/v1/call \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from_number": "+15551234567",
    "to_number":   "+14155552671",
    "agent_id":    12
  }'
```

Respons:

```json
{ "call_id": 987654321, "status": "initiated" }
```

<Warning>
  `status: "initiated"` hanya berarti permintaan diterima — panggilan
  **belum terhubung**. Polling
  [`GET /v1/calls/{call_id}`](/api-reference/calls#retrieve-a-call)
  untuk status terkini (`in_progress` → `completed` / `failed`).
</Warning>

## Lakukan panggilan dengan konfigurasi sebaris

Jika Anda menginginkan Prompt sekali pakai yang tidak layak disimpan sebagai agen,
gunakan `config`. Strukturnya sesuai dengan skema respons dari
[webhook `call.incoming`](/id/webhooks/call-incoming):

```bash
curl -X POST https://api.thunderphone.com/v1/call \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from_number": "+15551234567",
    "to_number":   "+14155552671",
    "config": {
      "prompt":  "You are confirming Jane Doe appointment for 3pm tomorrow…",
      "voice":   "john",
      "product": "spark"
    }
  }'
```

## Ikuti panggilan

Secara paralel, berlangganan ke
[webhook `telephony.complete`](/id/webhooks/events) —
cara tercepat untuk mengetahui bahwa panggilan telah selesai. Jika Anda tidak dapat menerima
webhook masuk, lakukan polling `GET /v1/calls/{call_id}` setiap beberapa detik; rekaman
mencakup `end_reason`, `duration_seconds`, dan URL rekaman
setelah panggilan berakhir.

Jika agen Anda diatur untuk mengekstrak data terstruktur setelah panggilan,
data tersebut dikirimkan secara terpisah setelah finalisasi selesai.

### Teruskan variabel per panggilan ke agen tersimpan

Agen tersimpan dapat menggunakan placeholder seperti `{{name}}` atau `{{name|there}}` dalam
teks Prompt. Saat Anda melakukan panggilan keluar dengan `agent_id`, teruskan
`variables` dengan nilai untuk panggilan tersebut:

```json
{
  "from_number": "+[REDACTED_PHONE]",
  "to_number": "+[REDACTED_PHONE]",
  "agent_id": 12,
  "variables": {
    "name": "Jordan"
  }
}
```

Gunakan nilai string yang diberi kunci berdasarkan nama placeholder. Variabel ini berlaku untuk
agen tersimpan; contoh `config` inline dalam panduan ini tidak menggunakannya.

## Mode kegagalan yang perlu ditangani

| Error | Perbaikan |
|-------|-----|
| `402 Payment Required` | Isi ulang saldo atau aktifkan isi ulang otomatis |
| `400` dengan `code: destination_not_allowed` | ThunderPhone tidak menghubungi nomor tersebut: nomor tidak valid, nomor darurat, nomor tarif premium, kode singkat, atau negara yang dikenai sanksi. Dari nomor ThunderPhone, hanya nomor biasa AS dan Kanada yang dapat dihubungi (tanpa tarif premium). `reason` menjelaskan yang mana; lihat [tujuan yang diblokir](/api-reference/outbound-calls#blocked-destinations) |
| `409` dengan `retryable: false` untuk nomor ThunderPhone | Ikuti `code`: ajukan panggilan keluar di halaman Phone Numbers, tunggu peninjauan yang tertunda, atau gunakan nomor lain yang memenuhi syarat |
| `429` dengan `code: platform_outbound_daily_limit_reached` | Organisasi telah menggunakan panggilan keluar hari ini dari nomor ThunderPhone. Tunggu `resets_at` (00:00 UTC), ajukan limit yang lebih tinggi di halaman Phone Numbers, atau lakukan panggilan dari nomor pada koneksi VoIP Anda sendiri |
| `429` dengan `code: concurrent_call_limit_reached` | Organisasi memiliki panggilan yang sedang berlangsung sebanyak [limit panggilan bersamaan](/api-reference/introduction#call-limits) (20 secara default, termasuk panggilan masuk, keluar, web, dan uji). Coba lagi setelah jumlah detik pada header `Retry-After` berlalu atau setelah panggilan berakhir; kirim email ke support@thunderphone.com untuk menaikkan limit |
| `429` dengan `code: same_number_too_soon` | Anda menghubungi `to_number` yang sama kurang dari 10 detik yang lalu. Coba lagi setelah jumlah detik pada header `Retry-After` berlalu |
| `409` dengan `retryable: false` untuk nomor VoIP pelanggan | Perbaiki status yang disebutkan oleh `code`; untuk kegagalan verifikasi, jalankan [`POST /v1/phone-numbers/{id}/verify-voip`](/api-reference/phone-numbers#verify-a-voip-sourced-number) |
| konflik idempotensi `409` | Gunakan kembali kunci hanya dengan permintaan ternormalisasi asli, atau kirim kunci baru |
| `404 from_number is not registered to this organization` | Pastikan `from_number` cocok dengan nomor telepon aktif di organisasi Anda. Nomor yang sudah dalam proses penyediaan, gagal, sedang dilepas, atau telah dilepas juga mengembalikan respons ini |
| `500` dengan hanya field `detail` | Tidak ada trunk keluar yang dikonfigurasi. Hubungi dukungan; ini bukan masalah status nomor yang dapat Anda perbaiki |
| `502 Bad Gateway` | Kegagalan SIP / LiveKit sementara; aman untuk mencoba lagi |

Lihat [referensi panggilan keluar](/api-reference/outbound-calls#error-responses)
untuk daftar lengkap kode kelayakan stabil dan kedua bentuk respons `409`.
Jika nomor aktif menjadi tidak memenuhi syarat setelah permintaan diterima tetapi sebelum
panggilan dilakukan, pemeriksaan akhir mengembalikan payload `409` yang tidak dapat dicoba ulang.

## Mengontrol waktu tunggu

Panggilan keluar yang berlangsung lama karena pihak yang dipanggil lambat merespons
(pohon IVR, antrean) dapat dibatasi dengan `max_hold_seconds`:

```json
{
  "from_number": "+15551234567",
  "to_number":   "+14155552671",
  "agent_id":    12,
  "max_hold_seconds": 120
}
```

Agen menutup panggilan jika tidak ada audio manusia yang diterima dalam N detik terakhir. Nilai defaultnya adalah 900 detik (15 menit).

---

## Langkah berikutnya

<CardGroup cols={2}>
  <Card title="Referensi panggilan keluar" icon="phone-arrow-up-right" href="/api-reference/outbound-calls">
    Setiap kolom permintaan dan kode kesalahan.
  </Card>
  <Card title="Terima call.complete" icon="bolt" href="/id/webhooks/call-complete">
    Streaming panggilan keluar yang selesai ke sistem Anda.
  </Card>
  <Card title="Penagihan" icon="credit-card" href="/api-reference/billing">
    Isi ulang otomatis agar panggilan keluar tidak pernah gagal karena saldo.
  </Card>
  <Card title="Uji agen keluar" icon="flask" href="/id/guides/test-agents">
    Jalankan simulasi agen keluar Anda sebelum produksi.
  </Card>
</CardGroup>
