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

# Calls

> Retrieve call details and paginated call lists.

Calls are read-only from the API — they are created by the dialer engine
when a campaign is running. Use these endpoints to fetch call details,
timing, dispositions, and AI analysis results.

## Get a call

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.yotel.in/api/v1/calls/{call_id} \
    -H "Authorization: Bearer yt_live_YOUR_KEY"
  ```

  ```python Python theme={null}
  call = client.calls.get("call_id")
  print(call.disposition, call.talk_duration_s)
  ```

  ```typescript TypeScript theme={null}
  const call = await client.calls.get("call_id");
  console.log(call.disposition, call.talk_duration_s);
  ```
</CodeGroup>

**Scope:** `calls:read`  |  **Status:** `200 OK`

### Response fields

| Field                | Type            | Description                                                                            |
| -------------------- | --------------- | -------------------------------------------------------------------------------------- |
| `id`                 | string          | Call UUID                                                                              |
| `campaign_id`        | string \| null  | Campaign this call belongs to                                                          |
| `lead_id`            | string \| null  | Lead that was dialed                                                                   |
| `agent_id`           | string \| null  | Agent who handled the call (null for voice-agent-only calls)                           |
| `fs_uuid`            | string          | FreeSWITCH channel UUID                                                                |
| `direction`          | string          | `"outbound"` or `"inbound"`                                                            |
| `status`             | string          | `"dialing"`, `"ringing"`, `"answered"`, `"agent_connected"`, `"completed"`, `"failed"` |
| `dial_time`          | string \| null  | ISO 8601 timestamp when the call was originated                                        |
| `ring_time`          | string \| null  | When the remote party started ringing                                                  |
| `answer_time`        | string \| null  | When the remote party answered                                                         |
| `agent_connect_time` | string \| null  | When the call was bridged to a human agent                                             |
| `end_time`           | string \| null  | When the call ended                                                                    |
| `ring_duration_s`    | integer \| null | Seconds from ring to answer                                                            |
| `talk_duration_s`    | integer \| null | Seconds from answer to hangup                                                          |
| `total_duration_s`   | integer \| null | Seconds from dial to hangup                                                            |
| `hangup_cause`       | string \| null  | FreeSWITCH hangup cause (e.g., `"NORMAL_CLEARING"`, `"NO_ANSWER"`)                     |
| `has_recording`      | boolean         | Whether a recording exists                                                             |
| `recording_url`      | string \| null  | Signed URL (available after `call.recording_ready` webhook)                            |
| `disposition`        | string \| null  | Agent- or AI-set disposition code                                                      |
| `notes`              | string \| null  | Agent notes                                                                            |
| `ai_summary`         | string \| null  | Gemini-generated call summary                                                          |
| `ai_sentiment`       | string \| null  | Detected sentiment (`"positive"`, `"negative"`, `"neutral"`)                           |
| `ai_next_action`     | string \| null  | Suggested follow-up action                                                             |

***

## List calls for a campaign

Returns a paginated list of calls for a specific campaign.

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.yotel.in/api/v1/campaigns/{campaign_id}/calls?page=1&page_size=50" \
    -H "Authorization: Bearer yt_live_YOUR_KEY"
  ```

  ```python Python theme={null}
  calls = client.calls.list(campaign_id="campaign_id", page=1, page_size=50)
  print(f"Total: {calls.total}, Page: {calls.page}")
  ```

  ```typescript TypeScript theme={null}
  const calls = await client.calls.list({
    campaignId: "campaign_id",
    page: 1,
    pageSize: 50,
  });
  console.log(`Total: ${calls.total}, Page: ${calls.page}`);
  ```
</CodeGroup>

**Scope:** `calls:read`  |  **Status:** `200 OK`

### Query parameters

| Parameter     | Type    | Default | Description                |
| ------------- | ------- | ------- | -------------------------- |
| `page`        | integer | `1`     | Page number (1-indexed)    |
| `page_size`   | integer | `25`    | Results per page (1–200)   |
| `status`      | string  | —       | Filter by call status      |
| `disposition` | string  | —       | Filter by disposition code |

### Response

```json theme={null}
{
  "items": [ /* CallDetail objects */ ],
  "total": 1247,
  "page": 1,
  "page_size": 50
}
```

***

## Errors

| Status | Condition                                                |
| ------ | -------------------------------------------------------- |
| `404`  | Call or campaign not found, or belongs to another tenant |
