ThunderPhone 2.0 er lansert.Kom i gang selv – fra 2¢/min.Les mer om lanseringen

Webhooks

Oversikt over webhooks

Slik leverer ThunderPhone hendelser i sanntid, slik verifiserer du signaturer, og slik sammenlignes de eldre og endepunktbaserte leveringsmodellene.

ThunderPhone sender HTTP-POST-forespørsler til serveren din når ting skjer under en samtale — et innkommende anrop starter, en samtale avsluttes, en vurderingskjøring fullføres, et varsel utløses og så videre. Det finnes to leveringsmodeller:

Alle oppførte hendelsestyper i hendelseskatalogen leveres gjennom webhook-endepunkter. De seks hendelsene i samtalens livssyklus (telephony.incoming, telephony.complete, telephony.tool, web.incoming, web.complete, web.tool) sendes også til den eldre webhooken med én URL — hvis du har både en eldre URL og et matchende endepunkt, mottar du hendelsen på begge banene. Blokkerende atferd (telephony.incoming- / web.incoming-konfigurasjonsutvekslingen og verktøysdistribusjon i webhook-modus) finnes utelukkende på den eldre banen; hver levering til et endepunkt er en fire-and-forget-varsling.

Nyttelastformat

Leveringer til endepunkter 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 utsendte hendelse. Den er identisk på tvers av nye forsøk og på tvers av hvert endepunkt som mottar hendelsen — dedupliser på den.

Den eldre webhooken med én URL sender samme type og data, men uten event_id:

{
  "type": "telephony.incoming",
  "data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}

På nettverket serialiseres hver body kanonisk — nøkler sortert alfabetisk, ingen mellomrom, UTF-8. Eksemplene med pen formatering i denne dokumentasjonen er kun for lesbarhet.

Se hendelseskatalogen for hele listen over hendelses- typer og nyttelastfelt.

Signaturverifisering

Hver forespørsel har to signaturer, begge HMAC-SHA256 med endepunktets secret som nøkkel (eller webhookens secret på organisasjonsnivå for eldre leveringer):

  • X-ThunderPhone-Signature-V2: t=<unix seconds>,v1=<hex> signerer tidsstempelet, metoden, banen og spørringen samt råteksten. Verifiser denne, og avvis forespørsler der t avviker med mer enn 5 minutter fra klokken din, slik at en oppfanget forespørsel ikke kan spilles av på nytt senere. Nye forsøk signeres på nytt når de sendes.
  • X-ThunderPhone-Signature signerer bare råteksten. Den sendes fortsatt uendret, slik at eksisterende verifiseringsprogrammer fortsetter å fungere.

Trinn

  1. Les headeren, metoden, den rå stien og spørringen samt den rå brødteksten før eventuell parsing.
  2. Beregn den heksadesimale HMAC-SHA256-verdien av <t>\n<METHOD>\n<path and query>\n<body> med hemmeligheten din.
  3. Avvis forespørselen hvis t avviker med mer enn 300 sekunder, eller hvis resultatet ikke samsvarer med v1 i en sammenligning med konstant tid.

Brødtekster er den kanoniske JSON-serialiseringen (sorterte nøkler, kompakte skilletegn), og vi signerer nøyaktig byteverdiene vi overfører. Veiledningen for verifisering inneholder den nøyaktige signerte strengen, et gjennomarbeidet eksempel, kode uten SDK-en og den eldre headeren.

Python (Flask)
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 "", 204
Node.js (Express)
import 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);
  },
);

Leveringssemantikk

Disse semantikkene gjelder leveringer til endepunkt. Den eldre webhooken med én URL er ett synkront forsøk uten gjenforsøk, med unntak av konfigurasjonsutvekslingen for telefonsamtaler telephony.incoming, som forsøkes på nytt én gang.

Gjenforsøk

Hver hendelse forsøkes levert umiddelbart én gang. Ethvert 2xx-svar bekrefter leveringen. Ved ethvert annet utfall (ikke-2xx, tilkoblingsfeil, tidsavbrudd) prøver vi på nytt etter 1 min, 5 min, 30 min, 2 t, 6 t, 12 t og 24 t etter første forsøk — 8 forsøk fordelt over 24 timer. Hvis alle forsøk mislykkes, stopper leveringen, og endepunktet merkes med status="failing" i webhook-endepunkter; vi sender e-post til eierne og administratorene i organisasjonen din og viser det i dashbordet. Returner 2xx så snart nyttelasten er mottatt og lagret varig; behandle den asynkront. Testforsendelser fra endepunktets test-API får ett gjenforsøk omtrent ett minutt etter første forsøk og endrer aldri endepunktets status.

Rekkefølge

Leveringsrekkefølgen er etter beste evne. I praksis leverer vi i rekkefølgen hendelser sendes ut, men nye forsøk kan endre rekkefølgen ved feil. Dedupliser og avstem alltid etter call_id / objekt-ID.

Duplikater

Levering er minst én gang: et nytt forsøk etter et svar vi aldri mottok, kan duplisere en hendelse. Hvert nye forsøk har samme event_id, så lagre behandlede ID-er og hopp over gjentakelser. event_id er også delt på tvers av endepunkter — to endepunkter som abonnerer på den samme hendelsen, mottar samme event_id.

Tidsavbrudd

Leveringer til endepunkter har et tidsavbrudd på 30 s per forsøk. På den eldre ruten er blokkerende forespørsler som styrer oppførselen til aktive samtaler — konfigurasjonsutvekslingen telephony.incoming / web.incoming — begrenset til 10 s for en telefonsamtales første forsøk og 13 s for hele utvekslingen, inkludert det ene gjenforsøket, og til 10 s for en widgetøkt. Et tregt svar forsinker besvarelsen av samtalen, så sikt mot å svare innen et par sekunder. Utsending av verktøykall i webhook-modus tillater 20 s som standard, og verktøydeklarasjoner kan angi et overordnet timeout.

Kilde-IP-er

Utgående webhooks kommer fra ThunderPhones sky-IP-område. Hvis brannmuren din krever en tillatelsesliste, kontakt kundestøtte, så deler vi de gjeldende intervallene.

Velge mellom eldre og endepunktbaserte webhooks

FunksjonEldre (/v1/webhook)Endepunkter (/v1/developer/webhook-endpoints)
Antall URL-er1 per organisasjonMange per organisasjon
HendelsesdekningKun telephony.* / web.*Alle 10 hendelsestyper
Hendelsesfilter—Per endepunkt
Nye forsøkIngen, unntatt ett for utveksling av telefonanropskonfigurasjon8 forsøk over 24 t
Konvolutttype + datatype + data + event_id
Rotering av hemmelighetErstatter én hemmelighetHemmelighet per endepunkt
Deaktiver uten å slettePUT /v1/webhook med {"url": ""}status=disabled
Statustilgjengelighet—active / disabled / failing
Blokkerende konfigurasjonsutvekslingJa (telephony.incoming / web.incoming)Aldri — kun varsler
Best forDynamisk anropskonfigurasjonHendelsesmottak i produksjon

Nye integrasjoner bør motta hendelser gjennom endepunktbaserte webhooks. Behold (eller legg til) en eldre URL bare hvis du konfigurerer samtaler dynamisk når de besvares, eller bruker verktøysdirigering i webhook-modus — disse forespørsels-/svarutvekslingene kjører bare på den eldre ruten.


Relatert