# Webhooks
> Cómo recibir notificaciones en tiempo real de los eventos de tus documentos, y cómo verificar que vienen de Legaldoc.
Los webhooks son notificaciones HTTP que Legaldoc.io envía a una URL de tu elección cada vez que ocurre un evento sobre un documento o plantilla — sin que tengas que consultar la API periódicamente para saber si algo cambió.
Casos de uso típicos: sincronizar el estado de un documento con tu base de datos, disparar un flujo automatizado cuando se completa una firma, o integrar Legaldoc con tu CRM u otros sistemas de terceros.
## Cómo funcionan
1. Configuras una URL de webhook en Legaldoc.
2. Cuando ocurre un evento, Legaldoc envía un `POST` a esa URL con el tipo de evento y los datos del documento.
3. Tu servidor procesa el evento y responde `200 OK`.
## Eventos disponibles
### Eventos de documento
| Evento | Se dispara cuando... |
|---|---|
| `DOCUMENT_CREATED` | Se crea un nuevo documento. |
| `DOCUMENT_SENT` | El documento se envía a los destinatarios. |
| `DOCUMENT_OPENED` | Un destinatario abre el documento por primera vez. |
| `DOCUMENT_SIGNED` | Un destinatario firma. Se dispara por cada firma individual, no solo al completarse. |
| `DOCUMENT_RECIPIENT_COMPLETED` | Un destinatario completa su acción requerida (firmar, aprobar o visar). |
| `DOCUMENT_COMPLETED` | Todos los destinatarios completaron su acción. |
| `DOCUMENT_REJECTED` | Un destinatario rechaza el documento. |
| `DOCUMENT_CANCELLED` | El dueño del documento lo cancela o elimina. |
| `DOCUMENT_REMINDER_SENT` | Se envía un recordatorio a un destinatario pendiente. |
### Eventos de plantilla
| Evento | Se dispara cuando... |
|---|---|
| `TEMPLATE_CREATED` | Se crea una nueva plantilla. |
| `TEMPLATE_UPDATED` | Se modifica una plantilla (configuración, destinatarios o campos). |
| `TEMPLATE_DELETED` | Se elimina una plantilla. |
| `TEMPLATE_USED` | Se crea un documento a partir de una plantilla — se dispara junto con `DOCUMENT_CREATED`. |
Para el flujo de firma estándar, los eventos que casi siempre te interesan son `DOCUMENT_COMPLETED` y `DOCUMENT_REJECTED` — ver [Guía de Integración](/guides/integration-guide/#5-saber-cuándo-terminó). El resto sirve para trazabilidad más fina, por ejemplo notificar a un usuario interno cuando un destinatario específico firma dentro de un flujo secuencial con varios firmantes.
Puedes suscribirte a todos los eventos o solo a los que necesites.
## Estructura del payload
Toda notificación comparte esta forma:
```json
{
"event": "DOCUMENT_COMPLETED",
"payload": { /* documento o plantilla, con sus destinatarios */ },
"createdAt": "2024-04-22T11:52:18.277Z",
"webhookEndpoint": "https://tu-servidor.com/webhooks/legaldoc"
}
```
| Campo | Descripción |
|---|---|
| `event` | Identificador del tipo de evento — uno de los listados arriba. |
| `payload` | El documento o plantilla afectado, incluyendo su lista de destinatarios y el estado actual de cada uno. |
| `createdAt` | Fecha y hora en que se generó la notificación. |
| `webhookEndpoint` | La URL a la que se está entregando esta notificación. |
Dentro de `payload`, cada destinatario trae su propio estado: `signingStatus` (`NOT_SIGNED`, `SIGNED`, `REJECTED`), `readStatus` (`NOT_OPENED`, `OPENED`) y, si rechazó, `rejectionReason`. El detalle completo de cada recurso está en la [Referencia de la API](/api/).
## Configurar un webhook
Desde la configuración de tu cuenta o equipo, en la sección de Webhooks:
1. Indica la **URL** que va a recibir las notificaciones (debe ser HTTPS).
2. Elige a qué **eventos** te quieres suscribir.
3. Define, opcionalmente, un **secreto** — lo vas a necesitar para verificar la autenticidad de cada notificación (ver más abajo).
Tu endpoint debe cumplir estos requisitos:
| Requisito | Detalle |
|---|---|
| Protocolo | HTTPS |
| Método | Acepta `POST` |
| Content-Type | `application/json` |
| Respuesta | `2xx` dentro de 30 segundos |
| Disponibilidad | Accesible públicamente desde internet |
Para desarrollo local, expón tu servidor con un túnel (por ejemplo [ngrok](https://ngrok.com)) para poder recibir notificaciones reales mientras pruebas.
## Verificar la autenticidad
Si configuraste un secreto, cada notificación incluye el header `X-Legaldoc-Secret` con ese valor:
```http
POST /webhooks/legaldoc HTTP/1.1
Content-Type: application/json
X-Legaldoc-Secret: tu_secreto_configurado
{"event": "DOCUMENT_COMPLETED", "payload": { /* ... */ }}
```
Antes de procesar cualquier notificación, compara ese header contra tu secreto guardado usando una comparación de tiempo constante (no `===` ni `==`), para no filtrar información del secreto a través de variaciones en el tiempo de respuesta:
```javascript
const crypto = require('crypto');
function esValida(secretoRecibido, secretoEsperado) {
if (!secretoEsperado) return true; // sin secreto configurado
if (!secretoRecibido) return false;
try {
return crypto.timingSafeEqual(
Buffer.from(secretoRecibido),
Buffer.from(secretoEsperado),
);
} catch {
return false; // largos distintos
}
}
app.post('/webhooks/legaldoc', (req, res) => {
const secreto = req.headers['x-legaldoc-secret'];
if (!esValida(secreto, process.env.LEGALDOC_WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Firma inválida' });
}
const { event, payload } = req.body;
// procesar el evento...
res.status(200).json({ received: true });
});
```
Si la verificación falla, responde `401` sin detallar el motivo y registra el intento para monitoreo — nunca proceses el payload de una notificación que no verificó.
## Reintentos
Si tu endpoint no responde `2xx` a tiempo, Legaldoc reintenta la entrega con backoff exponencial:
| Intento | Espera |
|---|---|
| 1 | Inmediato |
| 2 | 1 minuto |
| 3 | 5 minutos |
| 4 | 30 minutos |
| 5 | 2 horas |
Después del quinto intento fallido, la notificación queda marcada como fallida y no se reintenta automáticamente. Por eso conviene diseñar tu handler así:
- **Responde rápido**: confirma con `200 OK` de inmediato y procesa el evento de forma asíncrona, en vez de hacer todo el trabajo dentro del mismo request.
- **Procesa de forma idempotente**: una misma notificación puede llegar más de una vez (por reintentos, o por un reenvío manual) — que procesarla dos veces no debe causar efectos duplicados en tu sistema.
## Disponibilidad
Los webhooks están disponibles para usuarios individuales y equipos.