atrusDocs
Guía de integración›Recibir avisos›Webhooks

Webhooks

Un webhook es un destino tuyo, una URL https, al que Datrus manda un aviso cuando pasa algo con el consentimiento de una persona o con una solicitud de derechos. Los eventos son los doce del catálogo: seis de consentimiento y seis de derechos (recibida, acusada, prorrogada, bloqueo ordenado, por vencer y resuelta). El resto de los módulos se consulta por la API y la bitácora.

Crear un destino

curl -X POST https://www.datrus.cl/api/v1/webhooks \
  -H "Authorization: Bearer dtr_live_…" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: …" \
  -d '{ "name": "CRM", "url": "https://crm.miempresa.cl/datrus", "events": ["consentimiento.otorgado", "consentimiento.revocado"] }'

La respuesta trae el secret una sola vez. Con él verificarás cada entrega. Si lo pierdes, POST /webhooks/{id}/rotate-secret entrega uno nuevo y las entregas pendientes se firman con él.

Qué recibe tu servidor

POST /datrus HTTP/1.1
Content-Type: application/json
X-Datrus-Firma: t=1757894400,v1=5f0c…e2a1

{
  "id": "…",
  "evento": "consentimiento.otorgado",
  "emitidoEn": "2026-09-14T12:00:00.000Z",
  "tenantId": "…",
  "datos": {
    "acuerdoId": "…", "acuerdoVersionId": "…", "evidenciaId": "…",
    "version": 3, "origen": "formulario", "hashVersion": "…",
    "creados": 2, "removidos": 0, "extendidos": 0, "acortados": 0, "fuentesRetiradas": 0,
    "terceros": []
  }
}

Y cuando entra una solicitud de derechos

Los seis eventos de derechos comparten destino, firma, reintentos y bitácora de entregas; lo que cambia es datos: el código de la solicitud, el canal por el que entró, los derechos pedidos, el estado y las fechas del plazo del art. 11. solicitud.por_vencer sale a los 5 días, a los 2 y el día del vencimiento, con diasRestantes. Es lo que deja orquestar el reloj desde tu mesa de ayuda sin consultar la API.

{
  "id": "…",
  "evento": "solicitud.recibida",
  "emitidoEn": "2026-10-08T14:02:11.000Z",
  "tenantId": "…",
  "datos": {
    "solicitudId": "…", "codigo": "SD-4K7M",
    "canal": "correo_admision",
    "derechos": ["acceso", "supresion"],
    "estado": "esperando_verificacion",
    "recibidaEl": "2026-10-08", "acuseEl": null,
    "venceEl": "2026-11-07", "prorrogaEl": null,
    "diasRestantes": null,
    "version": 1
  }
}
El aviso no trae datos de la persona. Trae acuerdoId, el mismo id que ves en la consola y en las exportaciones. Correlacionarlo con tu cliente es trabajo del receptor, con el dato que tú ya tienes y nosotros no. Así un webhook interceptado no expone a nadie.

Verificar la firma

La cabecera X-Datrus-Firma trae la marca de tiempo en segundos (t) y la firma (v1): un HMAC-SHA256 del secreto sobre la cadena t + "." + cuerpo, con el cuerpo tal cual llegó, sin reformatear. Rechaza lo que tenga más de 300 segundos de diferencia con tu reloj.

import { createHmac, timingSafeEqual } from 'node:crypto'

export function verificar(cuerpoCrudo, cabecera, secreto) {
  const partes = Object.fromEntries(cabecera.split(',').map((p) => p.split('=')))
  const t = Number(partes.t)
  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 300) return false
  const esperada = createHmac('sha256', secreto).update(`${t}.${cuerpoCrudo}`).digest('hex')
  const recibida = String(partes.v1 ?? '')
  return recibida.length === esperada.length && timingSafeEqual(Buffer.from(recibida), Buffer.from(esperada))
}

Responde 2xx rápido y procesa después. Cualquier otra respuesta, o no responder, cuenta como fallo.

Reintentos

Una entrega que falla se reintenta hasta 8 veces, esperando 60, 300, 900, 3600, 21600, 43200, 86400 segundos entre intentos. Cada intento se registra: GET /webhooks/{id}/deliveries muestra el estado, el código recibido y el próximo intento. Cuando se agotan, la entrega queda marcada y no se vuelve a mandar sola.

Las entregas salen en el momento en que ocurre el evento. Si necesitas forzar el despacho de lo pendiente, POST /webhooks/dispatch lo hace y te dice cuántas intentó, entregó y falló.

Reenviar un aviso

Si tu receptor perdió un aviso (un despliegue a mitad de una entrega, una cola que se vació del otro lado), pídelo de nuevo: POST /webhooks/{id}/deliveries/{deliveryId}/resend encola una entrega nueva con el mismo cuerpo, incluido el id del aviso, y la manda en el acto firmada con el secreto vigente. La entrega original no se toca: su historia de intentos es evidencia de lo que pasó. Un receptor que deduplica por id lo reconoce como el mismo evento.

Pausar y editar

PATCH /webhooks/{id} cambia nombre, URL o eventos, y pausa o reanuda el destino. Un destino pausado no encola entregas nuevas.