Cómo Capturar y Validar Webhooks de Stripe en CI con Apidog

Aprende cómo probar webhooks de Stripe en CI con Apidog: captura eventos en tu backend, regístralos y luego valida el payload con un Post-Request Processor.

INEZA Felin-Michel

INEZA Felin-Michel

16 July 2026

Cómo Capturar y Validar Webhooks de Stripe en CI con Apidog

Apidog para empresas

Despliegue local

SSO & RBAC

Conforme con SOC 2

Explorar Apidog Enterprise

Un cliente paga, Stripe dispara un evento payment_intent.succeeded a tu backend, y tu endpoint se supone que debe marcar el pedido como pagado. Ese último paso es el que falla silenciosamente. El webhook llega, tu manejador lanza un error, y nadie se da cuenta hasta que un ticket de soporte dice "Pagué, pero mi cuenta aún aparece como impagada". Quieres una prueba en CI que demuestre que el evento llegó y fue manejado correctamente, cada vez que despliegas.

La parte complicada es que un webhook es una llamada HTTP entrante de Stripe hacia ti, no una solicitud que tú haces. La mayoría de las herramientas de prueba de API están construidas para enviar una solicitud y verificar la respuesta, lo cual es la forma opuesta. Así que la pregunta se convierte en: ¿cómo afirmas algo que llega en su propio horario, dentro de una ejecución de CI, sin un humano observando? Esta guía muestra la forma honesta y compatible de hacerlo con Apidog, y comienza con una limitación que debes conocer de antemano. Si primero quieres tener una visión más amplia de cómo probar endpoints impulsados por eventos, nuestra guía sobre cómo probar webhooks sienta las bases, y la propia documentación de webhooks de Stripe cubre el modelo de entrega de eventos.

La restricción que debes considerar en tu diseño

Aquí está el hecho fundamental, expuesto claramente en la documentación de Apidog: "ApiDog no soporta nativamente la escucha de webhooks". Apidog no se ubica en una URL pública para capturar las llamadas entrantes de Stripe en tiempo real. Si esperabas apuntar Stripe a un oyente de Apidog y ver los eventos llegar, ese camino no existe.

Eso suena como un callejón sin salida. No lo es. Simplemente cambia la forma de la prueba. En lugar de interceptar el webhook a medida que llega, lo capturas en tu propio backend, lo almacenas y luego haces que Apidog consulte ese registro almacenado y haga una aserción sobre él. Primero capturas, luego validas. Una vez que aceptas esa división, todo el flujo de trabajo se vuelve sencillo y, lo que es importante, se adapta perfectamente a CI porque una consulta a la base de datos es determinista y repetible.

Cómo es el patrón de captura y luego consulta

El patrón que recomienda la documentación de Apidog tiene cuatro partes:

  1. Crea un endpoint en tu servicio backend para capturar los webhooks entrantes de Stripe.
  2. Almacena los datos del evento del webhook en una tabla Stripe event logs en tu base de datos.
  3. Usa el Post-Request Processor de Apidog para consultar tu base de datos.
  4. Recupera el evento de webhook almacenado y valídalo contra los resultados esperados.

Dos de esos pasos viven en tu código, y dos viven en Apidog. El endpoint de captura y la tabla de registro son tu responsabilidad de construir, porque se ejecutan dentro de tu propia aplicación. El trabajo de Apidog comienza una vez que el evento está en tu base de datos: se conecta a esa base de datos y lee la fila para confirmar que el evento fue manejado de la manera que esperas. Mantén esa división clara y el resto encajará.

Paso 1: construir el endpoint de captura

Tu backend necesita una ruta a la que Stripe pueda enviar una solicitud POST. Este es código de aplicación ordinario, no una característica de Apidog. Un manejador Express mínimo que verifica la firma y registra el evento se ve así:

import express from "express";
import Stripe from "stripe";

const app = express();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;

app.post(
  "/webhooks/stripe",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    let event;
    try {
      event = stripe.webhooks.constructEvent(
        req.body,
        req.headers["stripe-signature"],
        endpointSecret
      );
    } catch (err) {
      return res.status(400).send(`Signature check failed: ${err.message}`);
    }

    // Persiste el evento para que una prueba pueda leerlo más tarde.
    await db.query(
      `INSERT INTO stripe_event_logs (event_id, type, payload, handled_at)
       VALUES ($1, $2, $3, now())
       ON CONFLICT (event_id) DO NOTHING`,
      [event.id, event.type, JSON.stringify(event.data.object)]
    );

    if (event.type === "payment_intent.succeeded") {
      const intent = event.data.object;
      await markOrderPaid(intent.metadata.order_id);
    }

    res.json({ received: true });
  }
);

Dos cosas importan aquí. Primero, verificas la firma de Stripe con constructEvent antes de confiar en nada, lo cual es el paso de seguridad no negociable para cualquier receptor de webhook. Si quieres el razonamiento completo detrás de esa verificación, nuestro artículo sobre la verificación de firma de webhook explica por qué una comparación del cuerpo en bruto es la única forma segura de hacerlo. Segundo, escribes el evento en una tabla Stripe event logs. Esa fila es lo que Apidog leerá. La cláusula ON CONFLICT DO NOTHING mantiene el registro idempotente, ya que Stripe puede entregar el mismo evento más de una vez.

Paso 2: conectar tu base de datos en el entorno de Apidog

Apidog soporta la conexión a una base de datos en el entorno correspondiente, y esa conexión es lo que hace que todo este patrón funcione. Configura una conexión a la base de datos para el entorno al que apunta tu ejecución de CI, ya sea un Postgres de staging o una base de datos de prueba dedicada. Una vez que la conexión esté establecida, un paso de prueba puede ejecutar SQL contra ella y recuperar filas reales.

Haz que la conexión coincida con el entorno que estás probando. Una prueba que se ejecuta contra un entorno de staging debe consultar la base de datos de staging, para que el evento que tu prueba dispara sea el evento que tu prueba lee. Los entornos no coincidentes son la razón más común por la que un endpoint de captura que funciona aún falla la aserción.

Paso 3: añadir un Post-Request Processor para consultar el registro

Este es el punto clave. El Post-Request Processor es la característica de Apidog que consulta tu base de datos y valida el evento de webhook registrado dentro de una prueba. Lo adjuntas a una solicitud en tu escenario de prueba. Después de que se ejecuta la solicitud, el procesador ejecuta tu SQL, lee el evento almacenado y te permite hacer una aserción sobre el resultado.

Un flujo realista para el caso payment_intent.succeeded:

  1. Tu escenario de prueba desencadena el pago. Esto podría ser una solicitud que crea una intención de pago y la confirma en el modo de prueba de Stripe, o un fixture que dispara un evento de prueba conocido a tu endpoint de captura.
  2. Stripe entrega el webhook a tu ruta /webhooks/stripe, que verifica la firma y escribe una fila en stripe_event_logs.
  3. Un Post-Request Processor en el siguiente paso consulta esa tabla para el evento.

La consulta que ejecuta el procesador es SQL simple:

SELECT event_id, type, payload, handled_at
FROM stripe_event_logs
WHERE type = 'payment_intent.succeeded'
ORDER BY handled_at DESC
LIMIT 1;

Luego haces una aserción contra la fila devuelta. La prueba pasa cuando los datos registrados coinciden con tus expectativas: el type es payment_intent.succeeded, el event_id coincide con el que activaste, el monto del payload es igual a lo que cobraste, y handled_at está poblado, lo que prueba que tu manejador realmente se ejecutó en lugar de que la fila fuera un marcador de posición. Recupera el evento de webhook almacenado, compáralo con el resultado esperado y deja que la aserción decida si pasa o falla.

Debido a que el tiempo de entrega del webhook no es instantáneo, dale un momento al evento para que llegue antes de que consultes. Un pequeño paso de retraso, o un bucle de sondeo que reintenta la consulta varias veces antes de fallar, evita que la prueba compita con la entrega de Stripe. Este es el único lugar donde la naturaleza asincrónica de los webhooks se filtra en el diseño de tu prueba, y una pequeña ventana de reintentos lo maneja limpiamente.

Una nota sobre el reenvío en tiempo real durante el desarrollo local

El patrón de captura y luego consulta está diseñado para CI, donde una base de datos y un registro almacenado son exactamente lo que necesitas. El desarrollo local es una situación diferente. Cuando estás escribiendo el manejador en tu portátil, Stripe no puede alcanzar localhost directamente, por lo que necesitas algo que reenvíe los eventos a tu máquina en tiempo real.

Para eso, la documentación de Apidog apunta a un servicio de retransmisión de webhooks, nombrando el CLI de Stripe y Ngrok como ejemplos. El CLI de Stripe puede escuchar y reenviar eventos directamente a tu puerto local:

stripe listen --forward-to localhost:3000/webhooks/stripe

Eso te proporciona eventos en vivo mientras construyes el manejador. Ngrok hace el mismo trabajo exponiendo tu puerto local en una URL pública que registras como un endpoint de Stripe. Usa estos para el ciclo de desarrollo interno, y luego confía en la base de datos más el flujo de Post-Request Processor para las aserciones que se ejecutan en tu pipeline. Los dos son complementarios: retransmisión para construir, captura-luego-consulta para probar.

No lo confundas con la función nativa de Webhook de Apidog

Apidog sí tiene una característica literalmente llamada Webhook, y es fácil asumir que así es como se capturan los eventos de Stripe. No lo es, y confundirlos te costará una tarde. La característica nativa Webhook es para definir y documentar un webhook saliente, es decir, un endpoint HTTP al que tu propio sistema llama cuando ocurre un evento. El sistema inicia la llamada a una URL externa, lo cual es lo opuesto a un endpoint regular donde los clientes te llaman a ti. Se utiliza para describir notificaciones de cambio de estado y resultados de tareas asíncronas en tu documentación de API, no para recibir las llamadas entrantes de Stripe.

Si deseas documentar uno de tus propios webhooks salientes, el flujo es corto:

  1. Haz clic en el icono + en la barra lateral izquierda.
  2. Selecciona New Other Protocol APIs, luego Webhook.
  3. Rellena los campos obligatorios: Request Method (normalmente POST), un Webhook Name, una Debug URL opcional solo para pruebas, y Other Info para el cuerpo de la solicitud, los encabezados y la configuración.
  4. Haz clic en Save.

Para probarlo, introduce una URL en el campo Debug URL y haz clic en Send para simular la llamada del webhook. Una advertencia que vale la pena recordar: la Debug URL es solo para pruebas y no aparecerá en tu documentación publicada ni en tu exportación OpenAPI. Para un tratamiento más completo del diseño y la documentación de las devoluciones de llamada de eventos, nuestro artículo sobre webhooks en el diseño de API cubre dónde encajan. La versión corta para este artículo: la función nativa de Webhook define tus eventos salientes, y el patrón de captura y luego consulta valida los entrantes de Stripe. Mantenlos en cajas mentales separadas.

Variaciones y endurecimiento

Una vez que la aserción básica funciona, algunas mejoras la hacen de grado de producción. Primero, haz aserciones sobre algo más que el tipo de evento. Verifica el event_id de principio a fin para que sepas que el evento exacto que activaste es el que validaste, no un residuo de una ejecución anterior. Trunca o acota la tabla stripe_event_logs por cada ejecución de prueba si los eventos se acumulan.

Segundo, prueba las rutas de fallo. Dispara un evento que tu manejador debería rechazar, una firma incorrecta o un tipo inesperado, y verifica que no se escriba ninguna marca de tiempo handled_at. Un conjunto de pruebas de webhook que solo verifica el camino feliz pierde los casos que realmente te alertan a las 2 a.m. Nuestras notas sobre las mejores prácticas de webhook de pago cubren la idempotencia y el comportamiento de reintento que vale la pena codificar en estas pruebas.

Tercero, mantén la aserción ajustada al significado comercial, no solo a la entrega. "El evento llegó" es más débil que "el pedido pasó a pagado". Si tu manejador actualiza una tabla orders, añade una segunda consulta que confirme que el estado posterior cambió, para que la prueba demuestre toda la cadena y no solo la escritura del registro.

También puedes llevar esto más allá de la puerta de fusión. Una vez que el escenario se guarda en Apidog, prográmalo para que se ejecute con una cadencia para que un manejador de webhook roto aparezca incluso entre despliegues. Nuestra guía sobre cómo programar pruebas de API en Apidog muestra cómo poner esta misma validación en un temporizador.

Automatiza el flujo de trabajo con la CLI de Apidog

Todo lo anterior da sus frutos cuando se ejecuta sin supervisión, y ahí es donde entra en juego la CLI de Apidog. Esta es intrínsecamente una historia de CI, por lo que integrar el escenario guardado en tu pipeline es el final natural. Instala la CLI y autentícate con tu token:

npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>

Luego, ejecuta tu escenario de validación de webhook guardado sin interfaz gráfica contra el entorno cuya base de datos contiene los registros de eventos:

apidog run --access-token $APIDOG_ACCESS_TOKEN -t <SCENARIO_ID> -e <ENV_ID> -r cli

Aquí -t es el ID del escenario de prueba, -e es el ID del entorno, y -r selecciona el reportero. Usa -r html,cli si quieres un informe navegable junto con la salida de la consola para tus artefactos de CI. El escenario lleva el Post-Request Processor y su consulta a la base de datos, por lo que un solo comando desencadena el flujo, lee la fila de stripe_event_logs y devuelve un código de salida distinto de cero si la aserción falla, que es exactamente lo que una pipeline necesita para controlar una fusión. La guía de instalación de la CLI de Apidog cubre la configuración del token, y nuestro tutorial de pipeline de CI/CD muestra la configuración completa de GitHub Actions en torno a este comando.

Preguntas frecuentes

¿Puede Apidog recibir un webhook de Stripe directamente? No. La documentación de Apidog afirma claramente que "no soporta nativamente la escucha de webhooks". Capturas el evento en tu propio endpoint de backend, lo almacenas en una base de datos, y Apidog lo lee de vuelta con un Post-Request Processor. Para el reenvío en tiempo real durante el desarrollo local, usa un relé como el CLI de Stripe o Ngrok en su lugar.

¿Dónde ocurren realmente las aserciones? Dentro del paso Post-Request Processor en una solicitud en tu escenario de prueba. Consulta tu tabla Stripe event logs a través de la conexión a la base de datos que configuraste en el entorno, recupera el evento almacenado y lo compara con tus valores esperados. La prueba pasa cuando los datos registrados coinciden.

¿Necesito un plan de pago para el flujo de validación de la base de datos? La documentación de Apidog para este flujo de trabajo no menciona ninguna restricción de plan, por lo que esta guía no inventará una. La respuesta honesta es verificar los detalles del plan actual en la página de precios. Puedes Descargar Apidog y configurar un proyecto de prueba para ver el Post-Request Processor y la conexión a la base de datos del entorno por ti mismo.

¿Cómo gestiono el retraso entre el desencadenamiento y la entrega? La entrega de webhooks no es instantánea, así que añade una pequeña espera o un reintento por sondeo antes de la consulta para que tu prueba no compita con Stripe. Unos pocos reintentos durante un par de segundos suelen ser suficientes. Si eres nuevo en la aserción en endpoints asíncronos, comienza con la guía general cómo probar webhooks antes de añadir los detalles específicos de Stripe.

¿Es útil aquí la función nativa de Webhook? No para capturar eventos de Stripe. Esa función define y documenta tus propios webhooks salientes, donde tu sistema llama a una URL externa. Es una herramienta de documentación y diseño, separada del patrón de captura y luego consulta que utiliza este artículo. Mantén los dos claramente separados.

Conclusión

No puedes apuntar Stripe a Apidog y capturar eventos en vivo, y pretender lo contrario lleva a una tarde frustrante. El camino soportado es más limpio de lo que parece a primera vista: captura el webhook en tu propio endpoint, regístralo en una tabla Stripe event logs, luego deja que el Post-Request Processor de Apidog consulte ese registro y afirme que el evento fue manejado. Envuelve el escenario guardado en apidog run y tu pipeline probará, en cada fusión, que un evento de pago real mueve tu pedido a pagado. Pruébalo gratis, no se requiere tarjeta de crédito, y pon una aserción real detrás del webhook que más importa.

Practica el diseño de API en Apidog

Descubre una forma más fácil de construir y usar APIs