Ir al contenido

Webhooks e integraciones

Qué hacer si un endpoint webhook no responde

Diagnostica timeouts, errores HTTP y caídas de un endpoint webhook con un método reproducible, observabilidad y respuestas rápidas.

Por Equipo AltokePayPublicado Actualizado 9 min de lectura

Un webhook parece simple: un sistema envía una solicitud HTTP y otro la recibe. Sin embargo, cuando el endpoint deja de responder, el síntoma visible —un timeout, un 502 o varios reintentos— no siempre indica dónde está la falla. El problema puede aparecer antes de llegar a la aplicación, durante la validación, al consultar una dependencia o después de haber ejecutado la acción de negocio.

La investigación debe separar transporte, recepción y procesamiento. También debe comenzar por el contrato del proveedor: cada proveedor define la URL admitida, método HTTP, encabezados, autenticación, formato del cuerpo, tiempo máximo de respuesta, códigos considerados exitosos y política de reintentos. No conviene trasladar las reglas de una integración a otra.

Primero, clasifica el síntoma

No responder puede significar situaciones distintas:

  • Error de resolución o conexión: el emisor no encuentra el dominio, no logra abrir la conexión o rechaza el certificado presentado.
  • Timeout: la conexión existe, pero no llega una respuesta completa dentro del plazo del emisor.
  • Código 4xx: el receptor rechazó la solicitud por ruta, autenticación, tamaño, formato o reglas propias.
  • Código 5xx: un proxy o la aplicación informó una falla temporal o inesperada.
  • Respuesta exitosa sin efecto: el endpoint contestó, pero la tarea posterior no se ejecutó, se duplicó o quedó perdida.

HTTP define la semántica general de los códigos, pero el emisor decide cuáles cuentan como entrega aceptada. RFC 9110 es la referencia del protocolo; el panel o documentación del proveedor sigue siendo la fuente para su contrato concreto.

Sigue la solicitud por capas

Investiga de afuera hacia adentro. Primero comprueba que la URL pública sea la configurada y que la ruta acepte el método esperado. Después revisa DNS, TLS, balanceador, proxy inverso, firewall y aplicación. Finalmente inspecciona colas, base de datos y servicios externos.

Una matriz breve evita saltar directamente al código:

Capa Pregunta útil Evidencia
Configuración ¿La URL y el ambiente son correctos? Configuración vigente, sin copiar secretos
Red ¿Se resolvió el dominio y se abrió conexión? Métricas DNS/TLS, registros del proxy
HTTP ¿Qué método, ruta y código se observaron? Registro de acceso con identificador de solicitud
Aplicación ¿La solicitud pasó la validación? Log estructurado y error clasificado
Dependencias ¿Qué llamada consumió el tiempo? Duración por consulta o servicio
Negocio ¿La acción se confirmó una sola vez? Estado del evento y clave idempotente

Un 502 Bad Gateway, por ejemplo, indica que un intermediario recibió una respuesta inválida de un servidor aguas arriba; no demuestra por sí solo que el cuerpo del webhook fuera incorrecto. MDN documenta el significado de 502 y ayuda a distinguirlo de un rechazo generado deliberadamente por la aplicación.

Responde rápido y mueve el trabajo pesado

El endpoint debería hacer el trabajo mínimo necesario para aceptar o rechazar la entrega según el contrato: leer el cuerpo sin alterarlo, aplicar la validación exigida, extraer una identidad estable, registrar la recepción y colocar la tarea en una cola duradera. Enviar correos, generar documentos o llamar a varios servicios antes de responder aumenta la probabilidad de timeout.

Este ejemplo público e hipotético usa TypeScript con APIs de Node. El encabezado y la función de validación son deliberadamente genéricos: deben sustituirse por el mecanismo documentado por el proveedor real.

import { createServer } from "node:http";

const receiverToken = process.env.PROVIDER_WEBHOOK_TOKEN;
const maximumBodyBytes = 256_000;

if (!receiverToken) {
  throw new Error("Falta PROVIDER_WEBHOOK_TOKEN");
}

async function enqueueDeliveryPlaceholder(
  eventId: string,
  body: Buffer,
): Promise<void> {
  console.log(JSON.stringify({ eventId, bytes: body.length, state: "demo" }));
}

createServer(async (request, response) => {
  if (request.method !== "POST" || request.url !== "/hooks/provider") {
    response.writeHead(404).end();
    return;
  }

  try {
    const chunks: Buffer[] = [];
    let receivedBytes = 0;

    for await (const chunk of request) {
      receivedBytes += chunk.length;
      if (receivedBytes > maximumBodyBytes) {
        response.writeHead(413).end();
        return;
      }
      chunks.push(Buffer.from(chunk));
    }

    const rawBody = Buffer.concat(chunks);
    const eventId = request.headers["x-event-id"];
    const suppliedToken = request.headers.authorization;

    if (suppliedToken !== `Bearer ${receiverToken}` || typeof eventId !== "string") {
      response.writeHead(401).end();
      return;
    }

    await enqueueDeliveryPlaceholder(eventId, rawBody);
    response.writeHead(202).end();
  } catch {
    if (!response.headersSent) response.writeHead(503).end();
    else response.destroy();
  }
}).listen(8080);

enqueueDeliveryPlaceholder solo hace visible el punto de extensión: no es una cola ni almacenamiento duradero y debe reemplazarse antes de operar el receptor. El ejemplo no representa un contrato universal ni garantiza seguridad absoluta. Una comparación de token puede no ser el esquema correcto para tu proveedor. Sigue su documentación, limita la exposición del endpoint y conserva cualquier secreto exclusivamente en un gestor o variable de entorno, nunca en el repositorio.

Añade límites explícitos

Un receptor necesita límites para no convertir una solicitud defectuosa en agotamiento de recursos. Define un tamaño máximo del cuerpo, tiempo de lectura, concurrencia aceptable y presupuesto para dependencias. Rechaza temprano lo que exceda el contrato y evita registrar el cuerpo completo por defecto: podría contener datos personales o comerciales.

También distingue entre errores permanentes y temporales. Una ruta inexistente o un evento de tipo no admitido suele requerir corregir configuración o contrato. Una base de datos momentáneamente indisponible puede justificar una respuesta recuperable. El código exacto y el efecto sobre los reintentos dependen del proveedor; asumir que todos reaccionan igual crea bucles o pérdidas silenciosas.

Registra lo necesario para reconstruir el fallo

Un log útil incluye hora, ruta, método, código de respuesta, duración, tamaño, identificador de solicitud y, cuando el contrato lo proporcione, identificador del evento. No debería incluir tokens, credenciales ni cuerpos completos sin una necesidad documentada.

Relaciona cuatro momentos:

  1. llegada al proxy;
  2. aceptación o rechazo en la aplicación;
  3. inserción en la cola o registro duradero;
  4. resultado del consumidor.

Así puedes distinguir “nunca llegó” de “llegó y falló después”. La guía de logging de OWASP recomienda eventos auditables y protección frente a datos sensibles, inyección en logs y acceso excesivo.

Prueba de forma controlada

Reproduce con una carga de prueba autorizada y valores ficticios. Verifica método, Content-Type, tamaño y encabezados sin usar credenciales reales en capturas o comandos compartidos. Si el proveedor ofrece reenvío desde su panel o un entorno de pruebas, suele ser mejor que fabricar una solicitud que quizá no represente su contrato.

Prueba además estos escenarios:

  • cuerpo malformado;
  • identidad de evento ausente;
  • evento repetido;
  • cola no disponible;
  • procesamiento más lento de lo habitual;
  • despliegue durante una entrega;
  • dependencia externa con timeout.

La prueba de repetición es esencial: una recuperación de red puede hacer que el emisor reintente aunque el receptor haya procesado el primer intento. El artículo sobre consumidores seguros de eventos explica cómo limitar efectos duplicados.

Prepara una respuesta operativa

Cuando existe una incidencia, pausa cambios no relacionados, conserva evidencia y asigna responsables por capa. Si el endpoint está saturado, reducir trabajo síncrono suele ser más útil que ampliar timeouts sin diagnóstico. Si se acumuló una cola, restablece primero la recepción y luego drena el atraso con límites para no volver a sobrecargar las dependencias.

Tras recuperar el servicio, documenta la causa, el periodo afectado, los eventos reenviados y las comprobaciones realizadas. La trazabilidad de un cobro ofrece criterios para conservar decisiones sin acumular información innecesaria.

Finalmente, evalúa si el flujo realmente necesita entrega inmediata o si una consulta periódica puede complementar la recuperación. Webhooks vs. polling compara ambos modelos sin presentar uno como solución universal. Ningún control elimina todo riesgo: el objetivo es detectar fallos pronto, contener sus efectos y poder recuperar el procesamiento de manera verificable.

Lecturas relacionadas