telephony.complete / web.complete

ஒவ்வொரு அழைப்பும் முடிந்த பிறகு ஒரு நிறைவு நிகழ்வு தூண்டப்படும் — உள்வரும் தொலைபேசி அழைப்பு, வெளிச்செல்லும் தொலைபேசி அழைப்பு, வலை அழைப்பு அல்லது சோதனை அழைப்பு (பில்டர் மைக் அமர்வு). இது தடையற்றது: எந்த 2xx பதிலையும் அனுப்புங்கள்.

நிகழ்வு இரண்டு பாதைகளிலும் வழங்கப்படும்:

கோரிக்கை பேலோட் (எண்ட்பாயிண்ட் வழங்கல்கள்)

{
  "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_idintegerஇந்த அழைப்பிற்கான ஒவ்வொரு நிகழ்விலும் நிலையானது
directionstringinbound, outbound, web, test. வரலாற்று பேலோடுகளில் பழைய mic அல்லது widget மதிப்புகள் இருக்கலாம்
from_number, to_numberstringE.164. வலை அழைப்புகள் மற்றும் சோதனை அழைப்புகளுக்கு from_number என்பது நேரடியான "web" ஆகும்
origin_domainstringவலை/சோதனைக்கு மட்டும் — விட்ஜெட்டை ஹோஸ்ட் செய்த பக்கத்தின் மூல டொமைன் (மைக் அமர்வுகளுக்கு காலியாக இருக்கும்)
start_time, end_timetimestampISO 8601 UTC
duration_secondsinteger | nullதொடக்க/முடிவு நேரத்திலிருந்து பெறப்பட்டது
statusstringcompleted அல்லது failed
end_reasonstringகீழேயுள்ள அட்டவணையைப் பார்க்கவும்
product, voicestringஅழைப்பு நேரத்தில் செயலிலிருந்த ஏஜென்ட் கட்டமைப்பு
transfer_numberstring | nullஅழைப்பு மாற்றப்பட்டபோது அமைக்கப்படும்
recording_urlstring | nullகாலாவதியாகும் கையொப்பமிடப்பட்ட URL; உடனடியாகப் பதிவிறக்கவும். பதிவுக் கலைப்பொருள் கிடைக்காதபோது null
billable_minutesnumberகட்டணமிடப்பட்ட நிமிடங்கள், அருகிலுள்ள கால் நிமிடத்திற்கு வட்டமிடப்படும் (15-விநாடி அதிகரிப்புகள், குறைந்தபட்சம் 0.25). நேரடியாக குரலஞ்சலுக்குச் செல்லும் அழைப்புகளும் அவற்றின் உண்மையான மீட்டர் செய்யப்பட்ட நிமிடங்களை இங்கே தெரிவிக்கும், ஆனால் கட்டணம் திட்ட விகிதத்தில் ஒரு நிமிடத்திற்கு வரம்பிடப்படும்.
billing_total_centsintegerUSD சென்ட்கள்
transcriptsarrayஒவ்வொரு உரையாடல் முறைக்குமான டிரான்ஸ்கிரிப்ட் பதிவுகள்; டிரான்ஸ்கிரிப்ட் கிடைக்காதபோது காலியாக இருக்கலாம்

முடிவுக்கான காரணங்கள்

மதிப்புபொருள்
user_hangupஎதிர் தரப்பு முதலில் அழைப்பைத் துண்டித்தது
ai_hangupAI திட்டமிட்டு அழைப்பை முடித்தது
ai_transferAI அழைப்பை மாற்றியது; transfer_number அமைக்கப்படும்
ai_warm_transferAI வார்ம் (பங்கேற்புடனான) மாற்றத்தை நிறைவு செய்தது
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"] }
    }
  }
]
புலம்வகைவிளக்கம்
rolestringuser, model, tool, அல்லது system
content_typestringபேச்சுக்கு text/plain; கருவி அழைப்புகள், கருவி முடிவுகள் மற்றும் சிஸ்டம் நிகழ்வுகளுக்கு application/json
contentstring | objectபேச்சு உரை அல்லது மேலே காட்டப்பட்ட கட்டமைக்கப்பட்ட ஆப்ஜெக்ட். கருவி அழைப்புகள்: {"tool_call": name, "arguments": {…}}. கருவி முடிவுகள்: {"tool_name": name, "response": {…}}
start_ms, end_msintegerஅழைப்பு தொடக்கத்திலிருந்து ஆஃப்செட்கள், ms. ஆடியோ நேரம் அறியப்பட்டால் இருக்கும்
ttfa_msintegerஅளவிடப்பட்டால், model முறைக்கான முதல்-ஆடியோ-வரை நேரம்
audio_url, audio_urlsstring / arrayஒவ்வொரு முறைக்கும் பதிவு செய்யப்பட்ட ஆடியோவிற்கான காலாவதியாகும் கையொப்பமிடப்பட்ட URL-கள்

முழுமையாக கட்டமைக்கப்பட்ட முறை வரலாற்றுக்கு (குறுக்கீட்டு குறிப்பான்கள், ack-prompt-கள் மற்றும் மூல நிலைகளுடன்), இதைப் பயன்படுத்துங்கள்: GET /v1/calls/{call_id}/history.

பழைய பேலோட் வேறுபாடுகள்

பழைய ஒற்றை-URL வெப்ஹுக் உறை {"type": "telephony.complete" | "web.complete", "data": {…}}; இதில் event_id இல்லை, மேலும் அதன் data, எண்ட்பாயிண்ட் பேலோடிலிருந்து வேறுபடுகிறது:


எடுத்துக்காட்டு ஹேண்ட்லர்

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

பொதுவான பயன்பாட்டு வழக்குகள்

CRM ஒருங்கிணைப்பு

ஒவ்வொரு அழைப்பின் டிரான்ஸ்கிரிப்ட் மற்றும் பதிவு URL-ஐ உங்கள் வாடிக்கையாளர் பதிவுகளுடன் சேர்த்து சேமிக்கவும்.

பகுப்பாய்வு

தலைப்பு மாடலிங், CSAT சிக்னல் பிரித்தெடுத்தல் அல்லது பரிமாற்ற விகித கண்காணிப்புக்காக டிரான்ஸ்கிரிப்ட்களை ஒரு பைப்லைனுக்கு ஸ்ட்ரீம் செய்யவும்.

தர மதிப்பாய்வு

மனித மதிப்பாய்வுக்காக அழைப்புகளை QA கருவியில் திறக்கவும் அல்லது அவற்றை உங்கள் சொந்த மதிப்பீட்டு மாடல் மூலம் இயக்கவும்.

அறிவிப்புகள்

பரிமாற்றம் / தோல்வி ஏற்பட்டால் ஒரு மனித குழு உறுப்பினரைத் தூண்டவும்.


தொடர்புடையவை