> ## 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

> Recibe resultados de procesamiento vía webhook.

Las peticiónes asíncronas y por lotes entregan resultados a tu URL de webhook. Matil envía una petición `POST` con el payload del resultado cuando el procesamiento termina.

## Configuración

Incluye un objeto `webhook` en tu petición:

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

## Verificación de firma

Cada webhook incluye una cabecera `X-Matil-Signature`:

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

Verificala para asegurar que la petición viene de 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>
  Verifica siempre las firmas de los webhooks. Sin verificación, cualquiera podria enviar payloads falsos a tu endpoint.
</Warning>

## Reintentos

Si tu endpoint no responde con un código `2xx`, Matil reintenta hasta 3 veces con backoff exponencial.

## Eventos

| Evento                 | Disparador                                       |
| ---------------------- | ------------------------------------------------ |
| `structurer.completed` | Procesamiento asíncrono completado.              |
| `structurer.failed`    | Procesamiento asíncrono fallido.                 |
| `batch.item.completed` | Un elemento del lote termino (modo incremental). |
| `batch.completed`      | El lote completo termino.                        |
| `batch.failed`         | El lote completo falló.                          |
