Open in
Oversigt over webhooks
Sådan leverer ThunderPhone hændelser i realtid, hvordan du verificerer signaturer, og hvordan de ældre og endpoint-baserede leveringsmodeller sammenlignes.
ThunderPhone sender HTTP-POST-anmodninger til din server, når der sker
noget under et opkald — et indgående opkald starter, et opkald slutter, en
evalueringskørsel fuldføres, en alarm udløses osv. Der er to
leveringsmodeller:
Flere URL'er, hemmeligheder pr. slutpunkt, hændelsesfiltre pr. slutpunkt
og automatiske genforsøg.
Administrer via GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints.
Én URL pr. organisation. Indeholder opkaldslivscyklushændelserne, herunder
de blokerende konfigurationsudvekslinger. Administreres via GET/PUT /v1/webhook.
Alle angivne hændelsestyper i hændelseskataloget leveres
via webhook-slutpunkter. De seks opkaldslivscyklushændelser
(telephony.incoming, telephony.complete, telephony.tool,
web.incoming, web.complete, web.tool) sendes også til den
ældre webhook med enkelt URL — hvis du både har en ældre URL og et
matchende slutpunkt, modtager du hændelsen på begge stier. Blokerende
adfærd (telephony.incoming / web.incoming-konfigurationsudvekslingen
og værktøjsafsendelse i webhooktilstand)
findes udelukkende på den ældre sti; hver levering til et slutpunkt er en
fire-and-forget-notifikation.
Payloadformat
Leveringer til slutpunkter er et JSON-objekt med data, event_id og
type:
{
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
},
"event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
"type": "telephony.incoming"
}event_id er unik for hver udsendt hændelse. Den er identisk på tværs af genforsøg
og på tværs af hvert slutpunkt, der modtager hændelsen — dedupliker efter den.
Den ældre webhook med enkelt URL sender samme type og data, men
uden event_id:
{
"type": "telephony.incoming",
"data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}På netværket serialiseres hver body kanonisk — nøgler sorteres alfabetisk, uden mellemrum, UTF-8. De formaterede eksempler i denne dokumentation er kun for læsbarhed.
Se hændelseskataloget for den fulde liste over hændelsestyper og payloadfelter.
Signaturverificering
Hver anmodning indeholder to signaturer, begge HMAC-SHA256 med endpointets
secret som nøgle (eller din organisations webhook-secret for ældre
leveringer):
X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex>signerer tidsstemplet, metoden, stien og forespørgslen samt den rå body. Verificer denne, og afvis anmodninger, hvister mere end 5 minutter fra dit ur, så en opsnappet anmodning ikke kan afspilles igen senere. Gentagelser signeres igen, når de sendes.X-ThunderPhone-Signaturesignerer kun den rå body. Den sendes stadig uændret, så eksisterende verifikatorer fortsat fungerer.
Trin
- Læs headeren, metoden, den rå sti og forespørgsel samt den rå body før enhver parsing.
- Beregn den hexadecimale HMAC-SHA256 for
<t>\n<METHOD>\n<path and query>\n<body>med din hemmelighed. - Afvis anmodningen, hvis
tafviger med mere end 300 sekunder, eller hvis resultatet ikke matcherv1i en sammenligning med konstant tid.
Bodies er den kanoniske JSON-serialisering (sorterede nøgler, kompakte separatorer), og vi signerer nøjagtigt de bytes, vi sender. Guiden til verificering indeholder den nøjagtige signerede streng, et gennemarbejdet eksempel, kode uden SDK'et og den ældre header.
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);
},
);Leveringssemantik
Disse semantikker gælder for leverancer til endpoint. Den ældre webhook med én URL
er ét synkront forsøg uden genforsøg, bortset fra
konfigurationsudvekslingen for telefonopkaldet
telephony.incoming, som genforsøges én gang.
Genforsøg
Hver hændelse forsøges leveret én gang med det samme. Ethvert 2xx-svar
bekræfter leverancen. Ved ethvert andet udfald (ikke-2xx,
forbindelsesfejl, timeout) genforsøger vi efter 1 m, 5 m, 30 m, 2 h, 6 h,
12 h og 24 h efter det første forsøg — 8 forsøg fordelt over
24 timer. Hvis alle forsøg fejler, stopper leverancen, og endpointet
markeres med status="failing" i
webhook-endpoints; vi sender en e-mail til din organisations
ejere og administratorer og viser det i dashboardet. Returner 2xx, så snart
payloaden er accepteret varigt; behandl den asynkront.
Testafsendelser fra endpoint-test-API'et får ét genforsøg cirka et minut efter
det første forsøg og ændrer aldrig endpointets status.
Rækkefølge
Leveringsrækkefølgen er efter bedste evne. I praksis leverer vi i den
rækkefølge, hændelser udsendes, men genforsøg kan ændre rækkefølgen ved fejl.
Dedupliker og afstem altid efter call_id / objekt-id.
Dubletter
Levering er mindst én gang: et genforsøg efter et svar, vi aldrig
modtog, kan duplikere en hændelse. Hvert genforsøg har samme
event_id, så gem behandlede id'er, og spring gentagelser over. event_id deles
også på tværs af endepunkter — to endepunkter, der abonnerer på den
samme hændelse, modtager den samme event_id.
Timeouts
Leverancer til endpoints har en timeout på 30 s pr. forsøg. På den
ældre sti er blokerende anmodninger, der styrer aktiv opkaldsadfærd —
konfigurationsudvekslingen
telephony.incoming / web.incoming —
begrænset til 10 s for et telefonopkalds første forsøg og 13 s
for hele udvekslingen inklusive det ene genforsøg, og til 10 s for
en widgetsession. Et langsomt svar forsinker besvarelsen af opkaldet,
så sigt efter at svare inden for et par sekunder. Værktøjsafsendelse i webhooktilstand tillader 20 s
som standard, og værktøjsdeklarationer kan angive en timeout på øverste niveau.
Kilde-IP'er
Udgående webhooks kommer fra ThunderPhones cloud-IP-område. Hvis din firewall kræver en tilladelsesliste, skal du kontakte support, så deler vi de aktuelle områder.
Valg mellem ældre og endepunktbaserede webhooks
| Funktion | Ældre (/v1/webhook) | Endepunkter (/v1/developer/webhook-endpoints) |
|---|---|---|
| Antal URL'er | 1 pr. organisation | Mange pr. organisation |
| Hændelsesdækning | Kun telephony.* / web.* | Alle 10 hændelsestyper |
| Hændelsesfilter | — | Pr. endepunkt |
| Genforsøg | Ingen, undtagen ét for konfigurationsudvekslingen for telefonopkald | 8 forsøg over 24 timer |
| Konvolut | type + data | type + data + event_id |
| Rotation af hemmelighed | Erstatter én hemmelighed | Hemmelighed pr. endepunkt |
| Deaktiver uden at slette | PUT /v1/webhook med {"url": ""} | status=disabled |
| Synlighed af status | — | active / disabled / failing |
| Blokerende konfigurationsudveksling | Ja (telephony.incoming / web.incoming) | Aldrig — kun notifikationer |
| Bedst til | Dynamisk opkaldskonfiguration | Hændelsesforbrug i produktion |
Nye integrationer bør forbruge hændelser via endepunktbaserede webhooks. Behold (eller tilføj) kun en ældre URL, hvis du konfigurerer opkald dynamisk ved besvarelse eller bruger værktøjsafvikling i webhooktilstand — disse anmodnings-/svarudvekslinger kører kun på den ældre sti.
Relateret
Alle hændelsestyper og deres nyttelaster.
Administrer flere slutpunkter, hændelsesfiltre og hemmeligheder.
Den blokerende anmodning, din server skal besvare for at konfigurere opkald.
Nyttelast efter opkald med transskription, optagelse og målinger.