Webhooks
Los webhooks permiten recibir notificaciones automáticas en tu servidor cuando ocurren eventos en Luuk. A diferencia de la API (donde tú consultas los datos), con webhooks Luuk envía los datos a tu URL en tiempo real.
API vs Webhooks
| Característica | API (Pull) | Webhooks (Push) |
|---|---|---|
| Dirección | Tú consultas a Luuk | Luuk envía a tu servidor |
| Tiempo real | No (consultas periódicas) | Sí (inmediato) |
| Uso | Extraer datos masivos, reportes | Notificaciones, automatización |
| Requiere servidor | No | Sí (URL HTTPS accesible) |
| Autenticación | Session Token | Firma HMAC-SHA256 |
Ambos sistemas son complementarios. Usa la API para extraer datos históricos y webhooks para reaccionar a eventos en tiempo real.
Eventos Disponibles
| Evento | Descripción | Cuándo se dispara |
|---|---|---|
formulario.completado | Proceso completado | Un usuario finaliza un proceso |
hilo.creado | Hilo creado | Se inicia un nuevo hilo de trabajo |
checkpoint.respondido | Checkpoint respondido | Se responde un checkpoint del proceso |
seguimiento.vencido | Seguimiento vencido | Un hallazgo supera su plazo |
seguimiento.por_vencer | Seguimiento por vencer | Un hallazgo está próximo a vencer |
posta.transferida | Posta transferida | Se transfiere responsabilidad entre grupos |
Configurar Webhooks
Los webhooks se configuran desde el panel de administración en Webhooks (menú lateral).
Requisitos:
- Perfil Administrador o Intermedio
- URL de destino con HTTPS (obligatorio)
Pasos:
- Ir a la sección Webhooks en el menú lateral
- Click en Nuevo webhook
- Ingresar nombre descriptivo y URL HTTPS de destino
- Seleccionar los eventos que deseas recibir
- Click en Crear
- Guardar el secret que se muestra (solo se muestra una vez)
Verificar Firma (HMAC-SHA256)
Cada envío incluye un header X-Luuk-Signature con la firma HMAC-SHA256 del body. Verifica esta firma para asegurar que el request proviene de Luuk.
Node.js:
const crypto = require('crypto');
function verificarFirma(body, signature, secret) {
const hash = crypto
.createHmac('sha256', secret)
.update(body, 'utf8')
.digest('hex');
return hash === signature;
}
// En tu endpoint:
app.post('/webhook', (req, res) => {
const signature = req.headers['x-luuk-signature'];
const bodyString = JSON.stringify(req.body);
if (!verificarFirma(bodyString, signature, process.env.LUUK_WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Firma inválida' });
}
// Procesar evento...
console.log('Evento:', req.body.evento);
console.log('Datos:', req.body.datos);
res.status(200).json({ ok: true });
});
Python:
import hmac
import hashlib
def verificar_firma(body: str, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode('utf-8'),
body.encode('utf-8'),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
# En tu endpoint (Flask):
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-Luuk-Signature')
body = request.get_data(as_text=True)
if not verificar_firma(body, signature, os.environ['LUUK_WEBHOOK_SECRET']):
return jsonify(error='Firma inválida'), 401
data = request.get_json()
print(f"Evento: {data['evento']}")
return jsonify(ok=True), 200
Estructura del Payload
Cada webhook envía un POST con el siguiente formato:
{
"evento": "formulario.completado",
"timestamp": "2026-03-12T15:30:00.000Z",
"clienteId": "abc123",
"datos": {
"formularioId": "xyz789",
"formularioNombre": "Inspección Diaria",
"hiloId": "hilo_456",
"correlativo": 1234,
"usuario": "Juan Pérez",
"fecha": "2026-03-12T15:30:00.000Z"
}
}
Headers enviados:
| Header | Descripción |
|---|---|
Content-Type | application/json |
X-Luuk-Signature | Firma HMAC-SHA256 del body |
X-Luuk-Event | Nombre del evento |
X-Luuk-Delivery | ID único del envío |
Gestionar Webhooks
Desde el panel puedes:
- Pausar/Activar: Detener temporalmente un webhook sin eliminarlo
- Editar: Cambiar nombre, URL o eventos suscritos
- Test: Enviar un evento de prueba para verificar tu endpoint
- Detalle: Ver historial de envíos con códigos de respuesta
- Eliminar: Eliminar webhook y todo su historial
Mejores Prácticas
- Responder rápido: Tu endpoint debe responder con
200en menos de 10 segundos - Verificar firma: Siempre validar
X-Luuk-Signatureantes de procesar - Idempotencia: Tu endpoint debe manejar envíos duplicados sin problemas
- HTTPS obligatorio: Solo se permiten URLs con certificado SSL válido
- Guardar el secret: Se muestra una sola vez al crear el webhook
Solución de Problemas
El webhook no llega:
- Verificar que el webhook está Activo en el panel
- Verificar que tu URL es accesible desde internet
- Revisar el historial de envíos en Detalle para ver códigos de error
Error 401/403 en tu servidor:
- Verificar que tu endpoint acepta POST sin autenticación adicional
- Revisar firewalls o middleware que puedan bloquear el request
Payload vacío:
- Verificar que tu servidor parsea correctamente
application/json - Revisar los logs de tu servidor web