telephony.incoming / web.incoming

જ્યારે ઇનબાઉન્ડ ફોન કૉલ કોઈ એજન્ટ સોંપાયેલ ન હોય તેવા નંબર પર પહોંચે, અથવા વેબ વિજેટ સત્ર mode="webhook"માં પબ્લિશેબલ કી પર શરૂ થાય, ત્યારે ThunderPhone તમારા લેગસી વેબહૂક URL પર બ્લોકિંગ telephony.incoming / web.incoming વિનંતી મોકલે છે અને કૉન્ફિગરેશન પ્રતિસાદ માટે 10 સેકન્ડ સુધી રાહ જુએ છે. દરેક કૉલ માટે prompt, અવાજ અને ટૂલ્સને ડાયનેમિક રીતે પસંદ કરવા માટે આ વિનિમયનો ઉપયોગ કરો — સંપૂર્ણ પેટર્ન માટે ડાયનેમિક કૉલ કૉન્ફિગરેશન માર્ગદર્શિકા જુઓ.

બ્લોકિંગ વિનિમયમાં કોઈ ફૉલબૅક નથી: જો તમારું હેન્ડલર નૉન-2xx સ્ટેટસ પરત કરે, સમયસમાપ્તિ થાય, અથવા વૅલિડેશન નિષ્ફળ જાય તેવું કૉન્ફિગ પરત કરે, તો કૉલ નકારવામાં આવે છે (ફોન કૉલ કનેક્ટ થતો નથી; વિજેટ સત્ર વિનંતી 502/422 સાથે નિષ્ફળ જાય છે). ઝડપથી જવાબ આપો — તમે નિર્ણય લો છો ત્યારે કૉલર રિંગબેક સાંભળી રહ્યો હોય છે.

વિનંતી પેલોડ

ફોન કૉલ્સ માટે (telephony.incoming):

{
  "type": "telephony.incoming",
  "data": {
    "call_id":     987654321,
    "from_number": "+14155550199",
    "to_number":   "+15551234567"
  }
}
ફીલ્ડપ્રકારવર્ણન
call_idઇન્ટિજરકૉલ id — આ કૉલ માટેની તમામ ઇવેન્ટ્સમાં સ્થિર
from_numberસ્ટ્રિંગE.164 કૉલર નંબર
to_numberસ્ટ્રિંગE.164 ગંતવ્ય (તમારા ThunderPhone નંબરોમાંથી એક)

વેબ વિજેટ સત્રો માટે (web.incoming), data ફોન નંબરોને બદલે એમ્બેડ કરતું પેજ ઓળખે છે:

{
  "type": "web.incoming",
  "data": {
    "call_id": 987654322,
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2"
  }
}
ફીલ્ડપ્રકારવર્ણન
call_idઇન્ટિજરકૉલ id
origin_domainસ્ટ્રિંગવિજેટ હોસ્ટ કરતા પેજનું ઓરિજિન
publishable_key_prefixસ્ટ્રિંગસત્ર ખોલનાર પબ્લિશેબલ કીના પ્રથમ અક્ષરો
language, primary_languageસ્ટ્રિંગવિજેટ સત્રે ભાષા ઓવરરાઇડની વિનંતી કરી હોય ત્યારે હાજર
voiceસ્ટ્રિંગવિજેટ સત્રે અવાજ ઓવરરાઇડની વિનંતી કરી હોય ત્યારે હાજર
website_contextસ્ટ્રિંગવિજેટે પ્રતિ-સત્ર પેજ કન્ટેક્સ્ટ પસાર કર્યો હોય ત્યારે હાજર

પ્રતિસાદ સ્કીમા

આ કોલ માટે એજન્ટ કન્ફિગરેશનનું વર્ણન કરતું JSON ઑબ્જેક્ટ પરત કરો. prompt અને voice આવશ્યક છે; બાકીનું બધું વૈકલ્પિક છે.

{
  "prompt":  "You are a helpful booking assistant for Acme Restaurant.",
  "voice":   "john",
  "product": "spark",
  "background_track": null,
  "tools":   []
}
ફીલ્ડપ્રકારઆવશ્યકવર્ણન
promptસ્ટ્રિંગહાએજન્ટને નિયંત્રિત કરતો સિસ્ટમ prompt
voiceસ્ટ્રિંગહાGET /v1/voices માંથી વૉઇસ ID, ઉદાહરણ તરીકે john. voice_name ઉપનામ તરીકે સ્વીકારવામાં આવે છે. અજાણ્યા વૉઇસીસ વેલિડેશનમાં નિષ્ફળ જાય છે અને કોલ નકારી કાઢે છે
productસ્ટ્રિંગનાડિફૉલ્ટ spark. માન્ય: spark, bolt, storm-base, storm-base-with-ack, storm-extra, storm-extra-with-ack
thinking_levelસ્ટ્રિંગનાminimal, base (ડિફૉલ્ટ), અથવા extra. Storm પ્રોડક્ટ્સ માટે ઓવરરાઇડ થાય છે: storm-extra* extra ફરજિયાત કરે છે, અન્ય storm-* base ફરજિયાત કરે છે
audio_context_modeસ્ટ્રિંગનાfull (ડિફૉલ્ટ) અથવા reduced
watchdog_enabledબુલિયનનાઆ કોલ માટે દેખરેખ સક્રિય કરો. ડિફૉલ્ટ false
storm_feedback_modeસ્ટ્રિંગનાnone, acknowledgement (ડિફૉલ્ટ), અથવા tick
languageસ્ટ્રિંગનાprimary_language માટેનું સંક્ષિપ્ત રૂપ
primary_languageસ્ટ્રિંગનાભાષા કોડ, સામાન્યકૃત (ડિફૉલ્ટ en). ઉકેલી ન શકાય તેવા કોડ્સ કોલ નકારી કાઢે છે
has_additional_languagesબુલિયનનાડિફૉલ્ટ false
additional_languagesસ્ટ્રિંગની એરેનાએજન્ટ બદલી શકે તેવી વધારાની ભાષાઓ
background_trackસ્ટ્રિંગ | નલનાપૃષ્ઠભૂમિ ઑડિયો ID અથવા null
acknowledgement_prompt_modeસ્ટ્રિંગનાauto (ડિફૉલ્ટ) અથવા manual (Storm-with-ack પ્રોડક્ટ્સ)
acknowledgement_promptસ્ટ્રિંગનાacknowledgement_prompt_mode="manual" હોય ત્યારે વપરાય છે
silence_interval_secondsઇન્ટિજર | નલના5–120. સંપર્ક-ચકાસણી પહેલાં કોલરનું મૌન રહેવાની સેકન્ડ્સ
silence_max_checkinsઇન્ટિજર | નલના1–10
silence_checkins_enabledબુલિયનનાડિફૉલ્ટ true
connect_tone_enabledબુલિયનનાડિફૉલ્ટ false
voicemail_actionસ્ટ્રિંગનાprompt (ડિફૉલ્ટ), hangup, અથવા message
voicemail_messageસ્ટ્રિંગનાvoicemail_action="message" હોય ત્યારે વપરાય છે
agent_nameસ્ટ્રિંગનાડેશબોર્ડ્સ અને વિજેટમાં દર્શાવાતું નામ
org_nameસ્ટ્રિંગનાએજન્ટના પર્સોના માટે સંસ્થાનું દર્શાવાતું નામ
toolsએરેનાઇનલાઇન ફંક્શન-ટૂલ સ્કીમાઓ (ફંક્શન ટૂલ્સ જુઓ)
call_idઇન્ટિજરનારિક્વેસ્ટના કોલ IDનું વૈકલ્પિક ઇકો; અવગણવામાં આવે છે

prompt અને voice આવશ્યક હોવાથી, {} અથવા વેલિડેશનમાં નિષ્ફળ જતો કોઈપણ પ્રતિસાદ કોલને 422 સાથે નકારી કાઢે છે — આ પાથ પર સ્થિર-એજન્ટ ફૉલબૅક નથી (વેબહૂક મોડમાં નંબર અથવા કીને કોઈ એજન્ટ સોંપાયેલો નથી).


પ્રતિસાદ કદ મર્યાદા


ઉદાહરણ હેન્ડલર

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

ફંક્શન ટૂલ્સ સાથે પ્રતિસાદ

AI વાતચીત દરમિયાન તમારા APIને કૉલ કરી શકે તે માટે ટૂલ્સ જોડો:

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

પ્રોડક્ટ ટિયર સંદર્ભ

પ્રોડક્ટવિલંબતાતર્કશક્તિસ્વીકૃતિ
sparkસૌથી ઓછીમૂળભૂત
boltઓછીસુધારેલી
storm-baseમધ્યમમજબૂત
storm-base-with-ackમધ્યમમજબૂતવિચાર કરતી વખતે સ્વચાલિત ફિલર
storm-extraવધુઊંડી
storm-extra-with-ackવધુઊંડીવિચાર કરતી વખતે સ્વચાલિત ફિલર

સંબંધિત