---
title: "Endpoint Webhook"
description: "Kelola beberapa URL webhook dengan secret per endpoint dan filter peristiwa."
---

Sistem webhook berbasis endpoint memungkinkan Anda mendaftarkan **beberapa**
tujuan per organisasi, masing-masing dengan rahasia, status, dan
langganannya sendiri ke subset jenis peristiwa. Ini adalah model yang
direkomendasikan untuk semua integrasi baru.

Bandingkan dengan [webhook URL tunggal legacy](/api-reference/organizations#legacy-single-url-webhook),
yang dipertahankan untuk kompatibilitas mundur tetapi hanya mendukung satu URL per
organisasi.

## Endpoint

| Metode | Jalur | Peran yang diperlukan | Deskripsi |
|--------|------|---------------|-------------|
| `GET` | `/v1/developer/webhook-endpoints` | `admin+` | Daftarkan endpoint |
| `POST` | `/v1/developer/webhook-endpoints` | `admin+` | Buat endpoint |
| `PATCH` | `/v1/developer/webhook-endpoints/{endpoint_id}` | `admin+` | Perbarui label / URL / peristiwa / status |
| `DELETE` | `/v1/developer/webhook-endpoints/{endpoint_id}` | `admin+` | Hapus endpoint |
| `POST` | `/v1/developer/webhook-endpoints/{endpoint_id}/rotate-secret` | `admin+` | Ganti rahasia penandatanganan |
| `POST` | `/v1/developer/webhook-endpoints/{endpoint_id}/test` | `admin+` | Kirim pengiriman pengujian yang ditandatangani |
| `GET` | `/v1/developer/webhook-deliveries` | `admin+` | Periksa hasil pengiriman endpoint dan versi lama terbaru |

## Objek endpoint

```json
{
  "id": "c4d5e6f7-...",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "agent_id": 42,
  "agent_name": "Support Agent",
  "secret_hint": "a1b2…9f0e",
  "paused_at": null,
  "pause_last_error": "",
  "pause_undelivered_count": null,
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z"
}
```

| Kolom | Tipe | Deskripsi |
|-------|------|-------------|
| `id` | UUID | ID endpoint |
| `label` | string | Nama tampilan, 1–120 karakter |
| `url` | string | URL HTTPS; `http://localhost` diizinkan untuk pengembangan |
| `events` | array of string | Jenis peristiwa yang dilanggan (lihat [nilai valid](#valid-event-types)). Array kosong melanggankan semua peristiwa kecuali peristiwa per-giliran khusus eksplisit (`telephony.turn` / `web.turn`) |
| `status` | string | `active`, `disabled` (dijeda secara manual), atau `failing` (ditetapkan otomatis saat pengiriman menghabiskan jadwal coba ulang 24 jam tanpa satu pun respons 2xx) |
| `agent_id` | integer \| null | Agen yang menjadi cakupan endpoint ini; `null` berarti berlaku untuk seluruh organisasi |
| `agent_name` | string \| null | Nama agen dalam cakupan, atau `null` untuk endpoint yang berlaku untuk seluruh organisasi |
| `secret_hint` | string | 4 karakter pertama dan 4 karakter terakhir dari rahasia penandatanganan dengan elipsis (`a1b2…9f0e`) — cukup untuk mencocokkan silang rahasia yang Anda simpan secara lokal tanpa mengungkapkan nilai lengkapnya |
| `paused_at` | timestamp \| null | Waktu ThunderPhone menetapkan endpoint ke `failing`. `null` saat statusnya `active` atau `disabled` |
| `pause_last_error` | string | Kesalahan pengiriman terakhir saat endpoint dijeda, misalnya `HTTP 503: Service Unavailable`. Kosong kecuali jika `failing` |
| `pause_undelivered_count` | integer \| null | Peristiwa yang tidak terkirim sejak pengiriman berhasil terakhir endpoint, dihitung saat endpoint dijeda |
| `created_at`, `updated_at` | timestamp | |

<Note>
  `secret` lengkap endpoint dikembalikan **sekali** saat dibuat dan
  tidak pernah lagi. Simpan dengan aman — jika Anda kehilangannya,
  [rotasikan](#rotate-the-signing-secret) untuk mendapatkan yang baru.
</Note>

### Tipe peristiwa valid

`events` divalidasi berdasarkan kumpulan persis ini — nilai di luar daftar
mengembalikan `400`. Lihat [Katalog peristiwa](/id/webhooks/events) untuk bentuk
payload setiap tipe.

- `telephony.incoming`, `telephony.complete`, `telephony.tool`, `telephony.turn`
- `web.incoming`, `web.complete`, `web.tool`, `web.turn`
- `sms.sent`, `sms.failed`
- `sms.received` (dicadangkan; belum dipancarkan)
- `call.graded`, `call.data_extracted`, `call.transfer_completed`
- `campaign.completed`
- `issue.reported`, `issue.escalated`
- `test-call.completed`
- `alert.triggered`

`issue.escalated` tidak memiliki konteks agen dan hanya dikirimkan ke
endpoint seluruh organisasi.

`voice.ready` dan `voice.failed` tidak dapat dipilih secara eksplisit. Untuk menerimanya,
buat endpoint seluruh organisasi dengan `events: []`. Daftar peristiwa kosong
menerima setiap peristiwa yang didukung kecuali `telephony.turn` dan `web.turn`,
yang harus dipilih secara eksplisit.

### Status endpoint

- `active` — pengiriman berjalan normal.
- `disabled` — dijeda secara manual melalui `PATCH`. Tidak ada permintaan yang dikirim. Kami
  tidak pernah mengubah status endpoint `disabled`; mengubahnya kembali menjadi
  `active` selalu merupakan keputusan Anda.
- `failing` — ditetapkan secara otomatis ketika pengiriman ke endpoint menghabiskan
  seluruh jadwal percobaannya (8 percobaan selama 24 jam) tanpa pernah
  mendapatkan respons 2xx. Endpoint yang gagal tidak menerima trafik lebih lanjut.
  Kami mengirim email kepada pemilik dan admin organisasi Anda ketika ini terjadi, dan
  dasbor menampilkan endpoint yang dijeda dengan tombol Aktifkan kembali.
  Setelah endpoint diperbaiki, ubah statusnya kembali menjadi `active` melalui `PATCH`;
  pengiriman yang jadwal percobaannya belum habis akan dilanjutkan dari titik
  terakhirnya.

---

## Daftar endpoint

<CodeGroup>
```bash cURL
curl https://api.thunderphone.com/v1/developer/webhook-endpoints \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

Mengembalikan array [objek Endpoint](#endpoint-object).
Teruskan `?agent_id=42` untuk mengembalikan hanya endpoint yang dicakup agen tersebut.

### Endpoint dalam cakupan agen

Endpoint seluruh organisasi menerima setiap peristiwa yang cocok. Endpoint dengan
`agent_id` hanya menerima peristiwa yang cocok untuk panggilan yang ditangani agen tersebut;
peristiwa tanpa konteks agen, seperti `alert.triggered`, tidak pernah mencapainya. Anda
juga dapat membuat dan mengelola endpoint ini dari bagian
**Webhook** di pembuat agen.

---

## Buat endpoint

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label":  "Production — Call events",
    "url":    "https://example.com/thunderphone/hook",
    "events": ["telephony.incoming", "telephony.complete"]
  }'
```

```python Python
result = requests.post(
    "https://api.thunderphone.com/v1/developer/webhook-endpoints",
    headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
    json={
        "label":  "Production — Call events",
        "url":    "https://example.com/thunderphone/hook",
        "events": ["telephony.incoming", "telephony.complete"],
    },
).json()
secret = result["secret"]
endpoint_id = result["id"]
```
</CodeGroup>

### Bidang permintaan

| Bidang | Tipe | Wajib | Deskripsi |
|-------|------|----------|-------------|
| `label` | string | ya | 1–120 karakter |
| `url` | string | ya | URL HTTPS (`http` hanya diizinkan untuk `localhost` / `127.0.0.1`) |
| `events` | array | tidak | Kosong/tidak disertakan akan berlangganan ke semua peristiwa kecuali `telephony.turn` / `web.turn`, yang memerlukan langganan eksplisit. Harus menggunakan nilai yang tercantum dalam [Jenis peristiwa valid](#valid-event-types); duplikat dihapus |
| `agent_id` | integer \| null | tidak | Batasi pengiriman ke agen dalam organisasi ini; jangan sertakan atau gunakan `null` untuk endpoint seluruh organisasi |

Mengembalikan `201 Created` dengan [Objek endpoint](#endpoint-object) yang diperbarui serta
bidang `secret` tingkat teratas tambahan yang berisi kunci penandatanganan mentah — sebuah
string heksadesimal 48 karakter:

```json
{
  "id": "c4d5e6f7-…",
  "label": "Production — Call events",
  "url": "https://example.com/thunderphone/hook",
  "events": ["telephony.incoming", "telephony.complete"],
  "status": "active",
  "secret_hint": "a1b2…9f0e",
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z",
  "secret": "a1b2c37e08d94f5b16a2c8d90e7f3a4b5c6d7e8f90a19f0e"
}
```

<Warning>
  `secret` dikembalikan **hanya saat pembuatan**. Respons `GET` berikutnya
  hanya menyertakan `secret_hint`. Salin nilai lengkap ke pengelola rahasia Anda
  sebelum menutup respons.
</Warning>

---

## Perbarui endpoint

<CodeGroup>
```bash cURL
curl -X PATCH https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "label":  "Production — Call + Grade events",
    "events": ["telephony.incoming", "telephony.complete", "call.graded"]
  }'
```
</CodeGroup>

| Bidang | Tipe | Deskripsi |
|-------|------|-------------|
| `label` | string | |
| `url` | string | |
| `events` | array | |
| `status` | string | `active` atau `disabled`. Tetapkan `active` untuk mengaktifkan kembali endpoint yang ditandai server sebagai `failing` |
| `agent_id` | integer \| null | Tetapkan ID agen untuk membatasi endpoint, atau `null` agar berlaku untuk seluruh organisasi |

Mengembalikan `200 OK` dengan [Objek endpoint](#endpoint-object) yang diperbarui.

---

## Putar ulang rahasia penandatanganan

Ganti rahasia penandatanganan endpoint, misalnya ketika rahasia tersebut hilang atau
mungkin bocor. Untuk endpoint yang dicakup agen, Anda juga dapat menggunakan
dasbor: buka bagian **Webhook** agen dan pilih
**Buat ulang rahasia** pada endpoint. Endpoint di seluruh organisasi
diputar ulang melalui API.

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../rotate-secret \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```
</CodeGroup>

| Kolom | Tipe | Wajib | Deskripsi |
|-------|------|----------|-------------|
| `include_copies` | boolean | tidak | Default `true`. Juga memberikan rahasia baru kepada endpoint lain di organisasi Anda yang memiliki URL dan rahasia saat ini yang sama, seperti salinan endpoint ini pada agen lain, sehingga satu penerima tetap memverifikasi dengan satu rahasia |

Mengembalikan `200 OK`:

```json
{
  "endpoint": { "id": "c4d5e6f7-...", "secret_hint": "7f3a…c21d", "...": "..." },
  "secret": "7f3a90b2c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5c21d",
  "rotated_endpoint_ids": ["c4d5e6f7-..."]
}
```

| Kolom | Tipe | Deskripsi |
|-------|------|-------------|
| `endpoint` | objek | [Objek endpoint](#endpoint-object) dengan `secret_hint` barunya |
| `secret` | string | Rahasia penandatanganan baru. Hanya dikembalikan dalam respons ini |
| `rotated_endpoint_ids` | array UUID | Setiap endpoint yang kini menggunakan rahasia baru |

<Warning>
  Rahasia lama segera berhenti digunakan: pengiriman berikutnya,
  termasuk percobaan ulang, ditandatangani dengan rahasia baru. Hingga penerima Anda memiliki
  rahasia baru, pengiriman gagal dalam pemeriksaan tanda tangannya; jika penerima
  meresponsnya dengan status non-2xx, pengiriman akan dicoba ulang sesuai jadwal normal 24 jam,
  jadi segera perbarui penerima. Jika penerima Anda diluncurkan
  secara bertahap, buat penerima menerima kedua rahasia selama peluncuran — helper
  verifikasi SDK menerima daftar rahasia (lihat
  [Verifikasi tanda tangan webhook](/id/guides/verify-webhook-signatures)).
</Warning>

---

## Kirim pengiriman uji

Kirim event `webhook.test` sintetis ke satu endpoint menggunakan pipeline pengiriman normal, termasuk serialisasi JSON kanonis, kedua header tanda tangan, pencatatan pengiriman, dan pencatatan percobaan ulang.
Pengujian menargetkan endpoint yang dipilih terlepas dari filter `events`-nya.

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

Endpoint menerima envelope seperti berikut:

```json
{
  "data": {
    "message": "ThunderPhone webhook test",
    "sent_at": "2026-07-17T20:12:34.567890+00:00"
  },
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "type": "webhook.test"
}
```

API mengembalikan `200 OK` setelah percobaan pertama, bahkan jika tujuan
mengembalikan error. Periksa `success`, `status`, `response_code`, dan `error`
untuk hasil pengiriman:

```json
{
  "success": true,
  "event_id": "2ad6507c-7d19-4498-9b2d-7e8f944ab5a1",
  "event_type": "webhook.test",
  "status": "delivered",
  "response_code": 204,
  "error": ""
}
```

`webhook.test` bersifat sintetis dan tidak dapat ditambahkan ke langganan
`events` endpoint. Jika percobaan pertama gagal, ThunderPhone mencoba ulang sekali sekitar
satu menit kemudian lalu berhenti; pengiriman kemudian menampilkan `status: "failed"`
di bawah [Debug pengiriman](#debug-deliveries). Pengiriman uji tidak pernah menandai
endpoint sebagai `failing`.

Untuk mengonfigurasi pemicu berdasarkan bentuk peristiwa nyata, teruskan
`event_type` opsional. Pengiriman tetap sintetis dan berisi `"sample": true`;
sampel terkait panggilan menggunakan `call_id: 0` dan `agent_id: 0`.

```bash
curl -X POST https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-.../test \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event_type":"call.graded"}'
```

`event_type` menerima nilai apa pun dari [Jenis peristiwa yang valid](#valid-event-types).
Mengabaikannya mempertahankan perilaku `webhook.test` generik.

---

## Hapus endpoint

<CodeGroup>
```bash cURL
curl -X DELETE https://api.thunderphone.com/v1/developer/webhook-endpoints/c4d5e6f7-... \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

Mengembalikan `204 No Content`. Pengiriman ke URL segera berhenti;
percobaan ulang yang sedang berlangsung dibatalkan.

---

## Debug pengiriman

Sebelum menyimpulkan bahwa webhook tidak dikirim, periksa
[`GET /v1/developer/webhook-deliveries`](/api-reference/webhook-deliveries).
Ini menampilkan percobaan terbaru dari kedua sistem webhook, termasuk ID panggilan,
asal URL, status HTTP, jumlah percobaan, kategori kegagalan yang diizinkan, dan waktu
percobaan ulang berikutnya. Ini tidak pernah mengembalikan payload peristiwa, transkrip, teks error yang disimpan,
badan respons, atau jalur URL.

Anda juga dapat melihat riwayat terbaru yang sama di **Agen → pilih agen → Webhooks →
Pengiriman terbaru**. Baris menampilkan label endpoint dan asal URL yang digunakan oleh
percobaan terbaru. Ini adalah status operasional, bukan log audit yang tidak dapat diubah: menghapus endpoint
juga menghapus baris pengirimannya.

Untuk `404` n8n, pertama pastikan workflow aktif, menerima `POST`, dan menggunakan
URL webhook produksi, bukan URL pengujian. `401` atau `403` menunjukkan masalah
autentikasi atau validasi tanda tangan; timeout menunjukkan latensi
atau ketersediaan tujuan; error TLS menunjukkan rantai sertifikat, hostname, atau masa berlaku.

---

## Terkait

<CardGroup cols={2}>
  <Card title="Katalog peristiwa" icon="list" href="/id/webhooks/events">
    Daftar lengkap nilai `events` yang dapat Anda langgani.
  </Card>
  <Card title="Ringkasan webhook" icon="bolt" href="/id/webhooks/overview">
    Verifikasi tanda tangan dan semantik pengiriman.
  </Card>
</CardGroup>
