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

# Webhooks

> Register a URL and we POST signed events to it.

## Managing endpoints

| Method   | Path                                                                                                           |                                                                           |
| -------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `POST`   | [`/v1/webhook-endpoints`](/api-reference/webhook-endpoints/create)                                             | Create. **Returns the signing secret once.**                              |
| `GET`    | [`/v1/webhook-endpoints`](/api-reference/webhook-endpoints/list)                                               | List.                                                                     |
| `GET`    | [`/v1/webhook-endpoints/{id}`](/api-reference/webhook-endpoints/get)                                           | One endpoint.                                                             |
| `PATCH`  | [`/v1/webhook-endpoints/{id}`](/api-reference/webhook-endpoints/update)                                        | Change `url`, `events`, `agent_ids`, `description`, `enabled`.            |
| `DELETE` | [`/v1/webhook-endpoints/{id}`](/api-reference/webhook-endpoints/delete)                                        | Stop deliveries. History is kept.                                         |
| `POST`   | [`/v1/webhook-endpoints/{id}/rotate-secret`](/api-reference/webhook-endpoints/rotate-secret)                   | New secret, shown once. The old one stops working immediately.            |
| `POST`   | [`/v1/webhook-endpoints/{id}/test`](/api-reference/webhook-endpoints/test)                                     | Send a sample event now. See [Testing your endpoint](/webhooks/testing).  |
| `GET`    | [`/v1/webhook-endpoints/{id}/deliveries`](/api-reference/webhook-endpoints/list-deliveries)                    | Delivery log. Filters: `call_id`, `event`, `status`, `page`, `page_size`. |
| `GET`    | [`/v1/webhook-endpoints/{id}/deliveries/{delivery_id}`](/api-reference/webhook-endpoints/get-delivery)         | One delivery with the payload sent and every attempt.                     |
| `POST`   | [`/v1/webhook-endpoints/{id}/deliveries/{delivery_id}/retry`](/api-reference/webhook-endpoints/retry-delivery) | Queue another attempt now.                                                |

Create:

```json theme={null}
POST /v1/webhook-endpoints
{
  "url": "https://example.com/webhooks/contour",
  "events": ["call.started", "call.ended", "call.analyzed"],
  "agent_ids": ["3f1c1b2e-..."],
  "description": "Production"
}
```

```json theme={null}
201
{
  "id": "b7e1...",
  "url": "https://example.com/webhooks/contour",
  "events": ["call.started", "call.ended", "call.analyzed"],
  "agent_ids": ["3f1c1b2e-..."],
  "enabled": true,
  "secret_hint": "k9Qz",
  "secret": "whsec_....................",
  "created_at": "...", "updated_at": "..."
}
```

* The URL must be `https` and publicly reachable. Private and loopback
  addresses are rejected.
* `agent_ids` limits the endpoint to calls made by those agents. Omit it to
  receive events for every call in your organization, including calls started
  from the Contour dashboard. Use the `source` field on the call object to tell
  them apart.
* `secret` appears in this response and in rotate-secret only. Store it in
  your webhook handler's configuration.

## Events

| Event           | When                                                                           | What's filled in                                                                         |
| --------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
| `call.started`  | We accepted your `POST /v1/calls` and began dialing. Not "answered".           | `status: queued`, numbers, `variables`, `metadata`.                                      |
| `call.ended`    | The call finished, before any analysis. Usually within seconds of hangup.      | `disposition`, `duration_ms`, `disconnection_reason`, `recording_url`. `analysis: null`. |
| `call.analyzed` | Summary and structured extraction are ready. Usually 5–30s after `call.ended`. | Everything, including `analysis`.                                                        |

## Request format

```
POST https://example.com/webhooks/contour
Content-Type: application/json
User-Agent: Contour-Webhooks/1.0
X-Contour-Event: call.ended
X-Contour-Delivery-Id: 6a0d...-...
X-Contour-Signature: t=1725900000,v1=3f9a...

{
  "event": "call.ended",
  "id": "6a0d...",
  "created_at": "2026-09-10T14:04:36+00:00",
  "call": { ...call object... }
}
```

The `call` key is the full [call object](/calls/call-object).

<Tip>
  Respond with any `2xx` within 10 seconds. The body is ignored. Do your real
  work after responding, or in a queue: a slow handler looks like a failure to us
  and gets retried.
</Tip>

Webhook requests do not carry your API key. They are authenticated by the
signature header instead. See [Verifying signatures](/webhooks/verifying-signatures).
