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

# Webhooks

> Receive every call's result the moment it is ready.

Instead of polling, give Telleo one HTTPS endpoint. When a call reaches a final status, Telleo sends it there.

## Setting the endpoint

In the dashboard: **Settings → AI calling → API & webhooks → Webhook**. Enter the URL and save. Or with the API:

```bash theme={null}
curl -X PUT https://api.telleo.ai/v1/webhook \
  -H "X-API-Key: $TELLEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://crm.example.com/telleo/webhook"}'
```

The first time, the response contains the **signing secret** (`whsec_…`). It is shown once: store it with your other secrets. Your server uses it to [verify every delivery](/webhooks/verify-signatures).

Requirements for the URL:

* `https://`, with a valid certificate;
* a public address (private, loopback and link-local addresses are refused);
* no username or password in the URL; redirects are not followed.

One endpoint per account receives every event. To send results to several systems, fan them out from your endpoint.

## Events

| Event | When |
| - | - |
| `call.completed` | A call connected and is final. `data.outcome` holds the result. |
| `call.not_connected` | A call ended without connecting: `no_answer`, `busy`, `failed`, `canceled` or `expired`. |
| `webhook.test` | Sent only when you click **Send test event** or call `POST /v1/webhook/test`. |

Each call produces **exactly one** of `call.completed` or `call.not_connected`. See [Event payloads](/webhooks/events).

## Responding

* Answer with any `2xx` status within **10 seconds**. Do the real work (updating your CRM, sending a message) after you respond, or in a background job.
* Any other status, a timeout or a connection error counts as a failure, and the event is retried.

## Retries

A failed delivery is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 6 hours: six attempts over about 9 hours. After that, the event is dropped, but the call is still there: `GET /v1/calls/{id}` returns the same data.

Because of retries, your endpoint may see the same event more than once. Every attempt carries the same `id` (also in the `Telleo-Event-Id` header). Store the ids you have handled and skip repeats.

<Tip>
  If your endpoint was down for longer than the retry window, catch up with `GET /v1/calls?created_after=…` and process any call you have no record of.
</Tip>

## Managing the endpoint

| Action | Dashboard | API |
| - | - | - |
| See it | Webhook section | `GET /v1/webhook` |
| Change the URL (keeps the secret) | Edit and save | `PUT /v1/webhook` |
| New secret | **New secret** | `POST /v1/webhook/rotate-secret` |
| Send a test event | **Send test event** | `POST /v1/webhook/test` |
| Stop deliveries | **Remove** | `DELETE /v1/webhook` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.