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

# Webhooks

> Receive processing results via webhook.

Async and batch requests deliver results to your webhook URL. Matil sends a `POST` request with the result payload when processing completes.

## Configuration

Include a `webhook` object in your request:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "webhook": {
    "url": "https://your-server.com/webhook",
    "secret": "your-webhook-secret"
  }
}
```

## Signature verification

Every webhook includes a `X-Matil-Signature` header:

```
X-Matil-Signature: t=1234567890,v1=abc123...
```

Verify it to ensure the request came from Matil:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import hmac
import hashlib
import time

def verify_webhook(payload: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    timestamp = parts["t"]
    signature = parts["v1"]

    signed_payload = f"{timestamp}.{payload.decode()}"
    expected = hmac.new(
        secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        return False
    if abs(time.time() - int(timestamp)) > 300:
        return False
    return True
```

<Warning>
  Always verify webhook signatures. Without verification, anyone could send fake payloads to your endpoint.
</Warning>

## Retry behavior

If your endpoint doesn't respond with a `2xx` status, Matil retries up to 3 times with exponential backoff.

## Events

| Event                  | Trigger                                   |
| ---------------------- | ----------------------------------------- |
| `structurer.completed` | Async processing succeeded.               |
| `structurer.failed`    | Async processing failed.                  |
| `batch.item.completed` | A batch item finished (incremental mode). |
| `batch.completed`      | The entire batch finished.                |
| `batch.failed`         | The entire batch failed.                  |
