Open in
Ringkasan Webhook
Cara ThunderPhone mengirimkan peristiwa secara real-time, cara memverifikasi tanda tangan, serta perbandingan model pengiriman lama dan berbasis endpoint.
ThunderPhone mengirim permintaan HTTP POST ke server Anda ketika peristiwa
terjadi selama panggilan — panggilan masuk dimulai, panggilan berakhir, proses penilaian
selesai, peringatan dipicu, dan sebagainya. Ada dua model
pengiriman:
Beberapa URL, secret per endpoint, filter peristiwa per endpoint,
dan percobaan ulang otomatis.
Kelola melalui GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.
Satu URL per organisasi. Membawa peristiwa siklus hidup panggilan, termasuk
pertukaran konfigurasi pemblokiran. Dikelola di GET/PUT /v1/webhook.
Semua jenis peristiwa yang tercantum dalam katalog peristiwa
dikirimkan melalui endpoint webhook. Enam peristiwa siklus hidup panggilan
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) juga dikirim ke
webhook lama satu URL — jika Anda memiliki URL lama dan endpoint yang
sesuai, Anda menerima peristiwa di kedua jalur. Perilaku pemblokiran
(pertukaran konfigurasi telephony.incoming / web.incoming
dan pengiriman tool mode webhook)
hanya tersedia pada jalur lama; setiap pengiriman endpoint adalah
notifikasi tanpa menunggu respons.
Format payload
Pengiriman endpoint berupa objek JSON dengan data, event_id, dan
type:
{
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
},
"event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
"type": "telephony.incoming"
}event_id bersifat unik untuk setiap peristiwa yang diterbitkan. Nilainya sama pada percobaan ulang
dan pada setiap endpoint yang menerima peristiwa tersebut — lakukan deduplikasi berdasarkan ID ini.
Webhook lama satu URL mengirim type dan data yang sama, tetapi
tanpa event_id:
{
"type": "telephony.incoming",
"data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}Dalam transmisi, setiap body diserialisasi secara kanonis — kunci diurutkan secara alfabetis, tanpa spasi kosong, UTF-8. Contoh yang ditampilkan dengan format rapi dalam dokumentasi ini hanya untuk keterbacaan.
Lihat Katalog peristiwa untuk daftar lengkap jenis peristiwa dan field payload.
Verifikasi tanda tangan
Setiap permintaan membawa dua tanda tangan, keduanya HMAC-SHA256 yang menggunakan secret endpoint sebagai kunci (atau secret webhook tingkat organisasi Anda untuk pengiriman lama):
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex>menandatangani stempel waktu, metode, jalur dan kueri, serta body mentah. Verifikasi tanda tangan ini, dan tolak permintaan yangt-nya lebih dari 5 menit dari waktu Anda agar permintaan yang ditangkap tidak dapat diputar ulang nanti. Percobaan ulang ditandatangani kembali saat dikirim.X-ThunderPhone-Signaturehanya menandatangani body mentah. Tanda tangan ini tetap dikirim tanpa perubahan agar verifier yang sudah ada tetap berfungsi.
Langkah
- Baca header, metode, jalur dan kueri mentah, serta body mentah sebelum penguraian apa pun.
- Hitung HMAC-SHA256 heksadesimal dari
<t>\n<METHOD>\n<path and query>\n<body>menggunakan secret Anda. - Tolak permintaan jika
tmeleset lebih dari 300 detik, atau jika hasilnya tidak cocok denganv1dalam perbandingan waktu konstan.
Body adalah serialisasi JSON kanonis (kunci diurutkan, pemisah ringkas), dan kami menandatangani tepat byte yang kami kirimkan. Panduan verifikasi memiliki string yang ditandatangani secara tepat, contoh lengkap, kode tanpa SDK, dan header lama.
from flask import Flask, abort, request
from thunderphone import verify_signature
app = Flask(__name__)
@app.post("/thunderphone-webhook")
def handle():
query = request.query_string.decode()
if not verify_signature(
request.headers.get("X-ThunderPhone-Signature-V2"),
secret=WEBHOOK_SECRET,
method=request.method,
path=request.path + (f"?{query}" if query else ""),
body=request.get_data(), # raw bytes
):
abort(401)
event = request.get_json()
# dispatch on event["type"] …
return "", 204import express from "express";
import { verifySignature } from "@thunderphone/sdk";
const app = express();
app.post(
"/thunderphone-webhook",
express.raw({ type: "application/json" }),
(req, res) => {
const ok = verifySignature({
header: req.header("X-ThunderPhone-Signature-V2"),
secret: process.env.WEBHOOK_SECRET,
method: req.method,
path: req.originalUrl,
body: req.body,
});
if (!ok) return res.sendStatus(401);
const event = JSON.parse(req.body.toString("utf8"));
// dispatch on event.type …
res.sendStatus(204);
},
);Semantik pengiriman
Semantik ini berlaku untuk pengiriman endpoint. Webhook lama dengan satu URL
adalah satu upaya sinkron tanpa percobaan ulang, kecuali pertukaran konfigurasi
panggilan telepon telephony.incoming,
yang dicoba ulang sekali.
Percobaan ulang
Setiap event segera dicoba sekali. Respons 2xx apa pun
mengonfirmasi pengiriman. Untuk hasil lainnya (non-2xx,
kesalahan koneksi, waktu habis), kami mencoba ulang pada 1 m, 5 m, 30 m, 2 h, 6 h,
12 h, dan 24 h setelah upaya pertama — 8 upaya selama
24 jam. Jika semua upaya gagal, pengiriman berhenti dan endpoint
ditandai status="failing" di
endpoint webhook; kami mengirim email kepada
pemilik dan admin organisasi Anda serta menampilkannya di dasbor. Kembalikan 2xx segera setelah
payload diterima secara tahan lama; proses secara asinkron.
Pengiriman uji dari API pengujian endpoint mendapatkan satu percobaan ulang sekitar satu menit setelah
upaya pertama dan tidak pernah mengubah status endpoint.
Urutan
Urutan pengiriman adalah upaya terbaik. Dalam praktiknya, kami mengirimkan sesuai
urutan event dipancarkan, tetapi percobaan ulang dapat mengubah urutan saat terjadi kegagalan.
Selalu lakukan deduplikasi dan rekonsiliasi berdasarkan call_id / ID objek.
Duplikat
Pengiriman bersifat setidaknya sekali: percobaan ulang setelah respons yang tidak
kami terima dapat menduplikasi event. Setiap percobaan ulang membawa
event_id yang sama, jadi simpan ID yang sudah diproses dan lewati pengulangan. event_id juga
dibagikan antar-endpoint — dua endpoint yang berlangganan pada
event yang sama menerima event_id yang sama.
Waktu habis
Pengiriman endpoint memiliki waktu habis 30 s per upaya. Pada
jalur lama, permintaan pemblokiran yang mengendalikan perilaku panggilan langsung — pertukaran
konfigurasi telephony.incoming / web.incoming
— dibatasi hingga 10 s untuk upaya pertama panggilan telepon
dan 13 s untuk seluruh pertukaran termasuk satu
percobaan ulangnya, serta hingga 10 s untuk sesi widget. Respons yang lambat menunda
pengangkatan panggilan, jadi usahakan menjawab dalam beberapa detik. Pengiriman tool mode webhook mengizinkan 20 s
secara default, dan deklarasi tool dapat menetapkan timeout tingkat atas.
IP sumber
Webhook keluar berasal dari rentang IP cloud ThunderPhone. Jika firewall Anda memerlukan daftar izin, hubungi dukungan dan kami akan membagikan rentang saat ini.
Memilih antara webhook legacy dan berbasis endpoint
| Fitur | Legacy (/v1/webhook) | Endpoint (/v1/developer/webhook-endpoints) |
|---|---|---|
| Jumlah URL | 1 per organisasi | Banyak per organisasi |
| Cakupan event | Hanya telephony.* / web.* | Semua 10 jenis event |
| Filter event | — | Per endpoint |
| Percobaan ulang | Tidak ada, kecuali satu untuk pertukaran konfigurasi panggilan telepon | 8 percobaan selama 24 jam |
| Envelope | type + data | type + data + event_id |
| Rotasi secret | Mengganti satu secret | Secret per endpoint |
| Nonaktifkan tanpa menghapus | PUT /v1/webhook dengan {"url": ""} | status=disabled |
| Visibilitas Status | — | active / disabled / failing |
| Pertukaran konfigurasi yang memblokir | Ya (telephony.incoming / web.incoming) | Tidak pernah — hanya notifikasi |
| Paling sesuai untuk | Konfigurasi panggilan dinamis | Konsumsi event di produksi |
Integrasi baru sebaiknya menerima event melalui webhook berbasis endpoint. Pertahankan (atau tambahkan) URL legacy hanya jika Anda mengonfigurasi panggilan secara dinamis saat panggilan diangkat atau menggunakan pengiriman tool mode webhook — pertukaran permintaan/respons tersebut hanya berjalan pada jalur legacy.
Terkait
Semua jenis event dan payload-nya.
Kelola beberapa endpoint, filter event, dan secret.
Permintaan pemblokiran yang harus dijawab server Anda untuk mengonfigurasi panggilan.
Payload pascapanggilan dengan transkrip, rekaman, dan metrik.