Webhooks salientes para integrar tu app a medida
Webhooks salientes: cómo conectar tu aplicación a medida con sistemas de terceros
Imagina que tienes una aplicación que gestiona pedidos y quieres que, cada vez que entra uno nuevo, el CRM de ventas se entere al instante. Una opción es que el CRM pregunte cada pocos minutos: "¿hay pedidos nuevos? ¿y ahora? ¿y ahora?". La otra es que tu aplicación, en el momento exacto en que ocurre el pedido, levante el teléfono y avise. Lo primero es polling. Lo segundo es un webhook saliente. Y casi siempre, lo segundo es lo que quieres.
Llevo años diseñando este tipo de integraciones para empresas que tienen software propio y necesitan que hable con herramientas externas. Voy a contarte cómo funciona un webhook saliente bien hecho, qué problemas vas a encontrarte por el camino y cómo se resuelven sin que el sistema se te caiga el primer día de tráfico real.
Qué es exactamente un webhook saliente
Un webhook saliente es una petición HTTP que tu aplicación envía a un sistema de terceros cuando sucede algo relevante. No esperas a que nadie pregunte: cuando se confirma un pago, se da de alta un cliente o se cierra una incidencia, tu sistema dispara una llamada (normalmente un POST) hacia una URL que el tercero te ha facilitado de antemano.
La diferencia con consultar una API por polling es de fondo, no de forma:
- Con polling, el sistema receptor pregunta cada X segundos por si hay novedades. Gasta recursos preguntando aunque no haya nada, e introduce un retardo (el intervalo entre preguntas) antes de enterarse de los cambios.
- Con un webhook saliente, eres tú quien empuja la información en el instante en que ocurre el evento. Cero llamadas en vacío, latencia mínima.
La analogía que más me gusta es la del timbre frente al portero que sale cada cinco minutos a mirar si hay alguien en la puerta. El timbre (el webhook) avisa cuando hay algo. El portero que patrulla (el polling) gasta zapatos sin necesidad.
Ojo, no es que el polling esté mal siempre. Para sincronizaciones masivas nocturnas o cuando el tercero no soporta recibir webhooks, sigue teniendo sentido. Pero para reaccionar a eventos en tiempo casi real, el webhook gana de calle.
Para qué los vas a usar de verdad
En proyectos reales, los webhooks salientes acaban conectando tu aplicación a medida con piezas muy concretas del negocio:
- Avisar al CRM cuando un usuario se registra o cambia de plan, para que comercial lo tenga al momento.
- Sincronizar con el ERP el alta de una factura o un movimiento de stock, sin esperar al batch de la noche.
- Publicar en Slack o Teams una alerta cuando algo importante pasa: un pedido grande, un error crítico, un SLA a punto de incumplirse.
- Notificar al sistema del propio cliente, cuando tu software actúa como proveedor y otras empresas necesitan reaccionar a tus eventos.
El patrón siempre es el mismo: ocurre un evento dentro de tu dominio y uno o varios destinos quieren enterarse. El webhook es el mensajero.
Cómo diseñar el payload
El cuerpo del webhook es un JSON. Hasta ahí, fácil. Lo que distingue un diseño cuidado de uno que dará dolores de cabeza en seis meses son tres decisiones.
Identifica el tipo de evento. Cada mensaje debe declarar qué es. Un campo event con un valor tipo pedido.creado o factura.pagada permite al receptor enrutar sin adivinar nada del contenido.
Incluye un identificador único del evento. Un id por cada disparo, que no se repita jamás. Lo vas a necesitar para idempotencia, y lo explico más abajo.
Versiona los eventos desde el día uno. Tu payload va a cambiar: añadirás campos, renombrarás otros. Si no versionas, cada cambio rompe a quien te consume. Un campo version o un esquema pedido.creado.v2 te salva de muchas llamadas incómodas.
Un payload razonable se ve así:
{
"id": "evt_9f3a2c10",
"event": "pedido.creado",
"version": "1",
"created_at": "2026-06-09T10:32:00Z",
"data": {
"pedido_id": "PED-4821",
"importe": 149.90,
"moneda": "EUR"
}
}
Fíjate en separar la envoltura (id, event, version, created_at) de la carga útil (data). Esa frontera te permite evolucionar el contenido sin tocar la mecánica del transporte.
Seguridad: que nadie te suplante ni te escuche
Aquí es donde muchas integraciones flojean. Estás enviando datos de negocio por internet a un sistema ajeno, y el receptor tiene que poder fiarse de que el mensaje viene de ti y no de un impostor.
HTTPS, sin excepciones. Nada de http:// plano. El cifrado en tránsito es la base; sin él, todo lo demás sobra.
Firma HMAC con SHA-256. Este es el mecanismo central. Tú y el receptor compartís un secreto que nadie más conoce. Antes de enviar, calculas un HMAC SHA-256 sobre el cuerpo crudo de la petición usando ese secreto, y lo mandas en una cabecera. El receptor repite el cálculo con su copia del secreto: si las firmas coinciden, el mensaje es auténtico y no se ha manipulado por el camino.
Las cabeceras de una petición bien firmada suelen verse así:
POST /webhooks/pedidos HTTP/1.1
Content-Type: application/json
X-Webhook-Id: evt_9f3a2c10
X-Webhook-Signature: sha256=4f8b...c91
X-Webhook-Timestamp: 1749465120
Incluye un timestamp para frenar los ataques de replay. Si alguien captura una petición válida e intenta reenviarla más tarde, el X-Webhook-Timestamp permite al receptor rechazar mensajes demasiado viejos (por ejemplo, con más de cinco minutos). Para que esto funcione de verdad, el timestamp debe entrar dentro del cálculo de la firma; si no, el atacante lo cambiaría a su antojo.
Allowlist de IPs cuando puedas. Si tus webhooks salen siempre desde un rango de direcciones conocido, comunícaselo al receptor para que solo acepte peticiones desde ahí. Es una capa extra, no un sustituto de la firma, pero suma.
La regla mental que repito a los equipos: el secreto demuestra quién envía, el timestamp demuestra cuándo, y el HTTPS protege el camino. Las tres cosas, juntas.
Fiabilidad: porque la red falla
Internet no garantiza nada. El receptor estará caído justo cuando dispares el evento más importante del mes. Asúmelo desde el diseño.
Reintentos con backoff exponencial
Si la primera entrega falla, no te rindas ni machaques al receptor cada segundo. Reintenta espaciando los intentos: a los 5 segundos, luego al minuto, luego a los 10 minutos, después a la hora. Ese espaciado creciente es el backoff exponencial, y le da al sistema receptor margen para recuperarse sin que tú lo satures.
Idempotencia con el id de evento
Aquí entra en juego ese id único del que hablábamos. Como vas a reintentar, es posible que el receptor reciba el mismo evento dos veces (por ejemplo, si respondió tarde y tú ya lo habías dado por fallido). La solución es que el receptor guarde los id ya procesados y descarte los repetidos. Así, aunque el mensaje llegue tres veces, el efecto en su sistema ocurre una sola vez. A eso se le llama operación idempotente.
Cola de entrega y dead-letter queue
Disparar el webhook de forma síncrona, dentro de la misma transacción que generó el evento, es una mala idea: si el tercero tarda, tu aplicación se queda esperando. Lo correcto es encolar el evento y que un proceso aparte se encargue de entregarlo y reintentarlo.
Cuando un evento agota todos sus reintentos y sigue sin entregarse, no lo tires a la basura. Mándalo a una dead-letter queue: una cola apartada donde quedan los mensajes que han fracasado, listos para inspección manual o para un reintento posterior cuando el problema esté resuelto.
"At least once" frente a entrega garantizada
Conviene ser honesto sobre las garantías. La entrega exactamente una vez (exactly once) es, en la práctica, casi imposible en sistemas distribuidos. Lo realista y lo que casi todo el mundo implementa es at least once: el evento llegará al menos una vez, posiblemente más. Por eso la idempotencia no es opcional, es la pieza que hace que "al menos una vez" se comporte, de cara al receptor, como "exactamente una vez".
Observabilidad: ver lo que pasa
Un webhook que se envía y se olvida es una caja negra. El día que el cliente diga "no me ha llegado la notificación del pedido", necesitarás respuestas.
Registra cada intento de entrega con su resultado: a qué URL, con qué id de evento, qué código de respuesta devolvió, cuánto tardó y en qué intento va. Con esos logs puedes reconstruir qué ocurrió con cualquier evento.
Y, si el proyecto lo justifica, monta un panel para el cliente donde pueda:
- Ver el historial de webhooks enviados y su estado (entregado, reintentando, fallido).
- Consultar el detalle de los fallos: código de error, respuesta del receptor.
- Reenviar manualmente un evento que falló, sin tener que abrir un ticket.
Ese panel convierte una fuente constante de soporte en algo que el propio cliente resuelve solo. La inversión se paga sola en tickets que no llegan.
Si tú eres quien consume el webhook
A veces el papel se invierte y es tu aplicación la que recibe webhooks de un tercero. Dos consejos que valen oro:
- Responde 2xx rápido. El emisor interpreta tu respuesta como "recibido". Si tardas en contestar porque te pones a procesar pesadamente, lo más probable es que el emisor crea que has fallado y reintente, duplicando el trabajo. Acepta, responde
200, y procesa después. - Procesa de forma asíncrona. Encola el evento recibido y trátalo fuera del ciclo de la petición HTTP. El receptor debe limitarse a validar la firma, comprobar idempotencia y soltar un 2xx. El trabajo de verdad va por detrás.
Es el mismo principio que aplicas como emisor, visto desde el otro lado del cable: nadie debe quedarse esperando a nadie.
Por dónde empezar tu integración
Antes de escribir una línea de código, cierra estas decisiones: qué eventos vas a emitir y cómo se llaman, qué forma tendrá el payload y cómo lo versionarás, qué mecanismo de firma usarás y cómo distribuirás el secreto. Con eso claro, lo demás es ingeniería ordenada: cola de entrega, reintentos con backoff, idempotencia en el receptor, dead-letter queue para los irrecuperables y logs que te dejen ver qué pasa.
Empieza pequeño con un solo tipo de evento y un solo destino, y comprueba el flujo completo de punta a punta antes de abrir el grifo a más integraciones. Un webhook bien diseñado desde el principio se mantiene callado durante años; uno improvisado se convierte en deuda técnica el primer pico de tráfico.
Si tienes una aplicación a medida y quieres conectarla con el CRM, el ERP o los sistemas de tus clientes sin que la fiabilidad sea un problema, hablemos de tu integración.