Webhooks de DeCAya
Un webhook avisa a tu servidor en cuanto cambia el estado de un DeCA, sin que tengas que consultar la API en bucle. Da igual quién haya hecho el cambio: los eventos se emiten tanto si el documento se creó por API como si lo creó una persona en el panel.
Eventos
| Evento | Cuándo se emite |
|---|---|
document.generated | Se ha emitido un DeCA y su PDF ya está disponible. |
document.modified | Se ha creado una versión nueva: hay un PDF, una URL y un QR nuevos. |
document.completed | El servicio de transporte se ha marcado como finalizado. |
document.cancelled | El DeCA se ha anulado. |
Formato del evento
El payload es deliberadamente breve: identificadores, estado y tus propias referencias. Los datos del artículo 6 son contenido regulado y no viajan en el webhook; se leen con GET /api/v1/documents/{id} cuando los necesites.
{
"id": "evt_5f2c9a1b4e7d4c0f8a3b6d9e2c1f4a70",
"type": "document.generated",
"version": "2026-08-20",
"environment": "production",
"createdAt": "2026-10-05T07:12:44.201Z",
"data": {
"documentId": "0f2c…",
"documentNumber": "DEC-2026-000184",
"versionNumber": 1,
"status": "generated",
"externalId": "SO-4821",
"externalSource": "sap"
}
}El campo version versiona el sobre, no la URL: un mismo endpoint sigue recibiendo eventos cuando el formato evolucione.
Verificar la firma
Cada envío lleva la cabecera DeCAya-Signature con la marca de tiempo y un HMAC-SHA256 del texto <timestamp>.<cuerpo>, calculado con el secreto del endpoint:
DeCAya-Signature: t=1791184364,v1=3f7c…Verifica siempre antes de procesar. Calcula el HMAC sobre el cuerpo en crudo, no sobre el JSON reserializado, y rechaza marcas de tiempo con más de 5 minutos de antigüedad: el timestamp va dentro de la firma precisamente para que un envío capturado no pueda reproducirse indefinidamente.
import crypto from "node:crypto";
export function verify(rawBody, header, secret) {
const parts = Object.fromEntries(
header.split(",").map((part) => part.trim().split("=")),
);
const timestamp = Number(parts.t);
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(parts.v1),
);
}Rotar el secreto
Al rotar, el secreto anterior sigue siendo válido durante 24 horas, así que puedes desplegar el nuevo valor sin perder los eventos que ya estaban en camino. Durante ese periodo acepta la firma si coincide con cualquiera de los dos.
Responder
Responde 2xx en cuanto hayas guardado el evento, y haz el trabajo pesado después. Cortamos la petición a los 10 segundos, y una respuesta lenta cuenta como fallida.
El mismo evento puede llegar más de una vez. Usa id como clave de deduplicación: es el mismo valor en todos los reintentos y en todos tus endpoints.
Reintentos
Un envío fallido se reintenta hasta 6 veces con espera creciente (10 s, 1 min, 5 min, 30 min, 2 h, 6 h). Después queda marcado como agotado y puedes reenviarlo a mano desde el panel o con POST /api/v1/webhook-deliveries/{id}/replay. Un endpoint que falla de forma continuada se desactiva solo; volver a activarlo reinicia el contador.
Endpoints de gestión
Todo lo siguiente requiere el permiso webhooks:manage. El endpoint pertenece al entorno de la clave que lo crea, de modo que una clave de pruebas nunca puede tocar el endpoint de producción.
GET /api/v1/webhook-endpointsPOST /api/v1/webhook-endpointsconurl(https obligatorio) yenabledEventsPATCH /api/v1/webhook-endpoints/{id}para cambiar la suscripción o desactivarloDELETE /api/v1/webhook-endpoints/{id}POST /api/v1/webhook-endpoints/{id}/rotate-secretGET /api/v1/webhook-deliveriespara el historial de envíos
Crear el primero
curl -X POST https://decaya.es/api/v1/webhook-endpoints \
-H "Authorization: Bearer $DECAYA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://erp.example.com/hooks/decaya",
"enabledEvents": ["document.generated", "document.modified"]
}'La respuesta incluye el secret con el que verificar las firmas. También puedes hacerlo sin escribir código desde Ajustes → Webhooks.
DeCAya llega muy pronto: tu DeCA listo en segundos
Conocer DeCAya →