Skip to main content

Event Overview

Event Name: call_ended Trigger: Sent automatically when any call completes Method: POST
Content-Type: application/json

Payload Structure

{
  "event": "call_ended",
  "data": {
    "callSid": "2303fa770b666a64ab1694c1e",
    "name": "outbound",
    "agent": "6803fa770b666a64ab1694c1e",
    "versionId": "1203fa770b666a64ab1694c1e",
    "from": "919876543210",
    "to": "918765432109",
    "recordingUrl": "https://example.com/recording.mp3",
    "call_duration": 120,
    "time": "2025-12-19 16:01:07",
    "transcription": "Full call transcript...",
    "batchId": "0303fa770b666a64ab1694c1e",
    "hangup_reason": "CLIENT_INITIATED",
    "call_metadata": {
      "name": "Jatin",
      "age": 25
    },
    "try_count": 0,
    "post_call": {
      "lead_status": "interested"
    },
    "post_call_detail": {
      "lead_status": {
        "value": "interested",
        "comment": "Customer showed interest"
      }
    },
    "functions_called": [
      {
        "name": "update_crm",
        "success": true,
        "timestamp": "2025-12-19T15:25:00.000Z"
      }
    ],
    "disposition_reason": "Customer requested callback",
    "conversion_status": true,
    "next_call_scheduled": false,
    "call_link": "https://callkaro.ai/dashboard/call-history?call_id=abc123"
  }
}

Field Descriptions

FieldTypeDescription
eventStringAlways "call_ended"
dataObjectContains all call information

Data Object Fields

FieldTypeDescription
callSidStringUnique identifier for the call session
nameStringCall type
agentStringAgent ID that handled the call
versionIdStringVersion ID of the agent
fromStringPhone number call originated from
toStringPhone number called
recordingUrlStringURL to call recording audio file
call_durationNumberDuration in seconds
timeStringTimestamp when call was made
transcriptionStringFull call transcript
batchIdStringBatch/Campaign ID (if applicable)
hangup_reasonStringReason call ended
call_metadataObjectCustom metadata passed when triggering call
try_countNumberTrial count: -1 for inbound, 0 for first, 1+ for retries
post_callObjectPost-call variables (values only)
post_call_detailObjectPost-call variables with values and reasoning
functions_calledArrayFunctions executed during/after call
disposition_reasonStringShort disposition for the call
conversion_statusBooleanWhether lead was converted/goal achieved
next_call_scheduledBooleanWhether another call was scheduled
call_linkStringLink to view call in dashboard

Reference Documentation

Example Implementation

Node.js (Express)

const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhook/call-webhook', (req, res) => {
  const { event, data } = req.body;
  
  if (event === 'call_ended') {
    console.log('Call ended:', data.callSid);
    console.log('Duration:', data.call_duration, 'seconds');
    console.log('Hangup reason:', data.hangup_reason);
    console.log('Conversion:', data.conversion_status);
    
    // Process webhook data
    // Update CRM, send notifications, etc.
    
    res.status(200).json({ 
      status: 'success',
      message: 'Webhook received' 
    });
  } else {
    res.status(400).json({ 
      status: 'error',
      message: 'Unknown event type' 
    });
  }
});

app.listen(3000);

Python (FastAPI)

from fastapi import FastAPI, Request
import uvicorn

app = FastAPI()

@app.post("/webhook/call-webhook")
async def handle_webhook(request: Request):
    payload = await request.json()
    event = payload.get("event")
    data = payload.get("data", {})

    if event == "call_ended":
        print(f"Call ended: {data.get('callSid')}")
        print(f"Duration: {data.get('call_duration')} seconds")
        print(f"Hangup: {data.get('hangup_reason')}")
        print(f"Converted: {data.get('conversion_status')}")
        
        # Process webhook data
        
        return {
            "status": "success",
            "message": "Webhook received"
        }

    return {
        "status": "error",
        "message": "Unknown event type"
    }

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

Response Requirements

Your webhook endpoint must:
  • Respond with HTTP status code 2xx (preferably 200)
  • Respond within 5 seconds
  • Return a JSON response (optional but recommended)