telephony.incoming / web.incoming

Wakati simu inayoingia inapofikia nambari isiyo na ejenti iliyoteuliwa, au kipindi cha wijeti ya wavuti kinapoanza kwenye ufunguo unaoweza kuchapishwa katika mode="webhook", ThunderPhone hutuma ombi linalozuia la telephony.incoming / web.incoming kwa URL yako ya webhook ya urithi na husubiri hadi sekunde 10 kwa jibu la usanidi. Tumia ubadilishanaji huu kuchagua kwa mabadiliko prompt, sauti na zana kwa kila simu — angalia mwongozo wa usanidi wa simu unaobadilika kwa mchakato wa kutoka mwanzo hadi mwisho.

Ubadilishanaji wa kuzuia hauna mbadala: ikiwa kishughulikiaji chako kinarejesha hali isiyo ya 2xx, kinaisha muda, au kinarejesha usanidi unaoshindwa uthibitishaji, simu inakataliwa (simu ya simu haiunganishwi; ombi la kipindi cha wijeti linashindwa kwa 502/422). Jibu haraka — mpigaji anasikia mlio wa kuita huku ukiamua.

Payload ya ombi

Kwa simu za simu (telephony.incoming):

{
  "type": "telephony.incoming",
  "data": {
    "call_id":     987654321,
    "from_number": "+14155550199",
    "to_number":   "+15551234567"
  }
}
SehemuAinaMaelezo
call_idintegerKitambulisho cha simu — thabiti katika matukio yote ya simu hii
from_numberstringNambari ya mpigaji ya E.164
to_numberstringLengwa la E.164 (moja ya nambari zako za ThunderPhone)

Kwa vipindi vya wijeti ya wavuti (web.incoming), data hutambua ukurasa unaopachika wijeti badala ya nambari za simu:

{
  "type": "web.incoming",
  "data": {
    "call_id": 987654322,
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2"
  }
}
SehemuAinaMaelezo
call_idintegerKitambulisho cha simu
origin_domainstringAsili ya ukurasa unaopangisha wijeti
publishable_key_prefixstringHerufi za kwanza za ufunguo unaoweza kuchapishwa uliofungua kipindi
language, primary_languagestringHuwepo wakati kipindi cha wijeti kiliomba ubadilishaji wa lugha
voicestringHuwepo wakati kipindi cha wijeti kiliomba ubadilishaji wa sauti
website_contextstringHuwepo wakati wijeti ilipitisha muktadha wa ukurasa kwa kila kipindi

Muundo wa jibu

Rudisha kitu cha JSON kinachoeleza usanidi wa ejenti kwa simu hii. prompt na voice zinahitajika; kila kitu kingine ni cha hiari.

{
  "prompt":  "You are a helpful booking assistant for Acme Restaurant.",
  "voice":   "john",
  "product": "spark",
  "background_track": null,
  "tools":   []
}
SehemuAinaInahitajikaMaelezo
promptstringndiyoPrompt ya mfumo inayoendesha ejenti
voicestringndiyoKitambulisho cha sauti kutoka GET /v1/voices, kwa mfano john. voice_name inakubaliwa kama jina mbadala. Sauti zisizojulikana hushindwa uthibitishaji na hukataa simu
productstringhapanaChaguo-msingi ni spark. Zinazoruhusiwa: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack
thinking_levelstringhapanaminimal, base (chaguo-msingi), au extra. Hubatilishwa kwa bidhaa za Storm: storm-extra* hulazimisha extra, storm-* nyingine hulazimisha base
audio_context_modestringhapanafull (chaguo-msingi) au reduced
watchdog_enabledbooleanhapanaWasha usimamizi kwa simu hii. Chaguo-msingi ni false
storm_feedback_modestringhapananone, acknowledgement (chaguo-msingi), au tick
languagestringhapanaUfupisho wa primary_language
primary_languagestringhapanaMsimbo wa lugha, uliosanifishwa (chaguo-msingi en). Misimbo isiyoweza kutatuliwa hukataa simu
has_additional_languagesbooleanhapanaChaguo-msingi ni false
additional_languagesarray of stringhapanaLugha za ziada ambazo ejenti inaweza kubadilisha kwenda kwazo
background_trackstring | nullhapanaKitambulisho cha sauti ya mandharinyuma au null
acknowledgement_prompt_modestringhapanaauto (chaguo-msingi) au manual (bidhaa za Storm-with-ack)
acknowledgement_promptstringhapanaHutumika wakati acknowledgement_prompt_mode="manual"
silence_interval_secondsinteger | nullhapana5–120. Sekunde za ukimya wa mpigaji simu kabla ya ukaguzi
silence_max_checkinsinteger | nullhapana1–10
silence_checkins_enabledbooleanhapanaChaguo-msingi ni true
connect_tone_enabledbooleanhapanaChaguo-msingi ni false
voicemail_actionstringhapanaprompt (chaguo-msingi), hangup, au message
voicemail_messagestringhapanaHutumika wakati voicemail_action="message"
agent_namestringhapanaJina la kuonyesha linaloripotiwa kwa dashibodi na wijeti
org_namestringhapanaJina la kuonyesha la shirika kwa persona ya ejenti
toolsarrayhapanaMiundo ya ndani ya zana za function (tazama Function Tools)
call_idintegerhapanaMwangwi wa hiari wa kitambulisho cha simu cha ombi; hupuzwa

Kwa kuwa prompt na voice zinahitajika, kurudisha {} au jibu lolote linaloshindwa uthibitishaji hukataa simu kwa 422 — hakuna mbadala wa ejenti tuli katika njia hii (namba au ufunguo katika hali ya webhook hauna ejenti iliyowekwa).


Kikomo cha ukubwa wa jibu


Kishughulikiaji cha mfano

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

Jibu lenye zana za function

Ambatisha zana ili AI iweze kuita API zako katikati ya mazungumzo:

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

Muhtasari wa viwango vya bidhaa

BidhaaUcheleweshajiMantikiUthibitisho
sparkNdogo zaidiMsingi
boltNdogoImeboreshwa
storm-baseWastaniImara
storm-base-with-ackWastaniImaraKijazaji kiotomatiki wakati wa kufikiri
storm-extraKubwa zaidiKina
storm-extra-with-ackKubwa zaidiKinaKijazaji kiotomatiki wakati wa kufikiri

Yanayohusiana