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 | integer | ਕਾਲ ਆਈਡੀ — ਇਸ ਕਾਲ ਦੇ ਸਾਰੇ ਈਵੈਂਟਾਂ ਵਿੱਚ ਸਥਿਰ |
from_number | string | E.164 ਕਾਲਰ ਨੰਬਰ |
to_number | string | 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 | integer | ਕਾਲ ਆਈਡੀ |
origin_domain | string | ਵਿਜਿਟ ਨੂੰ ਹੋਸਟ ਕਰਨ ਵਾਲੇ ਪੰਨੇ ਦਾ ਓਰਿਜਿਨ |
publishable_key_prefix | string | ਸੈਸ਼ਨ ਖੋਲ੍ਹਣ ਵਾਲੀ ਪ੍ਰਕਾਸ਼ਯੋਗ ਕੀ ਦੇ ਪਹਿਲੇ ਅੱਖਰ |
language, primary_language | string | ਜਦੋਂ ਵਿਜਿਟ ਸੈਸ਼ਨ ਨੇ ਭਾਸ਼ਾ ਓਵਰਰਾਈਡ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੋਵੇ ਤਾਂ ਮੌਜੂਦ |
voice | string | ਜਦੋਂ ਵਿਜਿਟ ਸੈਸ਼ਨ ਨੇ ਆਵਾਜ਼ ਓਵਰਰਾਈਡ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੋਵੇ ਤਾਂ ਮੌਜੂਦ |
website_context | string | ਜਦੋਂ ਵਿਜਿਟ ਨੇ ਪ੍ਰਤੀ-ਸੈਸ਼ਨ ਪੰਨਾ ਸੰਦਰਭ ਪਾਸ ਕੀਤਾ ਹੋਵੇ ਤਾਂ ਮੌਜੂਦ |
ਜਵਾਬ ਸਕੀਮਾ
ਇਸ ਕਾਲ ਲਈ ਏਜੰਟ ਕੌਂਫਿਗਰੇਸ਼ਨ ਦਾ ਵੇਰਵਾ ਦੇਣ ਵਾਲਾ 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 ਗੱਲਬਾਤ ਦੌਰਾਨ ਤੁਹਾਡੇ 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 | ਵੱਧ | ਡੂੰਘਾ | ਸੋਚਦੇ ਸਮੇਂ ਆਟੋ ਫਿਲਰ |