telephony.complete / web.complete
ಪ್ರತಿ ಕರೆ ಮುಗಿದ ನಂತರ ಪೂರ್ಣಗೊಳಿಸುವಿಕೆ ಈವೆಂಟ್ ಸಕ್ರಿಯಗೊಳ್ಳುತ್ತದೆ — ಒಳಬರುವ ಟೆಲಿಫೋನಿ, ಹೊರಹೋಗುವ ಟೆಲಿಫೋನಿ, ವೆಬ್ ಕರೆ, ಅಥವಾ ಪರೀಕ್ಷಾ ಕರೆ (ಬಿಲ್ಡರ್ ಮೈಕ್ ಸೆಷನ್). ಇದು ತಡೆಯದ: ಯಾವುದೇ 2xx ನೊಂದಿಗೆ ಪ್ರತಿಕ್ರಿಯಿಸಿ.
ಈವೆಂಟ್ ಅನ್ನು ಎರಡೂ ಮಾರ್ಗಗಳಲ್ಲಿ ವಿತರಿಸಲಾಗುತ್ತದೆ:
- Webhook ಎಂಡ್ಪಾಯಿಂಟ್ಗಳು ಕೆಳಗೆ ದಾಖಲಿಸಿರುವ ಸ್ಥಿರ ಪೇಲೋಡ್,
ಪ್ರತಿ ವಿತರಣೆಯ
event_id, 30 s ಕಾಲಾವಧಿ ಮಿತಿ ಮತ್ತು 24 h ವರೆಗೆ ಮರುಪ್ರಯತ್ನಗಳೊಂದಿಗೆtelephony.complete(ಫೋನ್ ಕರೆಗಳು) ಅಥವಾweb.complete(ವೆಬ್ ಕರೆಗಳು ಮತ್ತು ಬಿಲ್ಡರ್ ಮೈಕ್ ಪರೀಕ್ಷಾ ಕರೆಗಳು) ಸ್ವೀಕರಿಸುತ್ತವೆ. - ಲೆಗಸಿ ಏಕ-URL webhook ಸ್ವಲ್ಪ ಭಿನ್ನವಾದ ಪೇಲೋಡ್ನೊಂದಿಗೆ ಒಂದು ಸಿಂಕ್ರೊನಸ್ ಪ್ರಯತ್ನವನ್ನು (10 s ಕಾಲಾವಧಿ ಮಿತಿ, ಮರುಪ್ರಯತ್ನಗಳಿಲ್ಲ) ಸ್ವೀಕರಿಸುತ್ತದೆ — ನೋಡಿ ಲೆಗಸಿ ಪೇಲೋಡ್ ವ್ಯತ್ಯಾಸಗಳು.
ವಿನಂತಿ ಪೇಲೋಡ್ (ಎಂಡ್ಪಾಯಿಂಟ್ ವಿತರಣೆಗಳು)
{
"data": {
"billable_minutes": 1.25,
"billing_total_cents": 8,
"call_id": 987654321,
"direction": "inbound",
"duration_seconds": 54,
"end_reason": "user_hangup",
"end_time": "2026-04-20T18:25:04.822Z",
"from_number": "+14155550199",
"product": "spark",
"recording_url": "https://storage.example.com/…",
"start_time": "2026-04-20T18:24:10.113Z",
"status": "completed",
"to_number": "+15551234567",
"transcripts": [ /* see Transcript format */ ],
"transfer_number": null,
"voice": "john"
},
"event_id": "6a7b8c9d-0e1f-4a2b-8c3d-4e5f6a7b8c9d",
"type": "telephony.complete"
}
| ಕ್ಷೇತ್ರ | ಪ್ರಕಾರ | ವಿವರಣೆ |
|---|---|---|
call_id | ಪೂರ್ಣಾಂಕ | ಈ ಕರೆಗೆ ಸಂಬಂಧಿಸಿದ ಪ್ರತಿಯೊಂದು ಈವೆಂಟ್ನಲ್ಲಿಯೂ ಸ್ಥಿರವಾಗಿರುತ್ತದೆ |
direction | ಸ್ಟ್ರಿಂಗ್ | inbound, outbound, web, test. ಐತಿಹಾಸಿಕ ಪೇಲೋಡ್ಗಳು ಲೆಗಸಿ mic ಅಥವಾ widget ಮೌಲ್ಯಗಳನ್ನು ಹೊಂದಿರಬಹುದು |
from_number, to_number | ಸ್ಟ್ರಿಂಗ್ | E.164. ವೆಬ್ ಕರೆಗಳು ಮತ್ತು ಪರೀಕ್ಷಾ ಕರೆಗಳಿಗೆ from_number ಅಕ್ಷರಶಃ "web" ಆಗಿರುತ್ತದೆ |
origin_domain | ಸ್ಟ್ರಿಂಗ್ | ವೆಬ್/ಪರೀಕ್ಷೆಗೆ ಮಾತ್ರ — ವಿಜೆಟ್ ಅನ್ನು ಹೋಸ್ಟ್ ಮಾಡಿದ ಪುಟದ ಮೂಲ (ಮೈಕ್ ಸೆಷನ್ಗಳಿಗೆ ಖಾಲಿ) |
start_time, end_time | ಟೈಮ್ಸ್ಟ್ಯಾಂಪ್ | ISO 8601 UTC |
duration_seconds | ಪೂರ್ಣಾಂಕ | null | ಪ್ರಾರಂಭ/ಅಂತ್ಯದಿಂದ ಪಡೆಯಲಾಗಿದೆ |
status | ಸ್ಟ್ರಿಂಗ್ | completed ಅಥವಾ failed |
end_reason | ಸ್ಟ್ರಿಂಗ್ | ಕೆಳಗಿನ ಕೋಷ್ಟಕವನ್ನು ನೋಡಿ |
product, voice | ಸ್ಟ್ರಿಂಗ್ | ಕರೆ ಸಮಯದಲ್ಲಿ ಜಾರಿಯಲ್ಲಿದ್ದ ಏಜೆಂಟ್ ಕಾನ್ಫಿಗರೇಶನ್ |
transfer_number | ಸ್ಟ್ರಿಂಗ್ | null | ಕರೆಯನ್ನು ವರ್ಗಾಯಿಸಿದಾಗ ಹೊಂದಿಸಲಾಗುತ್ತದೆ |
recording_url | ಸ್ಟ್ರಿಂಗ್ | null | ಅವಧಿ ಮುಗಿಯುವ ಸಹಿ ಮಾಡಿದ URL; ತಕ್ಷಣ ಡೌನ್ಲೋಡ್ ಮಾಡಿ. ರೆಕಾರ್ಡಿಂಗ್ ಆರ್ಟಿಫ್ಯಾಕ್ಟ್ ಲಭ್ಯವಿಲ್ಲದಾಗ null |
billable_minutes | ಸಂಖ್ಯೆ | ಬಿಲ್ ಮಾಡಲಾದ ನಿಮಿಷಗಳು, ಹತ್ತಿರದ ಕಾಲು ನಿಮಿಷಕ್ಕೆ ದುಂಡಾಗಿಸಲಾಗುತ್ತದೆ (15-ಸೆಕೆಂಡ್ ಹೆಚ್ಚಳಗಳು, ಕನಿಷ್ಠ 0.25). ನೇರವಾಗಿ ವಾಯ್ಸ್ಮೇಲ್ಗೆ ಹೋದ ಕರೆಗಳು ತಮ್ಮ ನಿಜವಾದ ಮೀಟರ್ ಮಾಡಿದ ನಿಮಿಷಗಳನ್ನು ಇಲ್ಲಿಯೂ ವರದಿ ಮಾಡುತ್ತವೆ, ಆದರೆ ಶುಲ್ಕವನ್ನು ಯೋಜನೆ ದರದಲ್ಲಿ ಒಂದು ನಿಮಿಷಕ್ಕೆ ಸೀಮಿತಗೊಳಿಸಲಾಗುತ್ತದೆ. |
billing_total_cents | ಪೂರ್ಣಾಂಕ | USD ಸೆಂಟ್ಗಳು |
transcripts | ಅರೇ | ಪ್ರತಿ ಸರದಿಯ ಟ್ರಾನ್ಸ್ಕ್ರಿಪ್ಟ್ ನಮೂದುಗಳು; ಟ್ರಾನ್ಸ್ಕ್ರಿಪ್ಟ್ ಲಭ್ಯವಿಲ್ಲದಾಗ ಖಾಲಿಯಾಗಿರಬಹುದು |
ಅಂತ್ಯದ ಕಾರಣಗಳು
| ಮೌಲ್ಯ | ಅರ್ಥ |
|---|---|
user_hangup | ದೂರದ ಪಕ್ಷವು ಮೊದಲು ಕರೆ ಕಡಿತಗೊಳಿಸಿತು |
ai_hangup | AI ಉದ್ದೇಶಪೂರ್ವಕವಾಗಿ ಕರೆಯನ್ನು ಮುಗಿಸಿತು |
ai_transfer | AI ಕರೆಯನ್ನು ವರ್ಗಾಯಿಸಿತು; transfer_number ಹೊಂದಿಸಲಾಗಿರುತ್ತದೆ |
ai_warm_transfer | AI ವಾರ್ಮ್ (ಸಹಭಾಗಿತ್ವದ) ವರ್ಗಾವಣೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸಿತು |
voicemail_hangup | ವಾಯ್ಸ್ಮೇಲ್ ಪತ್ತೆಯಾಯಿತು ಮತ್ತು ನಿಮ್ಮ voicemail_action ಪ್ರಕಾರ ಕರೆ ಮುಗಿಯಿತು |
max_duration | ಕರೆ ಗರಿಷ್ಠ ಅವಧಿ ಮಿತಿಯನ್ನು ತಲುಪಿತು |
superseded | ಸೆಷನ್ ಅನ್ನು ಹೊಸದು ಬದಲಾಯಿಸಿತು |
unknown | ಅಂತ್ಯದ ಕಾರಣವನ್ನು ನಿರ್ಧರಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ |
ಟ್ರಾನ್ಸ್ಕ್ರಿಪ್ಟ್ ಸ್ವರೂಪ
transcriptsನಲ್ಲಿರುವ ಪ್ರತಿಯೊಂದು ನಮೂದು ಒಂದು ಸಂಭಾಷಣೆಯ ಸರದಿಯಾಗಿದೆ. ಪಾತ್ರಗಳು
user (ಕರೆಮಾಡುವವರ ಮಾತು), model (ಏಜೆಂಟ್ನ ಮಾತು ಮತ್ತು ಸಾಧನ ಕರೆಯುವಿಕೆಗಳು),
tool (ಸಾಧನ ಫಲಿತಾಂಶಗಳು), ಮತ್ತು system (ಭಾಷೆ ಬದಲಾವಣೆಗಳಂತಹ ಕರೆ
ಘಟನೆಗಳು) ಆಗಿವೆ.
[
{
"role": "user",
"content_type": "text/plain",
"content": "Hi, I'm calling about my appointment.",
"start_ms": 1200,
"end_ms": 4100,
"audio_url": "https://storage.example.com/…"
},
{
"role": "model",
"content_type": "text/plain",
"content": "Sure, what date works best?",
"start_ms": 4200,
"end_ms": 6100
},
{
"role": "model",
"content_type": "application/json",
"content": {
"tool_call": "search_appointments",
"arguments": { "date": "2026-04-21" }
}
},
{
"role": "tool",
"content_type": "application/json",
"content": {
"tool_name": "search_appointments",
"response": { "available_slots": ["9:00 AM", "2:00 PM"] }
}
}
]
| ಕ್ಷೇತ್ರ | ಪ್ರಕಾರ | ವಿವರಣೆ |
|---|---|---|
role | string | user, model, tool, ಅಥವಾ system |
content_type | string | ಮಾತಿಗಾಗಿ text/plain; ಸಾಧನ ಕರೆಯುವಿಕೆಗಳು, ಸಾಧನ ಫಲಿತಾಂಶಗಳು ಮತ್ತು ಸಿಸ್ಟಮ್ ಘಟನೆಗಳಿಗಾಗಿ application/json |
content | string | object | ಮಾತಿನ ಪಠ್ಯ, ಅಥವಾ ಮೇಲೆ ತೋರಿಸಿರುವ ರಚನಾತ್ಮಕ ಆಬ್ಜೆಕ್ಟ್. ಸಾಧನ ಕರೆಯುವಿಕೆಗಳು: {"tool_call": name, "arguments": {…}}. ಸಾಧನ ಫಲಿತಾಂಶಗಳು: {"tool_name": name, "response": {…}} |
start_ms, end_ms | integer | ಕರೆ ಪ್ರಾರಂಭದಿಂದ ಆಫ್ಸೆಟ್ಗಳು, ms. ಆಡಿಯೊ ಸಮಯ ತಿಳಿದಿರುವಾಗ ಇರುತ್ತವೆ |
ttfa_ms | integer | ಅಳೆಯಲ್ಪಟ್ಟಾಗ, model ಸರದಿಗೆ ಮೊದಲ ಆಡಿಯೊಗೆ ತೆಗೆದುಕೊಳ್ಳುವ ಸಮಯ |
audio_url, audio_urls | string / array | ಪ್ರತಿ ಸರದಿಗೆ ರೆಕಾರ್ಡ್ ಮಾಡಿದಾಗ, ಆ ಸರದಿಯ ಆಡಿಯೊಗೆ ಅವಧಿ ಮುಗಿಯುವ ಸಹಿ ಮಾಡಿದ URLಗಳು |
ಅಡಚಣೆ ಗುರುತುಗಳು, ಸ್ವೀಕೃತಿ promptಗಳು ಮತ್ತು ಮೂಲ ಸ್ಥಾನಗಳನ್ನು ಒಳಗೊಂಡ ಸಂಪೂರ್ಣ
ರಚನಾತ್ಮಕ ಸರದಿ ಇತಿಹಾಸಕ್ಕಾಗಿ,
GET /v1/calls/{call_id}/history ಬಳಸಿ.
ಹಿಂದಿನ ಪೇಲೋಡ್ ವ್ಯತ್ಯಾಸಗಳು
ಹಿಂದಿನ ಏಕ-URL ವೆಬ್ಹುಕ್ ಎನ್ವಲಪ್
{"type": "telephony.complete" | "web.complete", "data": {…}} ಆಗಿದ್ದು,
ಇದರಲ್ಲಿ event_id ಇರುವುದಿಲ್ಲ, ಮತ್ತು ಅದರ data ಎಂಡ್ಪಾಯಿಂಟ್ ಪೇಲೋಡ್ನಿಂದ ಭಿನ್ನವಾಗಿದೆ:
- ಸರದಿ ಅರೇ
transcriptsಅಡಿಯಲ್ಲಿ ಅಲ್ಲದೆhistoryಅಡಿಯಲ್ಲಿರುತ್ತದೆ (ಮೇಲಿನಂತೆಯೇ ಸರದಿ ಸ್ಕೀಮಾ). - ಕ್ಷೇತ್ರಗಳ ಸಮೂಹವು ಕರೆಯ ಅಂತ್ಯದ ಮೂಲ ವರದಿಯಾಗಿದ್ದು, ಮೇಲಿನ ಟೇಬಲ್ಗಿಂತ ಹೆಚ್ಚುವರಿ ಆಂತರಿಕ ಕ್ಷೇತ್ರಗಳನ್ನು ಒಳಗೊಂಡಿರಬಹುದು — ತಿಳಿಯದ ಕ್ಷೇತ್ರಗಳನ್ನು ಮಾಹಿತಿಗಾಗಿ ಮಾತ್ರ ಪರಿಗಣಿಸಿ.
- ವೆಬ್ ಕರೆಗಳು (
direction: "web")from_number/to_numberಅನ್ನು ಬಿಟ್ಟುಬಿಡುತ್ತವೆ ಮತ್ತುorigin_domainಅನ್ನು ಸೇರಿಸುತ್ತವೆ. - ಬಿಲ್ಡರ್ ಮೈಕ್ ಪರೀಕ್ಷಾ ಕರೆಗಳು ಹಿಂದಿನ ಪಥದಲ್ಲಿ
telephony.completeಎಂದು ವರದಿಯಾಗುತ್ತವೆ (ಎಂಡ್ಪಾಯಿಂಟ್ ಸಿಸ್ಟಮ್ ಅವುಗಳನ್ನುweb.completeಗೆ ಮ್ಯಾಪ್ ಮಾಡುತ್ತದೆ). - ವರ್ಗಾವಣೆ ಸಮನ್ವಯ: ಕರೆ ವರ್ಗಾವಣೆಯಲ್ಲಿ ಕೊನೆಗೊಂಡಾಗ, ಹಿಂದಿನ ವೆಬ್ಹುಕ್ ಅನ್ನು ಸಿಂಕ್ರೋನಸ್ ಆಗಿ ಕರೆಯಲಾಗುತ್ತದೆ ಮತ್ತು ಹಸ್ತಾಂತರ ಗುರಿಯು ಸಿದ್ಧವಾಗಿಲ್ಲ ಎಂದು ಸೂಚಿಸಲು
{"transfer_ready": false}ಎಂದು ಪ್ರತಿಕ್ರಿಯಿಸಬಹುದು. ಇತರೆ ಯಾವುದೇ ಪ್ರತಿಕ್ರಿಯೆ (ಅಥವಾ ಹಿಂದಿನ ವೆಬ್ಹುಕ್ ಇಲ್ಲದಿರುವುದು) ವರ್ಗಾವಣೆಯನ್ನು ಮುಂದುವರಿಯಲು ಅನುಮತಿಸುತ್ತದೆ. ಇದಕ್ಕಾಗಿ ಎಂಡ್ಪಾಯಿಂಟ್ ವಿತರಣೆಗಳನ್ನು ಎಂದಿಗೂ ಪರಿಶೀಲಿಸಲಾಗುವುದಿಲ್ಲ.
ಉದಾಹರಣೆ ಹ್ಯಾಂಡ್ಲರ್
import hashlib
import hmac
import json
import os
from fastapi import FastAPI, HTTPException, Request
app = FastAPI()
SECRET = os.environ["THUNDERPHONE_WEBHOOK_SECRET"]
def verify(body: bytes, signature: str) -> bool:
expected = hmac.new(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"] in ("telephony.complete", "web.complete"):
data = event["data"]
# Endpoint deliveries use "transcripts"; the legacy webhook uses "history".
turns = data.get("transcripts") or data.get("history") or []
await persist_call_record(
call_id=data["call_id"],
turns=turns,
recording_url=data.get("recording_url"),
)
if data["end_reason"] in ("ai_transfer", "ai_warm_transfer"):
await notify_team(data.get("transfer_number"), data["call_id"])
return {"ok": True}
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" }),
async (req, res) => {
if (!verify(req.body, req.header("X-ThunderPhone-Signature"))) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body.toString("utf8"));
if (["telephony.complete", "web.complete"].includes(event.type)) {
const data = event.data;
// Endpoint deliveries use "transcripts"; the legacy webhook uses "history".
const turns = data.transcripts ?? data.history ?? [];
await persistCallRecord({ ...data, turns });
if (["ai_transfer", "ai_warm_transfer"].includes(data.end_reason)) {
await notifyTeam(data.transfer_number, data.call_id);
}
}
res.json({ ok: true });
},
);
ಸಾಮಾನ್ಯ ಬಳಕೆ ಸಂದರ್ಭಗಳು
ಪ್ರತಿ ಕರೆಯ ಟ್ರಾನ್ಸ್ಕ್ರಿಪ್ಟ್ + ರೆಕಾರ್ಡಿಂಗ್ URL ಅನ್ನು ನಿಮ್ಮ ಗ್ರಾಹಕ ದಾಖಲೆಗಳೊಂದಿಗೆ ಉಳಿಸಿ.
ವಿಷಯ ಮಾಡೆಲಿಂಗ್, CSAT ಸಿಗ್ನಲ್ ಹೊರತೆಗೆಯುವಿಕೆ ಅಥವಾ ವರ್ಗಾವಣೆ-ದರ ಮೇಲ್ವಿಚಾರಣೆಗಾಗಿ ಟ್ರಾನ್ಸ್ಕ್ರಿಪ್ಟ್ಗಳನ್ನು ಪೈಪ್ಲೈನ್ಗೆ ಸ್ಟ್ರೀಮ್ ಮಾಡಿ.
ಮಾನವ ಪರಿಶೀಲನೆಗಾಗಿ ಕರೆಗಳನ್ನು QA ಸಾಧನದಲ್ಲಿ ತೆರೆಯಿರಿ, ಅಥವಾ ಅವುಗಳನ್ನು ನಿಮ್ಮ ಸ್ವಂತ ಮೌಲ್ಯಮಾಪನ ಮಾಡೆಲ್ ಮೂಲಕ ಚಲಾಯಿಸಿ.
ವರ್ಗಾವಣೆ / ವೈಫಲ್ಯ ಸಂಭವಿಸಿದಾಗ ಮಾನವ ತಂಡದ ಸದಸ್ಯರನ್ನು ಪ್ರಚೋದಿಸಿ.