Open in
Prehľad webhookov
Ako ThunderPhone doručuje udalosti v reálnom čase, ako overovať podpisy a ako sa porovnávajú starší model doručovania a model založený na koncových bodoch.
ThunderPhone odosiela na váš server požiadavky HTTP POST, keď počas hovoru
nastanú udalosti — začne sa prichádzajúci hovor, hovor sa skončí, dokončí sa
hodnotenie, spustí sa upozornenie a podobne. Existujú dva modely
doručovania:
Viacero adries URL, tajné kľúče pre jednotlivé koncové body, filtre udalostí pre jednotlivé koncové body
a automatické opakovania.
Spravujte prostredníctvom GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.
Jedna adresa URL pre organizáciu. Obsahuje udalosti životného cyklu hovoru vrátane
blokujúcich výmien konfigurácie. Spravuje sa prostredníctvom GET/PUT /v1/webhook.
Všetkých desať typov udalostí v katalógu udalostí sa
doručuje prostredníctvom koncových bodov webhookov. Šesť udalostí životného cyklu hovoru
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) sa zároveň odosiela do
staršieho webhooku s jednou adresou URL — ak máte staršiu adresu URL aj zodpovedajúci
koncový bod, udalosť dostanete na oboch cestách. Blokujúce
správanie (výmena konfigurácie telephony.incoming / web.incoming
a odoslanie nástroja v režime webhooku)
je dostupné výlučne na staršej ceste; každé doručenie na koncový bod je
oznámenie typu fire-and-forget.
Formát dátovej časti
Doručenia na koncový bod sú objekty JSON s položkami data, event_id a
type:
{
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
},
"event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
"type": "telephony.incoming"
}event_id je jedinečný pre každú odoslanú udalosť. Je identický pri opakovaniach
aj na všetkých koncových bodoch, ktoré udalosť prijmú — používajte ho na deduplikáciu.
Starší webhook s jednou adresou URL odosiela rovnaké type a data, ale
bez event_id:
{
"type": "telephony.incoming",
"data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}Pri prenose je každé telo serializované kanonicky — kľúče sú zoradené abecedne, bez medzier, v kódovaní UTF-8. Príklady s formátovaním v tejto dokumentácii slúžia len na lepšiu čitateľnosť.
Úplný zoznam typov udalostí a polí dátovej časti nájdete v katalógu udalostí.
Overenie podpisu
Každá požiadavka obsahuje v hlavičke X-ThunderPhone-Signature podpis HMAC-SHA256 vytvorený nad nespracovaným telom požiadavky. Podpisovací kľúč je secret koncového bodu (alebo secret webhooku na úrovni vašej organizácie pre staršie doručenia).
Kroky
- Prečítajte nespracované telo požiadavky pred akýmkoľvek spracovaním.
- Vypočítajte
hmac_sha256(secret, body).hexdigest(). - Porovnajte výsledok v konštantnom čase s hlavičkou
X-ThunderPhone-Signature.
Podpisujeme presne tie bajty, ktoré odosielame, a tieto bajty sú kanonickou serializáciou JSON (zoradené kľúče, kompaktné oddeľovače). Overovanie voči nespracovanému telu preto vždy funguje — a ak vám váš framework poskytne iba spracovaný JSON, jeho opätovná serializácia so zoradenými kľúčmi a kompaktnými oddeľovačmi vytvorí identické bajty. Oba postupy sú uvedené v návode na overenie.
import hmac
import hashlib
def verify_signature(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature or "")
# Example Flask handler
from flask import Flask, request, abort
app = Flask(__name__)
@app.post("/thunderphone-webhook")
def handle():
body = request.get_data()
sig = request.headers.get("X-ThunderPhone-Signature", "")
if not verify_signature(body, sig, WEBHOOK_SECRET):
abort(401)
event = request.get_json()
# dispatch on event["type"] …
return "", 204import crypto from "node:crypto";
import express from "express";
function verifySignature(body, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
if (!signature || expected.length !== signature.length) return false;
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature),
);
}
const app = express();
app.post(
"/thunderphone-webhook",
express.raw({ type: "application/json" }),
(req, res) => {
const sig = req.header("X-ThunderPhone-Signature") || "";
if (!verifySignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString("utf8"));
// dispatch on event.type …
res.sendStatus(204);
},
);Sémantika doručovania
Táto sémantika sa vzťahuje na doručovanie do koncových bodov. Starší webhook s jednou URL je jeden synchrónny pokus bez opakovaní.
Opakovania
Každá udalosť sa okamžite pokúsi doručiť raz. Každá odpoveď 2xx
potvrdzuje doručenie. Pri akomkoľvek inom výsledku (nie-2xx,
chyba pripojenia, časový limit) pokus zopakujeme 1 min, 5 min, 30 min, 2 h, 6 h,
12 h a 24 h po prvom pokuse — 8 pokusov počas
24 hodín. Ak zlyhajú všetky pokusy, doručovanie sa zastaví a koncový bod
sa v koncových bodoch webhookov označí stavom
status="failing". Vráťte 2xx hneď po trvalom prijatí
payloadu; spracujte ho asynchrónne.
Poradie
Poradie doručovania je v rámci možností zachované. V praxi doručujeme v
poradí, v akom sú udalosti emitované, ale opakovania môžu pri zlyhaní poradie zmeniť.
Vždy odstráňte duplicity a zosúlaďte údaje podľa call_id / ID objektu.
Duplikáty
Doručovanie je aspoň raz: opakovanie po odpovedi, ktorú sme nikdy
nezaznamenali, môže vytvoriť duplicitnú udalosť. Každé opakovanie obsahuje rovnaké
event_id, preto ukladajte spracované ID a preskakujte opakovania. event_id je
zdieľané aj medzi koncovými bodmi — dva koncové body prihlásené na odber rovnakej
udalosti dostanú rovnaké event_id.
Časové limity
Doručovanie do koncových bodov má časový limit 30 s na pokus. V staršej ceste
blokujúce požiadavky, ktoré riadia správanie aktívneho hovoru —
výmena konfigurácie telephony.incoming / web.incoming —
vypršia po 10 s, ale pomalá odpoveď oneskorí prijatie hovoru, preto sa snažte
odpovedať do niekoľkých sekúnd. Odosielanie nástrojov v režime webhooku
tool dispatch predvolene umožňuje 20 s a deklarácie nástrojov
môžu nastaviť timeout na najvyššej úrovni.
Zdrojové IP adresy
Odchádzajúce webhooky pochádzajú z cloudového rozsahu IP adries ThunderPhone. Ak váš firewall vyžaduje zoznam povolených adries, kontaktujte podporu a poskytneme vám aktuálne rozsahy.
Výber medzi staršími webhookmi a webhookmi založenými na koncových bodoch
| Funkcia | Staršie (/v1/webhook) | Koncové body (/v1/developer/webhook-endpoints) |
|---|---|---|
| Počet URL | 1 na organizáciu | Viac na organizáciu |
| Pokrytie udalostí | Len telephony.* / web.* | Všetkých 10 typov udalostí |
| Filter udalostí | — | Pre každý koncový bod |
| Opakovania | Žiadne | 8 pokusov počas 24 h |
| Obálka | type + data | type + data + event_id |
| Rotácia tajného kľúča | Nahrádza jediný tajný kľúč | Tajný kľúč pre každý koncový bod |
| Zakázanie bez odstránenia | PUT /v1/webhook s {"url": ""} | status=disabled |
| Viditeľnosť stavu | — | active / disabled / failing |
| Blokujúca výmena konfigurácie | Áno (telephony.incoming / web.incoming) | Nikdy — iba oznámenia |
| Najvhodnejšie pre | Dynamickú konfiguráciu hovorov | Spracovanie udalostí v produkcii |
Nové integrácie by mali udalosti spracúvať prostredníctvom webhookov založených na koncových bodoch. Staršiu URL ponechajte (alebo pridajte) len v prípade, že konfigurujete hovory dynamicky pri ich prijatí alebo používate odosielanie nástrojov v režime webhooku — tieto výmeny požiadaviek a odpovedí fungujú iba v staršej ceste.
Súvisiace
Všetky typy udalostí a ich payloady.
Spravujte viacero koncových bodov, filtre udalostí a tajné kľúče.
Blokujúca požiadavka, na ktorú musí váš server odpovedať, aby nakonfiguroval hovory.
Payload po hovore s prepisom, nahrávkou a metrikami.