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

# Webhooks

> Eventos que OlivIA envía a tu backend, sus payloads y la política de entrega

Los **webhooks** permiten que tu backend reciba notificaciones en tiempo real de lo que ocurre durante las llamadas.

<Info>
  Los webhooks **no se registran desde la API externa**: se configuran en la plataforma (o con el equipo de Omniloy) y se asocian a una versión de protocolo. Aquí documentamos los eventos que recibirás y cómo se entregan.
</Info>

## Eventos

| Evento               | Cuándo se emite                             | Filtro              |
| -------------------- | ------------------------------------------- | ------------------- |
| `session.start`      | Al iniciarse la sesión de la llamada        | —                   |
| `session.teardown`   | Al cerrarse la sesión                       | —                   |
| `run.status_changed` | En cada cambio de estado del cuestionario   | `target_statuses[]` |
| `question.answered`  | Al capturarse una respuesta                 | `question_keys[]`   |
| `call.transferred`   | Cuando la llamada se transfiere a un humano | —                   |
| `number.to_verify`   | Cuando se detecta un número equivocado      | —                   |

## Payloads

El payload se construye por evento e incluye el contexto del run y el protocolo. Ejemplos abreviados:

`run.status_changed`:

```json theme={null}
{
  "new_status": "completed",
  "previous_status": "in_progress",
  "run": { "id": "…", "questionnaire_status": "completed", "score": 7, "score_class": "medium" },
  "protocol": { "id": "…", "protocol_key": "seguimiento-epoc", "title": "…" },
  "protocol_version": { "id": "…", "version": 3 },
  "answers": [ { "question_key": "disnea", "answer": "sí" } ],
  "calls": [ { "id": "…", "transcription": [ { "speaker": "patient", "content": "…", "occurred_at": "…" } ] } ]
}
```

`question.answered`:

```json theme={null}
{ "question_key": "disnea", "answer": "sí" }
```

<Note>
  Los payloads no incluyen datos personales del paciente salvo cuando el evento lo requiere explícitamente (p. ej. `number.to_verify`, que lleva `patient_id` y `phone`). Para asociar un run a un paciente, haz join por `run.enrollment_id`.
</Note>

## Autenticación hacia tu endpoint

OlivIA **no firma el cuerpo con HMAC**. En su lugar, cada webhook se autentica **contra tu endpoint** con las credenciales que configures. Opciones:

| Tipo                        | Efecto                                             |
| --------------------------- | -------------------------------------------------- |
| `bearer`                    | `Authorization: Bearer <token>`                    |
| `basic`                     | `Authorization: Basic <base64>`                    |
| `api_key`                   | Cabecera personalizada `<header_name>: <valor>`    |
| `oauth2_client_credentials` | OlivIA obtiene un token del `token_url` y lo envía |

Los secretos se cifran en reposo (AES-256-GCM) y se muestran enmascarados. Protege tu endpoint validando estas credenciales.

## Entrega y reintentos

* Entrega **best-effort**; cada intento se registra.
* Reintentos configurables: `max_retries` (0–10) y `timeout_ms` (100–60000, def. 10000).
* Se reintenta ante errores de red, timeouts y respuestas `5xx`. No se reintenta ante `4xx`. Las redirecciones **no** se siguen.
