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

# Webhooks overview

> Receive signed HTTPS callbacks when calls end, summaries are ready, balances run low and more.

A webhook endpoint is an HTTPS URL on your server. Larynth sends a `POST` request to it each time an event you subscribed to happens, for example when a call ends or its post-call summary is ready.

## Set up an endpoint

Create an endpoint in the dashboard or with the API. You choose the URL and the event types to receive.

```bash theme={null}
curl https://api-us.larynth.com/v1/webhooks \
  -H "Authorization: Bearer $LARYNTH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/larynth",
    "event_types": ["call.ended", "call.analyzed"],
    "description": "CRM sync"
  }'
```

The response includes a `secret` that starts with `whsec_`. It is shown once. Store it in your secrets manager, because you need it to [verify signatures](https://docs.larynth.com/webhooks/verify-signatures.md).

The URL must use HTTPS and must not contain credentials. Addresses on private or internal networks are refused with `webhook.url_not_allowed`. Creating endpoints needs the `webhooks:write` scope and an admin role.

## The request Larynth sends

Each delivery is a `POST` with a JSON body and these headers.

| Header | Value |
| - | - |
| `Content-Type` | `application/json` |
| `User-Agent` | `Larynth-Webhooks/1.0` |
| `webhook-id` | Unique message id, for example `msg_0123456789abcdef`. It stays the same across retries. |
| `webhook-timestamp` | Unix time in seconds when the attempt was sent. |
| `webhook-signature` | One or more space-separated signatures, each like `v1,<base64>`. |

The signing scheme follows the [Standard Webhooks](https://www.standardwebhooks.com) specification.

The body has the same four fields for every event.

```json theme={null}
{
  "id": "msg_0123456789abcdef",
  "type": "call.ended",
  "timestamp": "2026-11-01T12:00:00Z",
  "data": {
    "call_id": "c1"
  }
}
```

| Field | Description |
| - | - |
| `id` | The message id. Same value as the `webhook-id` header. Use it to ignore duplicates. |
| `type` | The event type. See [events](https://docs.larynth.com/webhooks/events.md). |
| `timestamp` | When the event was created, RFC 3339 in UTC. |
| `data` | The event payload. The fields depend on `type`. |

## Respond quickly

Return any `2xx` status within 10 seconds. Larynth reads at most the first 64 KB of your response and keeps a short excerpt for the delivery log. Redirects are not followed and count as a failure.

Do the real work after you respond. Verify the signature, store the event, return `200`, then process it from a queue.

## Retries

If your endpoint times out, can't be reached or returns anything other than `2xx`, Larynth retries the same message. A message gets up to 9 attempts in total, with these waits between them:

| After attempt | Wait before the next |
| - | - |
| 1 | 30 seconds |
| 2 | 2 minutes |
| 3 | 10 minutes |
| 4 | 30 minutes |
| 5 | 1 hour |
| 6 | 2 hours |
| 7 | 4 hours |
| 8 | 8 hours |

After the last attempt the delivery is marked `failed` and Larynth stops trying that message.

If an endpoint fails 50 deliveries in a row, Larynth disables it. Its `status` becomes `disabled` and `disabled_reason` says why. A successful delivery resets the counter. Fix the problem and re-enable the endpoint with `PATCH /v1/webhooks/{id}`.

Delivery is at least once. The same event can arrive more than once, so make your handler safe to run twice by keying on `id`.

## Inspect and test

* `POST /v1/webhooks/{id}/test` sends a test event to your endpoint. The `data` of a test event is `{"test": true, "message": "This is a test event from Larynth."}`.
* `GET /v1/webhooks/{id}/deliveries` lists attempts with status, response code, response time and a short excerpt of your response. Filter by `status`.
* `POST /v1/webhooks/{id}/rotate-secret` issues a new secret. The old secret stays valid for 24 hours, and during that time every delivery carries a signature for each secret. See [verify signatures](https://docs.larynth.com/webhooks/verify-signatures.md#rotate-a-secret).


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