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

# Webhooks

> Receive call outcomes, transcripts, and analysis in your own systems as soon as they happen

Webhooks push data from telli to your systems in real time. When something happens on a call, telli sends a POST request to the endpoint you configure, so you can update CRM records, qualify leads, and trigger follow-ups without polling the API.

One endpoint can receive every event type, so most integrations need only a single URL.

## Events

| Event                                                                       | Sent when                                                    |
| --------------------------------------------------------------------------- | ------------------------------------------------------------ |
| [`call_ended`](/webhooks/events/call-ended)                                 | A call reaches a terminal state and analysis has run         |
| [`auto_dialer_status_changed`](/webhooks/events/auto-dialer-status-changed) | A contact enters or exits the auto dialer                    |
| [`contact_status_changed`](/webhooks/events/contact-status-changed)         | A contact's status changes. Deprecated, removed July 1, 2027 |

Each event page documents its full payload, field by field.

## Prerequisites

* A telli account with API access
* An endpoint URL that accepts POST requests, either from your own service or from an automation platform such as [Zapier](/integrations/zapier), [Make](/integrations/make), or [n8n](/integrations/n8n)

## Add an endpoint

<Steps>
  <Step title="Create an endpoint">
    In your own service or automation platform, create a URL that accepts POST requests and copy it.
  </Step>

  <Step title="Open the webhook portal">
    In telli, go to **Settings > Developer** and click **Configure** under **Webhook configuration**.

    <img className="block dark:hidden" src="https://mintcdn.com/telli/ChKLaNvNIdyJ0pnq/images/webhook-configure-light.png?fit=max&auto=format&n=ChKLaNvNIdyJ0pnq&q=85&s=494d62b663664b5e0a23c773a0a5b53a" alt="The webhook configuration panel in telli developer settings" width="2880" height="1440" data-path="images/webhook-configure-light.png" />

    <img className="hidden dark:block" src="https://mintcdn.com/telli/ChKLaNvNIdyJ0pnq/images/webhook-configure-dark.png?fit=max&auto=format&n=ChKLaNvNIdyJ0pnq&q=85&s=7aebddee42f73eaa6d10c1e09c28fb68" alt="The webhook configuration panel in telli developer settings" width="2880" height="1440" data-path="images/webhook-configure-dark.png" />
  </Step>

  <Step title="Add the URL">
    Click **Add Endpoint**, paste your URL, and click **Add**.

    <img className="block dark:hidden" src="https://mintcdn.com/telli/04zvWx53Iz0ReCTi/images/add-endpoint-light.png?fit=max&auto=format&n=04zvWx53Iz0ReCTi&q=85&s=28a6fe7e270dde5c989a592fed1384a2" alt="The new endpoint form with a URL field and event subscriptions" width="2880" height="1440" data-path="images/add-endpoint-light.png" />

    <img className="hidden dark:block" src="https://mintcdn.com/telli/04zvWx53Iz0ReCTi/images/add-endpoint-dark.png?fit=max&auto=format&n=04zvWx53Iz0ReCTi&q=85&s=eaa08afed27275e3a7e755c0ff7999e2" alt="The new endpoint form with a URL field and event subscriptions" width="2880" height="1440" data-path="images/add-endpoint-dark.png" />
  </Step>

  <Step title="Select events">
    Enable the events this endpoint should receive. Leaving all of them enabled is fine — your handler can branch on the `event` field.
  </Step>

  <Step title="Test it">
    Place a test call from your telli account, then confirm the message was delivered in the webhook portal and that your system reacted as expected.
  </Step>
</Steps>

<iframe width="560" height="315" src="https://www.loom.com/embed/d7efb65d2fe44b5fa0bf9bfbf27162ef?sid=6cf819e5-9a43-473c-93a9-3b0aff850520" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen />

<br />

## Acknowledge messages

Return any 2xx status code (200–299) within 15 seconds to mark a message as processed. Anything else — an error status, a timeout, a dropped connection — counts as a failure and the message is retried.

If your processing takes longer than 15 seconds, acknowledge the message first and do the work asynchronously.

<Tip>
  Disable CSRF protection on your endpoint, otherwise webhook POST requests are rejected before your handler runs.
</Tip>

## Verify signatures

Every message is signed so you can confirm it came from telli and not from someone else posting to your URL. Verification is optional but recommended in production. See Svix's explanation of [why you should verify webhooks](https://docs.svix.com/receiving/verifying-payloads/why).

Your signing secret is in the webhook portal, under **Webhook configuration** in the telli dashboard.

<Accordion title="Node.js example">
  ```javascript theme={null}
  import { Webhook } from "svix";

  // Copy this from Webhook configuration in the telli dashboard
  const secret = "whsec_GET_THIS_FROM_THE_DASHBOARD";

  // These headers arrive with every webhook message
  const headers = {
    "svix-id": "msg_p5jXN8AQM9LWM0D4loKWxJek",
    "svix-timestamp": "1614265330",
    "svix-signature": "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=",
  };

  // The raw, unparsed request body
  const body = '{"test": 2432232314}';

  const wh = new Webhook(secret);

  // Throws on failure, returns the verified payload on success
  const payload = wh.verify(body, headers);
  ```
</Accordion>

Svix's [verification documentation](https://docs.svix.com/receiving/verifying-payloads/how) has equivalent examples for Python, Go, Java, PHP, and other languages.

## Retries

Failed deliveries are retried automatically with exponential backoff. Each delay starts after the preceding attempt fails:

| Attempt | Delay after previous failure |
| ------- | ---------------------------- |
| 1       | Immediately                  |
| 2       | 5 seconds                    |
| 3       | 5 minutes                    |
| 4       | 30 minutes                   |
| 5       | 2 hours                      |
| 6       | 5 hours                      |
| 7       | 10 hours                     |
| 8       | 10 hours                     |

A message that fails three times before succeeding arrives roughly 35 minutes and 5 seconds after the first attempt. If an endpoint is removed or disabled, its pending delivery attempts stop.

You can also retry any message manually from the webhook portal, or use **Recover** to replay all failed messages from a given date.
