telephony.incoming / web.incoming
Kui sissetulev telefonikõne jõuab numbrile ilma määratud
häälagendita või veebividina seanss käivitub avalikul võtmel režiimis
mode="webhook", saadab ThunderPhone sinu
pärand-webhooki URL-ile
blokeeriva päringu telephony.incoming / web.incoming ja ootab
konfiguratsioonivastust kuni 10 sekundit. Kasuta seda vahetust, et
valida iga kõne jaoks dünaamiliselt viip, hääl ja tööriistad — täieliku
mustri leiad dünaamilise kõnekonfiguratsiooni juhendist.
Blokeerival vahetusel puudub varuvariant: kui sinu töötleja tagastab
muu kui 2xx olekukoodi, aegub või tagastab valideerimist mitte läbiva
konfiguratsiooni, lükatakse kõne tagasi (telefonikõne ei ühendata;
vidina seansipäring nurjub koodiga 502/422). Vasta kiiresti —
helistaja kuuleb samal ajal kutsungitooni.
Päringu sisu
Telefonikõnede puhul (telephony.incoming):
{
"type": "telephony.incoming",
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}
| Väli | Tüüp | Kirjeldus |
|---|---|---|
call_id | integer | Kõne ID — püsib sama kõigi selle kõne sündmuste puhul |
from_number | string | Helistaja E.164 number |
to_number | string | E.164 sihtnumber (üks sinu ThunderPhone'i numbritest) |
Veebividina seansside puhul (web.incoming) tuvastab data
telefoninumbrite asemel vidinat manustava lehe:
{
"type": "web.incoming",
"data": {
"call_id": 987654322,
"origin_domain": "https://example.com",
"publishable_key_prefix": "pk_live_a1b2"
}
}
| Väli | Tüüp | Kirjeldus |
|---|---|---|
call_id | integer | Kõne ID |
origin_domain | string | Vidinat majutava lehe päritolu |
publishable_key_prefix | string | Seansi avanud avaliku võtme esimesed märgid |
language, primary_language | string | Olemas, kui veebiseanss taotles keele ülekirjutamist |
voice | string | Olemas, kui veebiseanss taotles hääle ülekirjutamist |
website_context | string | Olemas, kui vidin edastas seansipõhise lehekonteksti |
Vastuse skeem
Tagasta JSON-objekt, mis kirjeldab selle kõne häälagendi konfiguratsiooni.
prompt ja voice on kohustuslikud; kõik muu on valikuline.
{
"prompt": "You are a helpful booking assistant for Acme Restaurant.",
"voice": "john",
"product": "spark",
"background_track": null,
"tools": []
}
| Väli | Tüüp | Kohustuslik | Kirjeldus |
|---|---|---|---|
prompt | string | jah | Häälagenti juhtiv süsteemiprompt |
voice | string | jah | Hääle ID asukohast GET /v1/voices, nt john. Aliaseks aktsepteeritakse voice_name. Tundmatud hääled ei läbi valideerimist ja kõne lükatakse tagasi |
product | string | ei | Vaikeväärtus on spark. Lubatud: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack |
thinking_level | string | ei | minimal, base (vaikeväärtus) või extra. Stormi toodete puhul kirjutatakse üle: storm-extra* sunnib kasutama extra, muud storm-* sunnivad kasutama base |
audio_context_mode | string | ei | full (vaikeväärtus) või reduced |
watchdog_enabled | boolean | ei | Luba selle kõne järelevalve. Vaikeväärtus on false |
storm_feedback_mode | string | ei | none, acknowledgement (vaikeväärtus) või tick |
language | string | ei | Lühivorm väärtusele primary_language |
primary_language | string | ei | Keelekood, normaliseeritud (vaikeväärtus en). Lahendamatud koodid lükkavad kõne tagasi |
has_additional_languages | boolean | ei | Vaikeväärtus on false |
additional_languages | array of string | ei | Lisakeeled, millele häälagent võib ümber lülituda |
background_track | string | null | ei | Taustaheli ID või null |
acknowledgement_prompt_mode | string | ei | auto (vaikeväärtus) või manual (Storm-with-ack toodetele) |
acknowledgement_prompt | string | ei | Kasutatakse, kui acknowledgement_prompt_mode="manual" |
silence_interval_seconds | integer | null | ei | 5–120. Helistaja vaikuse sekundid enne kontrollpäringut |
silence_max_checkins | integer | null | ei | 1–10 |
silence_checkins_enabled | boolean | ei | Vaikeväärtus on true |
connect_tone_enabled | boolean | ei | Vaikeväärtus on false |
voicemail_action | string | ei | prompt (vaikeväärtus), hangup või message |
voicemail_message | string | ei | Kasutatakse, kui voicemail_action="message" |
agent_name | string | ei | Kuvanimi, mis edastatakse töölaudadele ja vidinale |
org_name | string | ei | Organisatsiooni kuvanimi häälagendi persoona jaoks |
tools | array | ei | Sisemised funktsioonitööriistade skeemid (vt Funktsioonitööriistad) |
call_id | integer | ei | Päringu kõne ID valikuline kaja; eiratakse |
Kuna prompt ja voice on kohustuslikud, lükkab {} või mis tahes
valideerimist mitteläbiv vastus kõne tagasi koodiga 422 — sellel teel
ei ole staatilise häälagendi varuvarianti (veebikonksu režiimis oleval
numbril või võtmel pole määratud häälagenti).
Vastuse suuruse piirang
Näidiskäitleja
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 {}
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({});
},
);
Vastus funktsioonitööriistadega
Lisa tööriistad, et AI saaks vestluse ajal sinu API-sid kutsuda:
{
"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"
}
}
}
]
}
Tootetasemete spikker
| Toode | Viiteaeg | Arutlusvõime | Kinnitussõnum |
|---|---|---|---|
spark | Madalaim | Põhiline | — |
bolt | Madal | Täiustatud | — |
storm-base | Keskmine | Tugev | — |
storm-base-with-ack | Keskmine | Tugev | Automaatne täitetekst mõtlemise ajal |
storm-extra | Kõrgem | Sügav | — |
storm-extra-with-ack | Kõrgem | Sügav | Automaatne täitetekst mõtlemise ajal |
Seotud
Mitteblokeeriv kõne lõpetamise sündmus.
Täielik JSON-skeem tools[] jaoks ja allkirjastatud lõpp-punkti leping.
Telli mitu URL-i sündmustele telephony.incoming / web.incoming.
Mustrid helistajapõhiste viipade, tööriistade ja A/B-testide jaoks.