ThunderPhone 2.0 er lanceret.Selvbetjening fra 2 cent pr. minut.Læs mere om lanceringen

Webhooks

telephony.incoming / web.incoming

Blokerende webhook, der former konfigurationen for et indgående opkald i realtid.

Når et indgående telefonopkald når et nummer uden en tilknyttet agent, eller en webwidgetsession starter på en publicerbar nøgle i mode="webhook", sender ThunderPhone en blokerende telephony.incoming / web.incoming-anmodning til din ældre webhook-URL og venter på et konfigurationssvar: op til 13 sekunder for et telefonopkald, inklusive ét genforsøg, og op til 10 sekunder for en widgetsession (se Timeouts and retries). Brug denne udveksling til dynamisk at vælge en prompt, stemme og værktøjer pr. opkald — se vejledningen til dynamisk opkaldskonfiguration for det fulde mønster.

Tidsgrænser og genforsøg

Svar hurtigt: Personen, der ringer, venter på linjen, mens du beslutter dig.

For et telefonopkald (telephony.incoming):

  • Det første forsøg kan tage op til 10 sekunder.
  • Hvis det får timeout, ikke kan oprette forbindelse eller modtager et 5xx-, 408- eller 429-svar, prøver ThunderPhone én gang til. Genforsøget får den resterende tid af et budget på 13 sekunder for hele udvekslingen: omkring 3 sekunder efter et første forsøg med timeout, næsten alle 13 efter en hurtig fejl. Der foretages ikke noget genforsøg, hvis der ville være mindre end 2 sekunder tilbage.
  • Ethvert andet 4xx-svar, et svar over størrelsesgrænsen eller et 2xx-svar, hvis brødtekst ikke er en gyldig konfiguration, er endeligt og prøves ikke igen.
  • Begge forsøg sender den samme brødtekst, den samme X-ThunderPhone-Signature og den samme X-ThunderPhone-Idempotency-Key-header (telephony-incoming-<call_id>), så en handler med bivirkninger kan genkende genforsøget.

Der er ingen fallback-agent. Hvis der ikke modtages en brugbar konfiguration, afsluttes opkaldet straks i stedet for at lade personen, der ringer, vente på en stille linje. Det vises i opkaldshistorikken som et mislykket, ikke-faktureret opkald med end_reason inbound_config_webhook_failed, og det sædvanlige telephony.complete-event sendes.

En widgetsession (web.incoming) får ét forsøg på op til 10 sekunder. Hvis det mislykkes, mislykkes sessionsanmodningen med 502 eller 422.

Anmodningspayload

For telefonopkald (telephony.incoming):

{
  "type": "telephony.incoming",
  "data": {
    "call_id":     987654321,
    "from_number": "+14155550199",
    "to_number":   "+15551234567"
  }
}
FeltTypeBeskrivelse
call_idintegerOpkalds-id — stabilt på tværs af alle hændelser for dette opkald
from_numberstringOpkaldernummer i E.164-format
to_numberstringDestination i E.164-format (et af dine ThunderPhone-numre)

For webwidgetsessioner (web.incoming) identificerer data indlejringssiden i stedet for telefonnumre:

{
  "type": "web.incoming",
  "data": {
    "call_id": 987654322,
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2"
  }
}
FeltTypeBeskrivelse
call_idintegerOpkalds-id
origin_domainstringSidens oprindelse, der hoster widgetten, som browseren sendte den. En klient, der ikke er en browser, kan sende en vilkårlig værdi, så betragt den ikke som bevis på, hvor anmodningen kom fra
publishable_key_prefixstringFørste tegn i den publicerbare nøgle, der åbnede sessionen
language, primary_languagestringFindes, når widgetsessionen har anmodet om en sprogtilsidesættelse
voicestringFindes, når widgetsessionen har anmodet om en stemmetilsidesættelse
website_contextstringFindes, når widgetten har sendt sidekontekst pr. session

Tilsidesættelsesfelterne (language, voice, website_context og eventuelle browser-variables) ankommer kun, når den publicerbare nøgle tillader dem i sine browsertilsidesættelser. En sessionsanmodning med en tilsidesættelse, som nøglen ikke tillader, afvises, før denne webhook kaldes.


Svarskema

Returner et JSON-objekt, der beskriver agentkonfigurationen for dette opkald. prompt og voice er påkrævede; alt andet er valgfrit.

{
  "prompt":  "You are a helpful booking assistant for Acme Restaurant.",
  "voice":   "john",
  "product": "spark",
  "background_track": null,
  "tools":   []
}
FeltTypePåkrævetBeskrivelse
promptstrengjaSystemprompt, der styrer agenten
voicestrengjaStemme-id fra GET /v1/voices, f.eks. john. voice_name accepteres som et alias. Ukendte stemmer fejler validering og afviser opkaldet
productstrengnejStandard er spark. Tilladt: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack
thinking_levelstrengnejminimal, base (standard) eller extra. Tilsidesættes for Storm-produkter: storm-extra* tvinger extra, andre storm-* tvinger base
audio_context_modestrengnejfull (standard) eller reduced
watchdog_enabledboolesknejAktivér overvågning for dette opkald. Standard er false
additional_audio_contextboolesk | nullnejMedtag de seneste par runder af opkalderens lyd i stedet for kun den seneste runde, hvilket forbedrer rettelser og indsamling af data med mange stavemåder eller tal med en lille meromkostning i latenstid og pris. Er som standard slået til for indgående sessioner og slået fra for udgående telefonopkald; null bevarer standardindstillingen
storm_feedback_modestrengnejnone, acknowledgement (standard) eller tick. Angiver også, hvad opkalderen hører, mens lydmodellerne behandler en runde, når audio_tier er hearing
languagestrengnejForkortelse for primary_language
primary_languagestrengnejSprogkode, normaliseret (standard er en). Koder, der ikke kan fortolkes, afviser opkaldet
has_additional_languagesboolesknejStandard er false
additional_languagesarray af strengenejEkstra sprog, som agenten kan skifte til
native_voice_switchingboolesknejStandard er false. Når opkaldet skifter til et andet sprog, skal der skiftes til en stemme med det pågældende sprog som modersmål (matchet efter køn) i stedet for at beholde den konfigurerede stemme
language_switchingstreng | nullnejask_first (standard) eller follow_caller; null er det samme som ask_first. Angiver, hvordan en flersproget agent håndterer, at den anden person taler et andet af dens sprog. ask_first skifter straks, når personen beder om sproget eller siger en hel sætning på det, og spørger, om samtalen skal fortsætte på det efter noget kort, som et "ja". follow_caller skifter til ethvert konfigureret sprog, personen taler, selv ved et enkelt ord. Gælder kun, når additional_languages er angivet
audio_tierstreng | nullnejKun product: "bolt". standard (standard; "" og null betyder det samme) kører tre transskriberingsmodeller (opkald, der behandler PHI, bruger kun BAA-dækkede transskriberingsmodeller). lean nedgraderer til én transskriberingsmodel, som fejlhører oftere. hearing opgraderer til standard plus et kraftfuldt ensemble af lydmodeller, der lytter til opkalderens lyd i nogle runder, som tager ca. 1–2 sekunder længere. Andre produkter ignorerer det
endpointingstreng | nullnejfaster (200 ms), fast (300 ms), normal (500 ms, standard) eller patient (800 ms); null er det samme som normal. Angiver, hvor længe en Bolt v2-agent venter, efter opkalderen stopper, før modellen bedes om et svar. Kortere ventetid kan svare hurtigere, men sender flere anmodninger, som opkalderens næste ord gør forældede, hvilket øger modelomkostningen. Andre produkter ignorerer det
eagernessstreng | nullnejForældet: navnet på endpointing indtil 19. oktober 2026, læses stadig. Ignoreres, når endpointing er angivet
intelligencestreng | nullnejexpress, lite eller standard (standard); null er det samme som standard. Intelligensniveauet for en bolt-agent på Bolt v2-pipelinen: hvilken model der skriver dens svar. express bruger ca. 600 ms til første ord, er billigere end Standard og følger instruktioner mindst pålideligt; lite bruger ca. 900 ms, er billigst og mindre pålidelig; standard bruger ca. 900 ms og er bedst til at følge instruktioner. Express- og Lite-svar, der kun ville kalde et værktøj, sendes videre til Standard-modellen. Andre produkter ignorerer det
background_trackstreng | nullnejId for baggrundslyd eller null
acknowledgement_prompt_modestrengnejauto (standard) eller manual (Storm-with-ack-produkter)
acknowledgement_promptstrengnejBruges, når acknowledgement_prompt_mode="manual"
silence_interval_secondsheltal | nullnej5–120. Sekunder med stilhed fra opkalderen før en opfølgning
silence_max_checkinsheltal | nullnej1–10
silence_checkins_enabledboolesknejStandard er true
silence_final_actionstrengnejEfter den sidste opfølgning: hang_up (standard) eller transfer til silence_transfer_destination
silence_transfer_destinationstrengnejNavn på en post i denne konfigurations transfer_destinations; kræves med transfer. Uden transfer_destinations kan viderestillingen ikke gennemføres, og agenten lægger på
silence_final_messagestrengnej≤ 300 tegn, læses op som skrevet; "" (standard) bruger standardlinjen
connect_tone_enabledboolesknejStandard er false
pronunciation_dictsboolesk | nullnejStandard er false; null er det samme som false. Når værdien er true, bruger opkaldets Cartesia-tale ThunderPhones udtaleordbog for opkaldets sprog, hvor en findes. Fungerer for telefon- og widgetopkald. Gælder kun ThunderPhones egne Cartesia-stemmer, ikke stemmer på din egen Cartesia API-nøgle. Bruges ikke med agent_id, hvor den gemte agents indstillinger gælder
voicemail_actionstrengnejprompt (standard), hangup eller message
voicemail_messagestrengnejBruges, når voicemail_action="message"
agent_namestrengnejVisningsnavn, der rapporteres til dashboards og widgetten
org_namestrengnejOrganisationens visningsnavn for agentens persona
toolsarraynejIntegrerede skemaer for funktionsværktøjer (se Funktionsværktøjer)
transfer_destinationsarray af objekt | nullnejOp til 50 poster med {name, number}, som dette opkald kan viderestilles til, valideret som en agents viderestillingsnumre. Agenten viderestiller efter navn og kun til disse; [] betyder ingen viderestillinger. Udelad feltet eller send null for at lade agenten viderestille til et nummer, den vælger
timezonestrengnejIANA-tidszone for dette opkald, f.eks. America/Chicago. Agenten angiver dato og klokkeslæt i den frem for agentens egen tidszone. Tilladt også sammen med agent_id. Værdier, der ikke er IANA-zoner, ignoreres. Se Angiv tidszonen pr. opkald
call_idheltalnejValgfrit ekko af anmodningens opkalds-id; ignoreres

Da prompt og voice er påkrævet, afviser returnering af {} eller et svar, der fejler valideringen, opkaldet: Et telefonopkald afsluttes som beskrevet i Timeouts og genforsøg, og en widget-sessionsforespørgsel fejler med 422. Der er ingen fallback til en statisk agent på denne sti (et nummer eller en nøgle i webhook-tilstand har ingen tildelt agent).


Grænse for svarstørrelse


Eksempel på handler

Python (FastAPI)
import hashlib
import hmac
import json
import os
 
from fastapi import FastAPI, HTTPException, Request
 
app = FastAPI()
WEBHOOK_SECRET = os.environ["THUNDERPHONE_WEBHOOK_SECRET"]
 
def verify(body: bytes, signature: str) -> bool:
    expected = hmac.new(WEBHOOK_SECRET.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature or "")
 
@app.post("/thunderphone-webhook")
async def webhook(request: Request):
    body = await request.body()
    if not verify(body, request.headers.get("X-ThunderPhone-Signature", "")):
        raise HTTPException(status_code=401)
 
    event = json.loads(body)
    if event["type"] == "telephony.incoming":
        caller = event["data"]["from_number"]
        prompt = (
            "Greet the caller as a San Francisco local…"
            if caller.startswith("+1415")
            else "You are a friendly customer support agent…"
        )
        return {
            "prompt": prompt,
            "voice": "john",
            "product": "spark",
        }
    if event["type"] == "web.incoming":
        return {
            "prompt": "You are the website's helpful voice assistant…",
            "voice": "john",
            "product": "spark",
        }
    return {}
Node.js (Express)
import crypto from "node:crypto";
import express from "express";
 
const app = express();
const SECRET = process.env.THUNDERPHONE_WEBHOOK_SECRET;
 
function verify(body, signature) {
  const expected = crypto
    .createHmac("sha256", SECRET)
    .update(body)
    .digest("hex");
  return signature &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
 
app.post(
  "/thunderphone-webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    if (!verify(req.body, req.header("X-ThunderPhone-Signature"))) {
      return res.sendStatus(401);
    }
    const event = JSON.parse(req.body.toString("utf8"));
 
    if (event.type === "telephony.incoming" || event.type === "web.incoming") {
      const caller = event.data.from_number || "web";
      const prompt = caller.startsWith("+1415")
        ? "Greet the caller as a San Francisco local…"
        : "You are a friendly customer support agent…";
      return res.json({
        prompt,
        voice: "john",
        product: "spark",
      });
    }
    res.json({});
  },
);

Svar med funktionsværktøjer

Tilknyt værktøjer, så AI'en kan kalde dine API'er midt i samtalen:

{
  "prompt":  "You are a booking assistant. Use the available tools to help customers schedule appointments.",
  "voice":   "john",
  "product": "spark",
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_appointments",
        "description": "Find available appointment slots",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "service": { "type": "string" }
          },
          "required": ["date"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/search",
        "method": "POST",
        "headers": {
          "X-Api-Key": "your-key"
        }
      }
    }
  ]
}

Produktniveauer – hurtig oversigt

ProduktLatensRæsonneringBekræftelse
sparkLavestGrundlæggende—
boltLavForbedret—
storm-baseMellemStærk—
storm-base-with-ackMellemStærkAutomatisk udfyldning, mens der tænkes
storm-extraHøjereDyb—
storm-extra-with-ackHøjereDybAutomatisk udfyldning, mens der tænkes

Relateret