Open in
Přehled webhooků
Jak ThunderPhone doručuje události v reálném čase, jak ověřovat podpisy a jak se porovnávají starší model doručování a model založený na koncových bodech.
ThunderPhone odesílá na váš server požadavky HTTP POST, když během hovoru
nastanou události — začne příchozí hovor, hovor skončí, dokončí se
vyhodnocení, aktivuje se upozornění a podobně. Existují dva modely
doručování:
Více URL, tajné klíče pro jednotlivé koncové body, filtry událostí pro jednotlivé koncové body
a automatické opakování pokusů.
Spravujte pomocí GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.
Jedna URL pro každou organizaci. Obsahuje události životního cyklu hovoru včetně
blokujících výměn konfigurace. Spravuje se pomocí GET/PUT /v1/webhook.
Všechny uvedené typy událostí v katalogu událostí se
doručují prostřednictvím koncových bodů webhooků. Šest událostí životního cyklu hovoru
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) se také odesílá do
staršího webhooku s jednou URL — pokud máte starší URL i odpovídající
koncový bod, obdržíte událost na obou cestách. Blokující
chování (výměna konfigurace telephony.incoming / web.incoming
a odesílání nástrojů v režimu webhooku)
je dostupné výhradně na starší cestě; každé doručení do koncového bodu je
oznámení typu fire-and-forget.
Formát datové části
Doručení do koncového bodu jsou objektem JSON s 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é pro každou odeslanou událost. Je totožné při opakovaných pokusech
i ve všech koncových bodech, které událost obdrží — deduplikujte podle něj.
Starší webhook s jednou URL odesílá stejné type a data, ale
bez event_id:
{
"type": "telephony.incoming",
"data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}Při přenosu je každá datová část serializována kanonicky — klíče jsou řazeny abecedně, bez mezer, v kódování UTF-8. Příklady s formátováním v této dokumentaci slouží pouze pro lepší čitelnost.
Úplný seznam typů událostí a polí datové části naleznete v katalogu událostí.
Ověření podpisu
Každý požadavek obsahuje dva podpisy, oba HMAC-SHA256 s klíčem secret
koncového bodu (nebo secret webhooku na úrovni vaší organizace pro starší
doručování):
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex>podepisuje časové razítko, metodu, cestu a dotaz a nezpracované tělo. Ověřte tento podpis a odmítněte požadavky, jejichžtse liší od vašich hodin o více než 5 minut, aby zachycený požadavek nemohl být později znovu přehrán. Při opakovaném odeslání jsou pokusy podepsány znovu.X-ThunderPhone-Signaturepodepisuje pouze nezpracované tělo. Stále se odesílá beze změny, aby stávající ověřovače nadále fungovaly.
Kroky
- Před jakýmkoli parsováním načtěte hlavičku, metodu, nezpracovanou cestu a dotaz a nezpracované tělo.
- Pomocí svého tajného klíče vypočítejte hexadecimální HMAC-SHA256 z
<t>\n<METHOD>\n<path and query>\n<body>. - Požadavek odmítněte, pokud se
tliší o více než 300 sekund nebo pokud se výsledek při porovnání v konstantním čase neshoduje sv1.
Těla jsou kanonickou serializací JSON (seřazené klíče, kompaktní oddělovače) a podepisujeme přesně ty bajty, které přenášíme. Průvodce ověřením obsahuje přesný podepisovaný řetězec, praktický příklad, kód bez SDK a starší hlavičku.
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);
},
);Sémantika doručování
Tyto sémantiky se vztahují na doručování do endpointů. Starší webhook s jednou adresou URL provede jeden synchronní pokus bez opakování, s výjimkou výměny konfigurace telefonního hovoru
telephony.incoming,
která se opakuje jednou.
Opakování
Každá událost se ihned zkusí doručit jednou. Jakákoli odpověď 2xx
potvrzuje doručení. Při jakémkoli jiném výsledku (jiné než 2xx,
chyba připojení, časový limit) doručení zopakujeme 1 m, 5 m, 30 m, 2 h, 6 h,
12 h a 24 h po prvním pokusu — celkem 8 pokusů během
24 hodin. Pokud selžou všechny pokusy, doručování se zastaví a endpoint
se v endpointech webhooků označí jako
status="failing"; vlastníkům a administrátorům vaší organizace
odešleme e-mail a zobrazíme to v dashboardu. Vraťte 2xx, jakmile je
datová část trvale přijata; zpracujte ji asynchronně.
Testovací odeslání z testovacího API endpointu dostanou jedno opakování přibližně minutu po
prvním pokusu a nikdy nezmění stav endpointu.
Pořadí
Pořadí doručování není zaručeno. V praxi doručujeme události v
pořadí, v jakém jsou emitovány, ale opakování může při selhání pořadí změnit.
Vždy odstraňujte duplicity a slaďujte data podle call_id / ID objektu.
Duplicity
Doručování je alespoň jednou: opakování po odpovědi, kterou jsme
neobdrželi, může vytvořit duplicitní událost. Každé opakování nese stejné
event_id, proto ukládejte ID zpracovaných událostí a opakování přeskakujte. event_id je
také sdíleno mezi koncovými body — dva koncové body přihlášené ke
stejné události obdrží stejné event_id.
Časové limity
Doručení do endpointů mají časový limit 30 s na pokus. Ve
starší cestě jsou blokující požadavky, které řídí chování probíhajícího hovoru —
výměna konfigurace
telephony.incoming / web.incoming —
omezeny na 10 s pro první pokus telefonního hovoru a na 13 s pro celou výměnu včetně
jednoho opakování a na 10 s pro relaci widgetu. Pomalá odpověď zpozdí
přijetí hovoru, proto se snažte odpovědět během několika sekund. Spouštění nástrojů v režimu webhooku
ve výchozím nastavení umožňuje 20 s a deklarace nástrojů mohou nastavit timeout nejvyšší úrovně.
Zdrojové IP adresy
Odchozí webhooky pocházejí z rozsahu cloudových IP adres ThunderPhone. Pokud váš firewall vyžaduje seznam povolených adres, kontaktujte podporu a my vám sdělíme aktuální rozsahy.
Volba mezi staršími webhooky a webhooky založenými na koncových bodech
| Funkce | Starší (/v1/webhook) | Koncové body (/v1/developer/webhook-endpoints) |
|---|---|---|
| Počet URL | 1 na organizaci | Více na organizaci |
| Pokrytí událostí | Pouze telephony.* / web.* | Všech 10 typů událostí |
| Filtr událostí | — | Pro každý koncový bod |
| Opakování | Žádné, kromě jednoho při výměně konfigurace telefonního hovoru | 8 pokusů během 24 h |
| Obálka | type + data | type + data + event_id |
| Rotace tajného klíče | Nahrazuje jeden tajný klíč | Tajný klíč pro každý koncový bod |
| Zakázání bez odstranění | PUT /v1/webhook s {"url": ""} | status=disabled |
| Viditelnost stavu | — | active / disabled / failing |
| Blokující výměna konfigurace | Ano (telephony.incoming / web.incoming) | Nikdy — pouze oznámení |
| Nejvhodnější pro | Dynamickou konfiguraci hovorů | Zpracování událostí v produkci |
Nové integrace by měly zpracovávat události prostřednictvím webhooků založených na koncových bodech. Starší adresu URL ponechte (nebo přidejte) pouze v případě, že hovory konfigurujete dynamicky při jejich přijetí nebo používáte odesílání nástrojů v režimu webhooků — tyto výměny požadavků a odpovědí fungují pouze ve starší cestě.
Související
Všechny typy událostí a jejich datové obsahy.
Spravujte více koncových bodů, filtry událostí a tajné klíče.
Blokující požadavek, na který musí váš server odpovědět, aby nakonfiguroval hovory.
Datový obsah po hovoru s přepisem, nahrávkou a metrikami.