Webhooks explicados: cargas firmadas y estrategias de reintento

Backend2026-10-19TryQuickToolBox

Acabas de integrar un servicio de terceros que envía webhooks y todo funciona bien en las pruebas. Pero en producción, notas ocasionalmente eventos perdidos, entregas duplicadas o, peor aún, un actor malicioso enviando cargas falsas a tu endpoint. Los webhooks son simples en concepto pero complicados en la práctica. Este artículo explica cómo asegurar webhooks con cargas firmadas e implementar estrategias de reintento robustas para que puedas confiar en tus integraciones basadas en eventos.

¿Qué son los webhooks y por qué importan?

Los webhooks son callbacks HTTP definidos por el usuario que se activan por eventos específicos. Cuando ocurre un evento, como un pago exitoso o un nuevo registro de usuario, el servicio de origen envía una solicitud HTTP POST a una URL que proporcionas. Este modelo basado en push es más eficiente que el polling, reduciendo la latencia y la carga del servidor. Sin embargo, introduce desafíos: verificar la autenticidad y manejar fallos de entrega.

Asegurando webhooks con cargas firmadas

Sin verificación, cualquiera puede enviar solicitudes a tu endpoint de webhook. Las cargas firmadas resuelven esto al incluir una firma criptográfica que prueba que la solicitud se originó desde el remitente confiable.

Cómo funcionan las firmas HMAC

La mayoría de los proveedores usan HMAC (Hash-based Message Authentication Code) con un secreto compartido. El remitente calcula un hash de la carga usando el secreto y lo incluye en un encabezado (por ejemplo, X-Signature). Tu servidor recalcula el hash y lo compara. Si coinciden, la solicitud es auténtica.

// Ejemplo: Verificando una firma de webhook en Node.js
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(payload);
  const digest = hmac.digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}

Importante: Siempre usa una comparación de tiempo seguro para prevenir ataques de temporización. Además, verifica la firma contra el cuerpo de la solicitud sin procesar, no contra un objeto JSON parseado, porque el parseo puede alterar la carga.

Mejores prácticas para la verificación de firmas

Implementando reintentos confiables

Incluso con cargas firmadas, problemas de red o interrupciones temporales pueden causar que la entrega del webhook falle. Una estrategia de reintento robusta asegura que los eventos se entreguen eventualmente sin abrumar tu sistema.

Backoff exponencial con jitter

Reintentar inmediatamente puede empeorar la congestión. En su lugar, usa backoff exponencial: espera más tiempo entre cada reintento. Agrega jitter (variación aleatoria) para evitar problemas de estampida cuando muchos webhooks fallan simultáneamente.

// Ejemplo: Programa de reintentos con backoff exponencial y jitter
function getRetryDelay(attempt) {
  const base = 1000; // 1 segundo
  const max = 30000; // 30 segundos
  const delay = Math.min(base * Math.pow(2, attempt), max);
  return delay + Math.random() * 1000; // agrega hasta 1s de jitter
}

Idempotencia: manejando duplicados

Los reintentos pueden causar entregas duplicadas. Tu manejador de webhooks debe ser idempotente: procesar el mismo evento varias veces debe tener el mismo efecto que procesarlo una vez. Usa el ID del evento de la carga para rastrear eventos procesados.

Responde rápido y confirma

Tu endpoint de webhook debe responder con un código de estado 2xx lo más rápido posible, idealmente en unos pocos segundos. Si el procesamiento tarda más, encola el evento para manejo asíncrono y devuelve 202 Accepted. Esto previene timeouts y reintentos innecesarios.

Comparación: Webhook vs. Polling

Aspecto Webhooks Polling
Latencia Casi en tiempo real Depende del intervalo
Carga del servidor Baja (solo push) Alta (solicitudes constantes)
Complejidad Mayor (necesita reintentos, seguridad) Menor
Confiabilidad Requiere lógica de reintento Inherentemente confiable

Paso a paso: Construyendo un receptor de webhooks seguro

  1. Configura un endpoint HTTPS con un certificado válido.
  2. Extrae el encabezado de firma (por ejemplo, X-Signature) y la marca de tiempo.
  3. Verifica la firma usando el secreto compartido y el cuerpo sin procesar.
  4. Comprueba la marca de tiempo para rechazar solicitudes antiguas (por ejemplo, con más de 5 minutos).
  5. Parsea la carga y verifica si hay IDs de eventos duplicados.
  6. Procesa el evento de forma asíncrona si es necesario, y responde con 200 OK.
  7. Registra el evento para auditoría y depuración.

Preguntas frecuentes

¿Qué es una carga de webhook firmada?

Una carga firmada incluye una firma criptográfica (generalmente HMAC) que permite al receptor verificar que la solicitud provino de una fuente confiable y no fue manipulada.

¿Cuántas veces debo reintentar un webhook fallido?

La mayoría de los sistemas reintentan de 3 a 5 veces con backoff exponencial. Después de eso, el evento generalmente se marca como fallido y puede requerir intervención manual o manejo de cola de mensajes muertos.

¿Puedo usar webhooks sin HTTPS?

Está fuertemente desaconsejado. Sin HTTPS, las cargas y firmas pueden ser interceptadas o modificadas. Siempre usa TLS para endpoints de webhooks.

Al depurar cargas o registros de webhooks, formatear correctamente el JSON es esencial. Usa nuestro JSON Formatter para imprimir y validar cargas JSON rápidamente.