> For the complete documentation index, see [llms.txt](https://twentytwo.documentationai.com/llms.txt).
> Use it to discover all available pages before exploring further.

# Webhooks

Get notified instantly when a call completes via webhook events.

Twenty2 sends a webhook event to your server every time a call ends. This is the most reliable way to capture call outcomes, recordings, transcripts, and output variables — without polling the API.

---

## Setup

<Steps>
  <Step title="Go to Integrations" title-type="p">
    Navigate to **Profile → Integrations** in your Twenty2 dashboard
  </Step>

  <Step title="Enter your endpoint URL" title-type="p">
    Find the **Webhook URL** field and enter your publicly accessible HTTPS endpoint
  </Step>

  <Step title="Save" title-type="p">
    Click **Save** — Twenty2 will immediately start sending events to your URL
  </Step>
</Steps>

<Callout kind="note" collapsed="false">
  Twenty2 sends a `POST` request to your URL every time a call ends. Make sure your endpoint returns a `200` response within 5 seconds.
</Callout>

---

## Events

| Event            | Description                               |
| ---------------- | ----------------------------------------- |
| `call.failed`    | Call did not connect or was unanswered    |
| `call.completed` | Call connected and completed successfully |

---

## Example Payload

```json
{
  "event": "call.failed",
  "event_id": "evt_dd640228-c82f-494f-b0ff-4ef3db3aaf3b",
  "timestamp": "2026-05-22T07:18:39.684Z",
  "workspace_id": "69bcb7e7cf2a02ecc7a28e17",
  "assistant_id": "6a02dc5d92b9cbce7962a2b5",
  "assistant_name": "Varsha",
  "call": {
    "call_id": "6a100328ba090039ac8610a2",
    "direction": "outbound",
    "status": "failed",
    "from_number": "7971441943",
    "to_number": "9871532305",
    "started_at": "2026-05-22T07:18:30.092Z",
    "answered_at": null,
    "ended_at": "2026-05-22T07:18:39.684Z",
    "duration_seconds": 0,
    "billed_duration_seconds": 0,
    "call_cost_inr": 0,
    "disconnection_reason": "unanswered"
  },
  "campaign": {
    "campaign_id": "6a100328ba090039ac8610a0",
    "campaign_name": "web test"
  },
  "contact": {
    "phone_number": "9871532305",
    "input_variables": {
      "customerName": "Lakshay",
      "productInCart": "Shoes"
    }
  },
  "output_variables": {},
  "recording": {
    "available": false,
    "url": null
  },
  "transcript": {
    "available": false
  }
}
```

---

## Payload Reference

### Root fields

| Field            | Type   | Description                                    |
| ---------------- | ------ | ---------------------------------------------- |
| `event`          | string | Event type — `call.completed` or `call.failed` |
| `event_id`       | string | Unique identifier for this webhook delivery    |
| `timestamp`      | string | Time the event was fired (ISO 8601)            |
| `workspace_id`   | string | Your Twenty2 workspace ID                      |
| `assistant_id`   | string | ID of the assistant that handled the call      |
| `assistant_name` | string | Name of the assistant                          |

### `call` object

| Field                     | Type   | Description                                        |
| ------------------------- | ------ | -------------------------------------------------- |
| `call_id`                 | string | Unique identifier for the call                     |
| `direction`               | string |  `outbound`                                        |
| `status`                  | string | Final call status — `completed` or `failed`        |
| `from_number`             | string | Number the call was made from                      |
| `to_number`               | string | Number the call was made to                        |
| `started_at`              | string | Call start time (ISO 8601)                         |
| `answered_at`             | string | Time call was answered — `null` if unanswered      |
| `ended_at`                | string | Call end time (ISO 8601)                           |
| `duration_seconds`        | number | Total call duration in seconds                     |
| `billed_duration_seconds` | number | Billable duration in seconds                       |
| `call_cost_inr`           | number | Call cost in INR                                   |
| `disconnection_reason`    | string | Reason call ended — e.g. `unanswered`, `completed` |

### `campaign` object

| Field           | Type   | Description                                      |
| --------------- | ------ | ------------------------------------------------ |
| `campaign_id`   | string | ID of the campaign — `null` for standalone calls |
| `campaign_name` | string | Name of the campaign                             |

### `contact` object

| Field             | Type   | Description                                          |
| ----------------- | ------ | ---------------------------------------------------- |
| `phone_number`    | string | Contact's phone number                               |
| `input_variables` | object | Key-value pairs passed into the call at trigger time |

### `output_variables` object

Key-value pairs captured by the assistant during the call. Empty `{}` if the call did not connect or no variables were captured.

### `recording` object

| Field       | Type    | Description                                             |
| ----------- | ------- | ------------------------------------------------------- |
| `available` | boolean | `true` if a recording is available for this call        |
| `url`       | string  | URL to download the recording — `null` if not available |

### `transcript` object

| Field       | Type    | Description                                       |
| ----------- | ------- | ------------------------------------------------- |
| `available` | boolean | `true` if a transcript is available for this call |

---

