ThunderPhone 2.0 ir klāt.Sāciet uzreiz — no 2 centiem minūtē.Lasīt paziņojumu

Webhooks

telephony.incoming / web.incoming

Bloķējošs tīmekļa aizķeres punkts, kas reāllaikā konfigurē ienākošo zvanu.

Kad ienākošais tālruņa zvans sasniedz numuru bez piesaistīta balss aģenta vai tīmekļa logrīka sesija tiek sākta ar publicējamu atslēgu režīmā mode="webhook", ThunderPhone nosūta bloķējošu telephony.incoming / web.incoming pieprasījumu uz jūsu mantoto webhook URL un gaida līdz 10 sekundēm konfigurācijas atbildi. Izmantojiet šo apmaiņu, lai katram zvanam dinamiski izvēlētos uzvedni, balsi un rīkus — pilnu procesu skatiet dinamiskās zvanu konfigurācijas ceļvedī.

Bloķējošajai apmaiņai nav rezerves varianta: ja jūsu apstrādātājs atgriež ne-2xx statusu, pārsniedz noildzi vai atgriež konfigurāciju, kas neiztur validāciju, zvans tiek noraidīts (tālruņa zvans netiek savienots; logrīka sesijas pieprasījums neizdodas ar 502/422). Atbildiet ātri — kamēr pieņemat lēmumu, zvanītājs dzird atzvana signālu.

Pieprasījuma dati

Tālruņa zvaniem (telephony.incoming):

{
  "type": "telephony.incoming",
  "data": {
    "call_id":     987654321,
    "from_number": "+14155550199",
    "to_number":   "+15551234567"
  }
}
LauksTipsApraksts
call_idintegerZvanu ID — nemainīgs visos šī zvana notikumos
from_numberstringZvanītāja E.164 numurs
to_numberstringE.164 galamērķis (viens no jūsu ThunderPhone numuriem)

Tīmekļa logrīka sesijām (web.incoming) data tālruņa numuru vietā identificē iegulšanas lapu:

{
  "type": "web.incoming",
  "data": {
    "call_id": 987654322,
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2"
  }
}
LauksTipsApraksts
call_idintegerZvanu ID
origin_domainstringLapas avots, kurā tiek mitināts logrīks
publishable_key_prefixstringPublicējamās atslēgas pirmās rakstzīmes, kas atvēra sesiju
language, primary_languagestringPieejams, ja logrīka sesija pieprasīja valodas pārrakstīšanu
voicestringPieejams, ja logrīka sesija pieprasīja balss pārrakstīšanu
website_contextstringPieejams, ja logrīks nodeva katras sesijas lapas kontekstu

Atbildes shēma

Atgrieziet JSON objektu, kas apraksta balss aģenta konfigurāciju šim zvanam. prompt un voice ir obligāti; viss pārējais nav obligāts.

{
  "prompt":  "You are a helpful booking assistant for Acme Restaurant.",
  "voice":   "john",
  "product": "spark",
  "background_track": null,
  "tools":   []
}
LauksTipsObligātsApraksts
promptstringSistēmas uzvedne, kas vada balss aģentu
voicestringBalss ID no GET /v1/voices, piemēram, john. voice_name tiek pieņemts kā aizstājvārds. Nezināmas balsis neiztur validāciju un zvans tiek noraidīts
productstringNoklusējuma vērtība ir spark. Atļautās vērtības: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack
thinking_levelstringminimal, base (noklusējums) vai extra. Storm produktiem tiek ignorēts: storm-extra* piespiež extra, citi storm-* piespiež base
audio_context_modestringfull (noklusējums) vai reduced
watchdog_enabledbooleanIespējojiet šī zvana uzraudzību. Noklusējuma vērtība ir false
additional_audio_contextboolean | nullIekļaujiet pēdējos dažus zvanītāja audio dialoga posmus, nevis tikai pēdējo posmu, tādējādi uzlabojot labojumus un datu vākšanu, kurā ir daudz pareizrakstības vai ciparu, ar nelielu latentuma un izmaksu pieaugumu. Ienākošajām sesijām pēc noklusējuma ir ieslēgts, bet izejošajiem tālruņa zvaniem — izslēgts; null saglabā noklusējuma vērtību
storm_feedback_modestringnone, acknowledgement (noklusējums) vai tick
languagestringSaīsinājums laukam primary_language
primary_languagestringValodas kods, normalizēts (noklusējums en). Neatrisināmi kodi zvanu noraida
has_additional_languagesbooleanNoklusējuma vērtība ir false
additional_languagesstring masīvsPapildu valodas, uz kurām balss aģents var pārslēgties
native_voice_switchingbooleanNoklusējuma vērtība ir false. Kad zvans pārslēdzas uz citu valodu, konfigurētās balss vietā izmantojiet šai valodai dzimto balsi (atbilstoši dzimumam)
background_trackstring | nullFona audio ID vai null
acknowledgement_prompt_modestringauto (noklusējums) vai manual (Storm-with-ack produktiem)
acknowledgement_promptstringTiek izmantots, ja acknowledgement_prompt_mode="manual"
silence_interval_secondsinteger | null5–120. Zvanītāja klusuma sekunžu skaits pirms saziņas pārbaudes
silence_max_checkinsinteger | null1–10
silence_checkins_enabledbooleanNoklusējuma vērtība ir true
connect_tone_enabledbooleanNoklusējuma vērtība ir false
voicemail_actionstringprompt (noklusējums), hangup vai message
voicemail_messagestringTiek izmantots, ja voicemail_action="message"
agent_namestringParādāmais vārds, kas tiek rādīts informācijas paneļos un logrīkā
org_namestringOrganizācijas parādāmais nosaukums balss aģenta personībai
toolsarrayIekļautās funkciju rīku shēmas (skatiet Funkciju rīki)
call_idintegerNeobligāta pieprasījuma zvana ID atbalss; tiek ignorēta

Tā kā prompt un voice ir obligāti, atgriežot {} vai jebkuru atbildi, kas neiztur validāciju, zvans tiek noraidīts ar 422 — šajā ceļā nav statiska balss aģenta atkāpšanās varianta (numuram vai atslēgai tīmekļa āķa režīmā nav piešķirts balss aģents).


Atbildes lieluma ierobežojums


Apstrādātāja piemērs

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({});
  },
);

Atbilde ar funkciju rīkiem

Pievienojiet rīkus, lai AI varētu izsaukt jūsu API sarunas laikā:

{
  "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"
        }
      }
    }
  ]
}

Produkta līmeņu īsā atsauce

ProduktsLatenceSpriešanaApstiprinājums
sparkZemākāPamata
boltZemaUzlabota
storm-baseVidējaSpēcīga
storm-base-with-ackVidējaSpēcīgaAutomātisks aizpildījums domāšanas laikā
storm-extraAugstākaPadziļināta
storm-extra-with-ackAugstākaPadziļinātaAutomātisks aizpildījums domāšanas laikā

Saistītie materiāli