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

# Webhooks

> Get notified when a transcript or diarization finishes.

Pass `webhook_url` when you create a transcript or a diarization. When it finishes, AirCaps sends a `POST`:

```json theme={null}
{"event": "transcript.completed", "id": "tr_01k6z...", "status": "completed", "metadata": {"meeting_id": 42}}
```

`event` is `transcript.completed` or `transcript.failed` (for diarizations, `diarization.completed` or `diarization.failed`, with a `dia_...` ID). The payload never contains the result; fetch it with [`GET /v1/transcripts/{id}`](https://aircaps.ai/docs/api-reference/get-transcript) or [`GET /v1/diarizations/{id}`](https://aircaps.ai/docs/api-reference/get-diarization).

* To add your own header to each delivery, set `webhook_auth_header_name` and `webhook_auth_header_value` on the request.
* `webhook_url` must be a public http(s) address. Redirects are not followed.
* Canceled jobs send no webhook.

## Verify signatures

Deliveries are signed per [Standard Webhooks](https://www.standardwebhooks.com) with your account's webhook secret (`whsec_...`). Find and rotate it in the console under **API keys → Webhook signing secret**.

Headers: `webhook-id`, `webhook-timestamp`, `webhook-signature: v1,<base64>`.

```python theme={null}
# pip install standardwebhooks
import os
from standardwebhooks.webhooks import Webhook, WebhookVerificationError

wh = Webhook(os.environ["AIRCAPS_WEBHOOK_SECRET"])
try:
    event = wh.verify(request_body_bytes, request_headers)   # raw body bytes and the request headers
except WebhookVerificationError:
    ...                                                       # reject with 400
```

Manual check:

1. Base64-decode the secret without its `whsec_` prefix.
2. Compute HMAC-SHA256 with it over `{webhook-id}.{webhook-timestamp}.{raw body}` and base64-encode the result.
3. Compare it in constant time with the value after `v1,` in `webhook-signature`.
4. Reject timestamps more than 5 minutes old.

## Delivery

* Reply with any 2xx within 15 seconds.
* Failures (including timeouts, network errors and 3xx) are retried for about 24 hours: after 30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h, 8 h and 8 h.
* A 4xx other than 408 or 429 stops retries.
* `webhook-id` is stable across retries of one event; use it to deduplicate.
* The transcript shows `webhook_status` (`pending`, `delivered` or `failed`) and the last HTTP status as `webhook_status_code`.
* Rotating the secret applies to pending retries too.


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