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_idintegerਕਾਲ ਆਈਡੀ — ਇਸ ਕਾਲ ਦੇ ਸਾਰੇ ਈਵੈਂਟਾਂ ਵਿੱਚ ਸਥਿਰ
from_numberstringE.164 ਕਾਲਰ ਨੰਬਰ
to_numberstringE.164 ਮੰਜ਼ਿਲ (ਤੁਹਾਡੇ ThunderPhone ਨੰਬਰਾਂ ਵਿੱਚੋਂ ਇੱਕ)

ਵੈੱਬ ਵਿਜਿਟ ਸੈਸ਼ਨਾਂ (web.incoming) ਲਈ data ਫ਼ੋਨ ਨੰਬਰਾਂ ਦੀ ਬਜਾਏ ਏਮਬੈਡਿੰਗ ਪੰਨੇ ਦੀ ਪਛਾਣ ਕਰਦਾ ਹੈ:

{
  "type": "web.incoming",
  "data": {
    "call_id": 987654322,
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2"
  }
}
ਫ਼ੀਲਡਕਿਸਮਵੇਰਵਾ
call_idintegerਕਾਲ ਆਈਡੀ
origin_domainstringਵਿਜਿਟ ਨੂੰ ਹੋਸਟ ਕਰਨ ਵਾਲੇ ਪੰਨੇ ਦਾ ਓਰਿਜਿਨ
publishable_key_prefixstringਸੈਸ਼ਨ ਖੋਲ੍ਹਣ ਵਾਲੀ ਪ੍ਰਕਾਸ਼ਯੋਗ ਕੀ ਦੇ ਪਹਿਲੇ ਅੱਖਰ
language, primary_languagestringਜਦੋਂ ਵਿਜਿਟ ਸੈਸ਼ਨ ਨੇ ਭਾਸ਼ਾ ਓਵਰਰਾਈਡ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੋਵੇ ਤਾਂ ਮੌਜੂਦ
voicestringਜਦੋਂ ਵਿਜਿਟ ਸੈਸ਼ਨ ਨੇ ਆਵਾਜ਼ ਓਵਰਰਾਈਡ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੋਵੇ ਤਾਂ ਮੌਜੂਦ
website_contextstringਜਦੋਂ ਵਿਜਿਟ ਨੇ ਪ੍ਰਤੀ-ਸੈਸ਼ਨ ਪੰਨਾ ਸੰਦਰਭ ਪਾਸ ਕੀਤਾ ਹੋਵੇ ਤਾਂ ਮੌਜੂਦ

ਜਵਾਬ ਸਕੀਮਾ

ਇਸ ਕਾਲ ਲਈ ਏਜੰਟ ਕੌਂਫਿਗਰੇਸ਼ਨ ਦਾ ਵੇਰਵਾ ਦੇਣ ਵਾਲਾ 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, ਉਦਾਹਰਨ ਲਈ johnvoice_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 ਗੱਲਬਾਤ ਦੌਰਾਨ ਤੁਹਾਡੇ APIs ਨੂੰ ਕਾਲ ਕਰ ਸਕੇ:

{
  "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ਵੱਧਡੂੰਘਾਸੋਚਦੇ ਸਮੇਂ ਆਟੋ ਫਿਲਰ

ਸੰਬੰਧਿਤ