Introducción
Si alguna vez has configurado una integración entre dos servicios —por ejemplo, para que los datos de un sistema lleguen automáticamente a un CRM o a una hoja de Google Sheets—, seguramente te has topado con el término "webhook". Es una de esas tecnologías que sostienen silenciosamente gran parte de la automatización moderna, desde las notificaciones en Slack hasta la sincronización de pedidos en una tienda online. En este artículo explicaremos qué son los webhooks en términos sencillos, en qué se diferencian de las solicitudes habituales a una API, y cómo configurar en la práctica notificaciones de clics para enlaces cortos usando los webhooks de Lix.li.
Qué es un webhook, en términos simples
Un webhook es una forma de transmitir datos automáticamente de un servicio a otro en el momento en que ocurre un evento determinado. En lugar de que tu sistema pregunte constantemente "¿ha aparecido algo nuevo?", el servicio envía los datos a tu servidor por sí mismo, justo cuando ocurre el evento. La forma más sencilla de entender la diferencia es con una analogía del correo postal:
- Una solicitud habitual a una API es como ir tú mismo al buzón una y otra vez para comprobar si ha llegado una carta.
- Un webhook es como suscribirte a un servicio de entrega: la carta llega sola a tu puerta en cuanto está lista.
Técnicamente, un webhook es simplemente una solicitud HTTP normal (generalmente
POST) que un servidor envía a una URL previamente configurada en otro servidor cuando ocurre el evento correspondiente: el pago de un pedido, un cambio de estado en una tarea o, en el caso de Lix.li, un clic en un enlace corto.
Para qué sirven los webhooks
Los webhooks resuelven un problema muy concreto: cómo obtener datos actualizados sin tener que consultar constantemente ("polling") un servicio externo. Sin webhooks, para enterarte de nuevos eventos tendrías que enviar solicitudes periódicas a una API —cada minuto, cada cinco minutos— y comprobar cada vez si hay algo nuevo. Esto genera una carga innecesaria en ambos servidores y siempre añade un retraso entre el momento en que ocurre el evento y el momento en que te enteras de él. Los webhooks invierten esa lógica: el servicio te avisa cuando algo ocurre. Esto es especialmente útil para:
- Automatizar procesos de negocio — por ejemplo, registrar automáticamente nuevos leads en un CRM.
- Integraciones con analítica — enviar datos de clics a tu propio sistema de seguimiento.
- Bots y notificaciones — enviar eventos a un bot de Telegram o a un canal de Slack del equipo.
- Sincronización de datos — actualizar hojas de Google Sheets, paneles de control o sistemas internos en tiempo real.
Cómo funcionan los webhooks: el ejemplo de Lix.li
En Lix.li, los webhooks te permiten recibir información sobre los clics en tus enlaces cortos directamente en tu propio servidor, de forma automática, sin necesidad de consultar constantemente la API del servicio. Esto es útil si quieres enviar estos eventos a tu CRM, a un sistema de analítica, a Google Sheets, a un bot de Telegram o a cualquier otro sistema de automatización.
Cómo está construido
- Los clics no se envían de uno en uno: se acumulan y se entregan en lotes, una vez cada pocos minutos. Esto reduce la carga tanto en tu servidor como en el de Lix.li.
- La entrega ocurre casi en tiempo real, pero no de forma instantánea; los webhooks están diseñados para escenarios donde un retraso de unos minutos es aceptable, no para una reacción instantánea a cada clic individual.
- La entrega está garantizada bajo el principio de "al menos una vez": si ocurre un fallo de red durante el envío, un lote puede llegar duplicado. Por eso cada evento tiene un
event_idúnico, que debes usar para filtrar duplicados en tu propio sistema.
Configurar un webhook en el panel de control
La función de webhooks está disponible en el plan Premium. La configuración lleva solo unos pasos:
- Abre la sección "Webhooks" en tu panel de control y haz clic en "Añadir."
- Indica:
- la URL receptora — la dirección de tu servidor que aceptará las solicitudes entrantes (por ejemplo,
https://api.tusitio.com/webhooks/lix); - el alcance — si enviar eventos de todos los enlaces, de un grupo específico de enlaces, o solo de un enlace;
- si incluir o no la dirección IP del visitante en los datos del evento (desactivado por defecto, ya que se trata de datos personales).
- la URL receptora — la dirección de tu servidor que aceptará las solicitudes entrantes (por ejemplo,
- Justo después de crear el webhook, se te mostrará una clave secreta, que se muestra solo una vez; asegúrate de guardarla, ya que se usa para verificar la autenticidad de las solicitudes entrantes.
- Haz clic en "Probar" — el servicio enviará un evento de prueba y mostrará si tu servidor respondió correctamente.

Qué llega a tu servidor
Cada solicitud se envía con el método POST y un cuerpo en formato application/json. Además de los datos en sí, la solicitud incluye algunas cabeceras de servicio:
| Cabecera | Propósito |
|---|---|
X-Lix-Signature |
La firma del cuerpo de la solicitud, en formato sha256=, usada para verificar la autenticidad. |
X-Lix-Timestamp |
El momento del envío de la solicitud, como marca de tiempo Unix. |
X-Lix-Delivery |
Un identificador único de la entrega. |
User-Agent |
Con el valor Lix-Webhooks/1.0. |
| El cuerpo de la solicitud contiene el propio lote de eventos: |
{
"delivery_id": "0f3b9c2e-6a1d-4e88-9d5a-2f8c1b7a4e10",
"event_type": "redirects.batch",
"sent_at": "2026-06-01T12:05:00Z",
"window": {
"from": "2026-06-01T12:00:00Z",
"to": "2026-06-01T12:03:30Z"
},
"count": 2,
"truncated": false,
"events": [
{
"event_id": "2ef7bde608ce5404e97d5f042f95f89f1c232871",
"link_id": 12345,
"datetime": "2026-06-01T12:01:00Z",
"country": "US",
"city": "Boston",
"browser": "Chrome",
"os": "Windows",
"device": "Desktop",
"ref_domain": "google.com",
"group_id": null,
"is_bot": false
}
]
}
Cada evento dentro del lote incluye el ID del enlace, la hora del clic en UTC, el país, la ciudad, el navegador, el sistema operativo, el tipo de dispositivo, el dominio desde el que llegó el clic, el ID del grupo (si está definido) y un indicador de si se trató de un bot. La dirección IP del visitante solo se incluye si activaste explícitamente esa opción al configurar el webhook.
Si se ha acumulado un número muy elevado de eventos, un lote puede marcarse con truncated: true: esto significa que parte de los datos llegará en la siguiente entrega, y no se pierde nada.
Cómo verificar la autenticidad de una solicitud
Dado que la URL de tu servidor puede recibir técnicamente una solicitud desde cualquier lugar, es importante confirmar que una solicitud realmente proviene de Lix.li y no está falsificada. Para eso está la firma en la cabecera X-Lix-Signature.
El principio de verificación es el siguiente: tomas el cuerpo "en bruto" (sin procesar) de la solicitud, calculas un hash HMAC-SHA256 usando tu clave secreta, y comparas el resultado con lo que llegó en la cabecera. La comparación debe hacerse de forma segura (tiempo constante) para evitar ataques de temporización.
Ejemplo en PHP:
$raw = file_get_contents('php://input');
$secret = 'tu_secret';
$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_LIX_SIGNATURE'] ?? '')) {
http_response_code(401);
exit;
}
Ejemplo en Node.js (Express):
const crypto = require('crypto');
// es importante obtener el cuerpo EN BRUTO: app.use(express.raw({ type: 'application/json' }))
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(req.body).digest('hex');
const got = req.header('X-Lix-Signature') || '';
if (expected.length !== got.length ||
!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got))) {
return res.sendStatus(401);
}
Ejemplo en Python (Flask):
import hmac, hashlib
raw = request.get_data() # bytes en bruto
expected = 'sha256=' + hmac.new(secret.encode(), raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers.get('X-Lix-Signature', '')):
return '', 401
Requisitos para tu servidor receptor
Para que los webhooks funcionen de forma estable, tu servidor debe cumplir con algunas reglas:
- Responder con un código
2xx. Cualquier otro código, o un tiempo de espera agotado, se considera un fallo, y la entrega se reintentará. - Responder rápido. Solo dispones de unos segundos para responder; no proceses los datos de forma síncrona dentro del propio manejador de la solicitud. El enfoque correcto es guardar rápidamente los datos recibidos (por ejemplo, en una cola o una base de datos), devolver
2xx, y procesarlos por separado después. - Deduplicar por
event_id. Debido al mecanismo de reintento, el mismo evento puede llegar dos veces en ocasiones. - Ser idempotente. Volver a procesar el mismo lote no debe corromper tus datos.
- Verificar siempre la firma en cada solicitud entrante.
- Usar HTTPS. No se admiten direcciones locales ni internas para recibir webhooks.
Qué ocurre en caso de fallos
Si tu servidor no responde con un código 2xx, Lix.li reintenta la entrega con una pausa cada vez mayor entre intentos. Si el receptor no responde en absoluto durante un periodo prolongado (muchos intentos fallidos seguidos), el webhook se pausa automáticamente para evitar enviar datos al vacío. Esto se muestra en el registro de entregas de tu panel de control, y una vez que hayas solucionado el problema en tu extremo, puedes volver a activar el webhook.
Gestión de webhooks en el panel de control
Para cada webhook configurado, están disponibles las siguientes acciones:
- Probar — enviar un único evento de prueba y ver de inmediato el resultado: éxito, o el código de respuesta específico de tu servidor.
- Pausar / Reanudar — detener o reanudar temporalmente la entrega de eventos.
- Rotar la clave secreta — generar una nueva clave para reemplazar la anterior; la clave antigua deja de funcionar al instante, así que asegúrate de actualizarla también en tu extremo cuanto antes.
- Eliminar — quitar el webhook por completo.
- Registro de entregas — un historial de las entregas recientes, con estado, código de respuesta HTTP, número de eventos en el lote y hora de envío.
Preguntas frecuentes
¿Con qué rapidez llegan los eventos?
En lotes, aproximadamente cada pocos minutos, con un pequeño retraso de procesamiento. No es una entrega push instantánea, sino un escenario casi en tiempo real.
¿Puede llegar el mismo evento dos veces?
Sí, si se reintenta una entrega tras un fallo de red. Por eso es importante deduplicar los eventos por el campo event_id en tu extremo.
¿Se garantiza un orden estricto de los eventos?
Dentro de un mismo lote, los eventos siguen un orden cronológico, pero no hay una garantía estricta de orden entre distintos lotes; usa el campo datetime de cada evento para ordenarlos.
¿Qué ocurre con volúmenes de tráfico muy elevados?
Si se acumulan demasiados eventos en un mismo intervalo, el lote se marca con truncated: true, y el resto de los datos llega en la siguiente entrega; no se pierde ningún dato en el proceso.
¿Es obligatorio usar HTTPS?
Sí, la dirección del receptor debe comenzar con https://. No se aceptan direcciones locales ni internas.
¿Puedo recibir eventos solo de un enlace o de un grupo de enlaces?
Sí, al crear un webhook puedes elegir el alcance "Un enlace" o "Grupo" en lugar de todos los enlaces de la cuenta.
Ejemplo completo de un manejador en PHP
A continuación, un ejemplo mínimo pero funcional de un manejador que verifica la firma, responde rápidamente y procesa los eventos con protección contra duplicados: