Webhooks: cargas firmadas y reintentos

Backend2026-11-01TryQuickToolBox

Acabas de integrar un servicio de terceros que envía webhooks a tu endpoint. Todo funciona en las pruebas, pero en producción notas eventos perdidos, entregas duplicadas y ocasionales preocupaciones de seguridad. Los webhooks son simples en concepto pero complicados en la práctica, especialmente cuando se trata de verificar la autenticidad y manejar fallos.

Esta guía explica cómo proteger los webhooks con cargas firmadas e implementar mecanismos de reintento robustos, para que puedas construir integraciones confiables.

¿Qué son los webhooks?

Los webhooks son callbacks HTTP definidos por el usuario. Cuando ocurre un evento en un sistema de origen (por ejemplo, se completa un pago), se envía una solicitud HTTP POST a una URL que especifiques, conteniendo datos sobre el evento. Esto permite comunicación en tiempo real entre servicios sin polling.

Pero los webhooks introducen desafíos: ¿cómo sabes que la solicitud provino genuinamente del remitente esperado? ¿Qué pasa si tu endpoint está temporalmente caído? Ahí es donde entran las cargas firmadas y los reintentos.

Proteger webhooks con cargas firmadas

Una carga firmada usa una firma criptográfica para demostrar que la solicitud se originó en el remitente y no fue manipulada. El enfoque común es HMAC (Hash-based Message Authentication Code) con un secreto compartido.

Cómo funcionan las firmas HMAC

El remitente calcula un HMAC sobre el cuerpo de la solicitud (y a veces encabezados como la marca de tiempo) usando una clave secreta. La firma se envía en un encabezado (por ejemplo, X-Signature). Tu servidor recalcula el HMAC y lo compara con la firma recibida. Si coinciden, la solicitud es auténtica.

Aquí tienes un ejemplo mínimo en Python usando Flask:

import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = b'your_shared_secret'

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Signature')
    if not signature:
        abort(400, 'Missing signature')
    body = request.get_data()
    expected = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, signature):
        abort(401, 'Invalid signature')
    # Process the event
    return '', 200

Puntos clave:

Medidas de seguridad adicionales

Implementar reintentos confiables

Los consumidores de webhooks pueden fallar: tu servidor podría estar caído o el procesamiento podría agotar el tiempo de espera. Los remitentes deberían reintentar las entregas fallidas con retroceso exponencial. Como consumidor, debes manejar los reintentos con elegancia.

Del lado del remitente (si estás construyendo un sistema de webhooks)

  1. Devuelve un 2xx rápidamente: Confirma la recepción antes de procesar para evitar tiempos de espera. Usa una cola para trabajo asíncrono.
  2. Reintenta en caso de fallo: Si no se recibe un 2xx dentro de un tiempo de espera (por ejemplo, 5 segundos), reintenta con demoras crecientes (por ejemplo, 1s, 5s, 30s, 5m, 30m).
  3. Limita los reintentos: Tras un número máximo de intentos (por ejemplo, 5), marca la entrega como fallida y alerta.
  4. Incluye un ID de evento único: Para que los consumidores puedan deduplicar.

Del lado del consumidor (tu endpoint)

Comparación: cargas firmadas vs. autenticación básica

Enfoque Seguridad Complejidad Protección contra repetición
Firma HMAC Alta (integridad + autenticidad) Moderada Sí (con marca de tiempo)
Autenticación básica Baja (credenciales en el encabezado) Baja No
Lista de IPs permitidas Media (a nivel de red) Baja No

Probar webhooks localmente

Durante el desarrollo, necesitas una URL pública para recibir webhooks. Herramientas como ngrok o localtunnel pueden exponer tu servidor local. Prueba siempre la verificación de firmas y el comportamiento de reintentos con fallos simulados.

Al inspeccionar cargas de webhooks, puede que necesites formatear el JSON para facilitar la lectura. El Formateador JSON puede ayudarte a imprimir con formato y validar el cuerpo JSON.

Preguntas frecuentes

¿Qué es una carga de webhook firmada?

Una carga firmada incluye una firma criptográfica (a menudo HMAC) que permite al receptor verificar la autenticidad e integridad de la solicitud.

¿Cuántas veces debería reintentarse un webhook?

No hay un número fijo; las prácticas comunes van de 3 a 10 reintentos con retroceso exponencial. La clave es equilibrar la confiabilidad con el uso de recursos y alertar sobre fallos persistentes.

¿Puedo usar webhooks sin firmas?

No es recomendable. Sin firmas, no puedes verificar al remitente, lo que hace que tu endpoint sea vulnerable a suplantación. Usa siempre firmas en producción.

¿Listo para depurar tus cargas de webhooks? Prueba nuestro Formateador JSON para validar y formatear datos JSON rápidamente.