> ## Documentation Index
> Fetch the complete documentation index at: https://docs.callkaro.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Call Ended Event

> Receive data when a call completes

## Event Overview

**Event Name:** `call_ended`

**Trigger:** Sent automatically when any call completes

**Method:** `POST`\
**Content-Type:** `application/json`

## Payload Structure

```json theme={null}
{
  "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

| Field   | Type   | Description                   |
| ------- | ------ | ----------------------------- |
| `event` | String | Always `"call_ended"`         |
| `data`  | Object | Contains all call information |

### Data Object Fields

| Field                 | Type    | Description                                              |
| --------------------- | ------- | -------------------------------------------------------- |
| `callSid`             | String  | Unique identifier for the call session                   |
| `name`                | String  | Call type                                                |
| `agent`               | String  | Agent ID that handled the call                           |
| `versionId`           | String  | Version ID of the agent                                  |
| `from`                | String  | Phone number call originated from                        |
| `to`                  | String  | Phone number called                                      |
| `recordingUrl`        | String  | URL to call recording audio file                         |
| `call_duration`       | Number  | Duration in seconds                                      |
| `time`                | String  | Timestamp when call was made                             |
| `transcription`       | String  | Full call transcript                                     |
| `batchId`             | String  | Batch/Campaign ID (if applicable)                        |
| `hangup_reason`       | String  | Reason call ended                                        |
| `call_metadata`       | Object  | Custom metadata passed when triggering call              |
| `try_count`           | Number  | Trial count: -1 for inbound, 0 for first, 1+ for retries |
| `post_call`           | Object  | Post-call variables (values only)                        |
| `post_call_detail`    | Object  | Post-call variables with values and reasoning            |
| `functions_called`    | Array   | Functions executed during/after call                     |
| `disposition_reason`  | String  | Short disposition for the call                           |
| `conversion_status`   | Boolean | Whether lead was converted/goal achieved                 |
| `next_call_scheduled` | Boolean | Whether another call was scheduled                       |
| `call_link`           | String  | Link to view call in dashboard                           |

## Reference Documentation

<CardGroup cols={2}>
  <Card title="Call Types" icon="phone" href="/calls/call-types">
    View all call type values
  </Card>

  <Card title="Hangup Reasons" icon="phone-hangup" href="/calls/hangup-reasons">
    View all hangup reason values
  </Card>
</CardGroup>

## Example Implementation

### Node.js (Express)

```javascript theme={null}
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)

```python theme={null}
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)
