telephony.incoming / web.incoming
Gelen bir aramanın yapılandırmasını gerçek zamanlı olarak şekillendiren engelleyici webhook.
Bir gelen telefon çağrısı, atanmış bir ajanı olmayan bir numaraya ulaştığında veya mode="webhook" ayarındaki yayınlanabilir anahtarda bir web bileşeni oturumu başladığında ThunderPhone, eski webhook URL'nize bloklayıcı bir telephony.incoming / web.incoming isteği gönderir ve yapılandırma yanıtı için en fazla 10 saniye bekler. Her çağrı için istemi, sesi ve araçları dinamik olarak seçmek üzere bu alışverişi kullanın — uçtan uca örüntü için dinamik çağrı yapılandırma rehberine bakın.
Bloklayıcı alışverişin geri dönüş seçeneği yoktur: işleyiciniz 2xx
olmayan bir durum döndürürse, zaman aşımına uğrarsa veya doğrulaması
başarısız olan bir yapılandırma döndürürse çağrı reddedilir (telefon
çağrısı bağlanmaz; bileşen oturumu isteği 502/422 ile başarısız
olur). Hızlı yanıt verin — siz karar verirken arayan kişi çalma sesini
duyar.
İstek yükü
Telefon çağrıları için (telephony.incoming):
{
"type": "telephony.incoming",
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
}
}| Alan | Tür | Açıklama |
|---|---|---|
call_id | integer | Çağrı kimliği — bu çağrıdaki tüm olaylarda sabittir |
from_number | string | E.164 arayan numarası |
to_number | string | E.164 hedefi (ThunderPhone numaralarınızdan biri) |
Web bileşeni oturumları için (web.incoming) data, telefon
numaraları yerine yerleştirme sayfasını tanımlar:
{
"type": "web.incoming",
"data": {
"call_id": 987654322,
"origin_domain": "https://example.com",
"publishable_key_prefix": "pk_live_a1b2"
}
}| Alan | Tür | Açıklama |
|---|---|---|
call_id | integer | Çağrı kimliği |
origin_domain | string | Bileşeni barındıran sayfa kaynağı |
publishable_key_prefix | string | Oturumu açan yayınlanabilir anahtarın ilk karakterleri |
language, primary_language | string | Bileşen oturumu bir dil geçersiz kılma ayarı istediğinde bulunur |
voice | string | Bileşen oturumu bir ses geçersiz kılma ayarı istediğinde bulunur |
website_context | string | Bileşen, oturum başına sayfa bağlamı ilettiğinde bulunur |
Yanıt şeması
Bu çağrı için ajan yapılandırmasını açıklayan bir JSON nesnesi döndürün.
prompt ve voice zorunludur; diğer her şey isteğe bağlıdır.
{
"prompt": "You are a helpful booking assistant for Acme Restaurant.",
"voice": "john",
"product": "spark",
"background_track": null,
"tools": []
}| Alan | Tür | Zorunlu | Açıklama |
|---|---|---|---|
prompt | string | evet | Yapay zeka ajanını yönlendiren sistem istemi |
voice | string | evet | GET /v1/voices içinden ses kimliği; örneğin john. voice_name bir takma ad olarak kabul edilir. Bilinmeyen sesler doğrulamadan geçemez ve çağrıyı reddeder |
product | string | hayır | Varsayılan değer spark olur. İzin verilenler: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack |
thinking_level | string | hayır | minimal, base (varsayılan) veya extra. Storm ürünleri için geçersiz kılınır: storm-extra*, extra değerini zorunlu kılar; diğer storm-* ürünleri base değerini zorunlu kılar |
audio_context_mode | string | hayır | full (varsayılan) veya reduced |
watchdog_enabled | boolean | hayır | Bu çağrı için denetimi etkinleştirin. Varsayılan değer false |
additional_audio_context | boolean | null | hayır | Yalnızca en son tur yerine arayanın sesinin son birkaç turunu ekler; küçük bir gecikme/maliyet artışı karşılığında düzeltmeleri ve yazım/numara ağırlıklı veri toplamayı iyileştirir. Gelen oturumlarda varsayılan olarak açıktır, giden telefon çağrılarında kapalıdır; null varsayılanı korur |
storm_feedback_mode | string | hayır | none, acknowledgement (varsayılan) veya tick |
language | string | hayır | primary_language için kısa ad |
primary_language | string | hayır | Normalleştirilmiş dil kodu (varsayılan en). Çözümlenemeyen kodlar çağrıyı reddeder |
has_additional_languages | boolean | hayır | Varsayılan değer false |
additional_languages | string dizisi | hayır | Ajanın geçebileceği ek diller |
native_voice_switching | boolean | hayır | Varsayılan değer false. Çağrı başka bir dile geçtiğinde, yapılandırılmış sesi korumak yerine o dile özgü bir sesle değiştirin (cinsiyete göre eşleştirilir) |
background_track | string | null | hayır | Ortam sesi kimliği veya null |
acknowledgement_prompt_mode | string | hayır | auto (varsayılan) veya manual (Storm-with-ack ürünleri) |
acknowledgement_prompt | string | hayır | acknowledgement_prompt_mode="manual" olduğunda kullanılır |
silence_interval_seconds | integer | null | hayır | 5–120. Bir kontrol öncesindeki arayan sessizliği saniye sayısı |
silence_max_checkins | integer | null | hayır | 1–10 |
silence_checkins_enabled | boolean | hayır | Varsayılan değer true |
connect_tone_enabled | boolean | hayır | Varsayılan değer false |
voicemail_action | string | hayır | prompt (varsayılan), hangup veya message |
voicemail_message | string | hayır | voicemail_action="message" olduğunda kullanılır |
agent_name | string | hayır | Panolara ve widget'a bildirilen görünen ad |
org_name | string | hayır | Ajanın kişiliği için kuruluş görünen adı |
tools | dizi | hayır | Satır içi işlev aracı şemaları (Function Tools bölümüne bakın) |
call_id | integer | hayır | İsteğin çağrı kimliğinin isteğe bağlı yankısı; yoksayılır |
prompt ve voice zorunlu olduğundan, {} döndürmek veya doğrulamadan
geçemeyen herhangi bir yanıt çağrıyı 422 ile reddeder — bu yolda
statik ajan geri dönüşü yoktur (webhook modundaki bir numaraya veya anahtara
atanmış bir ajan bulunmaz).
Yanıt boyutu sınırı
Örnek işleyici
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({});
},
);İşlev araçlarıyla yanıt
Yapay zekanın görüşme sırasında API'lerinizi çağırabilmesi için araçlar ekleyin:
{
"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"
}
}
}
]
}Ürün katmanı hızlı başvuru
| Ürün | Gecikme | Akıl yürütme | Onay |
|---|---|---|---|
spark | En düşük | Temel | — |
bolt | Düşük | Gelişmiş | — |
storm-base | Orta | Güçlü | — |
storm-base-with-ack | Orta | Güçlü | Düşünürken otomatik dolgu |
storm-extra | Daha yüksek | Derin | — |
storm-extra-with-ack | Daha yüksek | Derin | Düşünürken otomatik dolgu |
İlgili
Engellemeyen çağrı sonu olayı.
tools[] için tam JSON şeması ve imzalı uç nokta sözleşmesi.
Birden çok URL'yi telephony.incoming / web.incoming olaylarına abone edin.
Arayana özel istemler, araçlar ve A/B testleri için kalıplar.