> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Recibe notificaciones de eventos en tiempo real de Dodo Payments. Configura endpoints, verifica firmas, gestiona reintentos y prueba webhooks durante el desarrollo.

<Frame>
  <img src="https://mintcdn.com/dodopayments/mOQO5ej_lx0yH9p-/images/cover-images/Webhooks.webp?fit=max&auto=format&n=mOQO5ej_lx0yH9p-&q=85&s=477435b1004773582aa51236b5cc58e7" alt="Imagen de portada del Webhook" style={{ maxHeight: '500px', width: 'auto' }} width="1200" height="630" data-path="images/cover-images/Webhooks.webp" />
</Frame>

Los webhooks envían notificaciones en tiempo real cuando ocurren eventos en tu cuenta de Dodo Payments. Úsalos para automatizar flujos de trabajo, actualizar tu base de datos, enviar notificaciones y mantener tus sistemas sincronizados.

<Info>
  Los webhooks de Dodo Payments siguen la especificación de [Standard Webhooks](https://standardwebhooks.com/) para la verificación de firmas y la estructura del payload.
</Info>

## Key Features

Los webhooks ofrecen entrega en tiempo real con seguridad integrada, reintentos automáticos y filtrado de eventos. Todos los SDK oficiales incluyen helpers de verificación de firmas, y el dashboard ofrece herramientas de prueba, supervisión y repetición.

## Getting Started

<Steps>
  <Step title="Go to Developer → Webhooks">
    En el Dashboard de Dodo Payments, ve a **Developer → Webhooks**.
  </Step>

  <Step title="Click Add Endpoint">
    Haz clic en **Add endpoint** para crear un nuevo receptor de webhooks.
  </Step>

  <Step title="Enter Your Endpoint URL">
    Proporciona la URL HTTPS donde Dodo Payments enviará los eventos de webhook, o selecciona un conector de integración (Slack, Discord, Zapier, Resend, etc.) para dirigir los eventos a un servicio de terceros sin escribir código.
  </Step>

  <Step title="Select Events">
    Elige qué eventos recibir. Los eventos están organizados por recurso (pago, suscripción, disputa, etc.). Puedes seleccionar eventos individuales o un recurso completo para recibir todos los eventos relacionados.
  </Step>

  <Step title="Save">
    Haz clic en **Create endpoint**. Tu secreto de firma del webhook aparece en la pestaña **Overview** del endpoint.
  </Step>
</Steps>

<Warning>
  Mantén seguro tu secreto del webhook. Nunca lo expongas en código del lado del cliente ni en el control de versiones.
</Warning>

Para rotar tu secreto del webhook, abre el endpoint y haz clic en **Rotate secret**, junto al secreto, en la pestaña **Overview**. El secreto anterior sigue siendo válido durante 24 horas después de la rotación.

## Conectores de integración

Dirige los eventos de webhook directamente a servicios de terceros mediante conectores de integración, eliminando la necesidad de crear y mantener handlers de webhook personalizados.

### Cómo funcionan los conectores

Un conector transforma los eventos de Dodo Payments al formato que espera el destino. Los datos que debes proporcionar dependen del destino:

| Tipo de conector | Lo que proporcionas | Destinos |
| - | - | - |
| **URL de webhook entrante** | Una URL de webhook que creas en el panel del proveedor. Sin API key. | [Slack](/integrations/slack), [Discord](/integrations/discord), [Microsoft Teams](/integrations/microsoft-teams), [Zapier](/integrations/zapier), [Windmill](/integrations/windmill) |
| **API del proveedor** | Una API key. La URL de destino proviene de la plantilla del conector. | [Resend](/integrations/resend), [SendGrid](/integrations/sendgrid), [Segment](/integrations/segment), [Customer.io](/integrations/customer-io), [Close CRM](/integrations/close-crm), [Loops](/integrations/loops) |

El dashboard muestra todos los conectores disponibles para tu empresa. Consulta [External Integrations](/integrations/introduction) para saber qué puede hacer cada destino con los eventos.

### Configurar un conector

Al crear o editar un endpoint, selecciona un conector y el panel lateral mostrará las instrucciones de configuración para ese destino. Prueba la transformación antes de guardar para confirmar que los eventos se convierten correctamente.

<Tip>
  Usa un conector para llegar a un destino compatible sin escribir código. Si necesitas lógica personalizada, utiliza un endpoint estándar con una [transformación](#transformations).
</Tip>

## Configurar eventos suscritos

Configura qué eventos recibe cada endpoint de webhook.

<Steps>
  <Step title="Navigate to Webhook Endpoints">
    Ve a **Developer → Webhooks** y haz clic en tu endpoint.
  </Step>

  <Step title="Open Event Configuration">
    Haz clic en **Edit** para abrir el panel lateral de configuración del endpoint.
  </Step>

  <Step title="Select Events">
    El selector de tipos de evento muestra todos los eventos de webhook disponibles en un árbol que se puede buscar, agrupados por recurso (por ejemplo, `payment`, `subscription`, `dispute`). Marca las casillas junto a los eventos que quieres recibir. Puedes seleccionar eventos individuales, un recurso completo o combinarlos.
  </Step>

  <Step title="Save Configuration">
    Haz clic en **Save** para aplicar los cambios.
  </Step>
</Steps>

<Warning>
  Si anulas la selección de todos los eventos, tu endpoint de webhook recibe todos los tipos de evento. Selecciona solo los eventos que necesita tu aplicación.
</Warning>

## Catálogo de eventos

Ve a **Developer → Webhooks** y abre la pestaña **Event catalog** para ver todos los tipos de evento que puede enviar Dodo Payments. Selecciona un evento para ver su esquema y payload de ejemplo.

<Card title="Webhook Events Guide" icon="list" href="/developer-resources/webhooks/intents/webhook-events-guide">
  Explora los eventos como documentación de referencia, agrupados por recurso.
</Card>

## Entrega de webhooks

### Timeouts

Los webhooks tienen un **tiempo de espera de 30 segundos** tanto para las operaciones de conexión como de lectura. Procesa los webhooks de forma asíncrona devolviendo inmediatamente un código de estado `200` y gestionando después el evento en segundo plano.

### Reintentos automáticos

Las entregas fallidas se reintentan con un retroceso exponencial, hasta un total de 8 intentos:

| Intento | Retraso |
| - | - |
| 1 | Inmediatamente |
| 2 | 5 segundos |
| 3 | 5 minutos |
| 4 | 30 minutos |
| 5 | 2 horas |
| 6 | 5 horas |
| 7 | 10 horas |
| 8 | 10 horas (final) |

Usa el panel para volver a reproducir manualmente los mensajes fallidos o recuperar en bloque los mensajes de un intervalo de tiempo específico.

### Idempotencia

Cada webhook incluye un encabezado `webhook-id` único. Almacena este ID para detectar y omitir eventos duplicados, ya que los reintentos pueden entregar el mismo evento varias veces.

```javascript theme={null}
// Use a persistent store such as your database in production. An in-memory Set is lost on restart.
const processedWebhooks = new Set();

app.post('/webhook', async (req, res) => {
  const webhookId = req.headers['webhook-id'];

  if (processedWebhooks.has(webhookId)) {
    return res.status(200).json({ received: true });
  }

  // processWebhook is your handler. Record the ID only after it succeeds,
  // so a failed attempt is processed again on retry.
  await processWebhook(req.body);
  processedWebhooks.add(webhookId);
  res.status(200).json({ received: true });
});
```

<Warning>
  Implementa siempre comprobaciones de idempotencia. Debido a los reintentos, puedes recibir el mismo evento varias veces.
</Warning>

### Orden de los eventos

Los eventos pueden llegar desordenados debido a los reintentos o a las condiciones de la red. Cada webhook incluye un campo `timestamp`; úsalo para ordenar los eventos si tu aplicación lo requiere. Siempre recibes el estado más reciente del payload en el momento de la entrega.

## Protección de los webhooks

Valida siempre los payloads de los webhooks y usa HTTPS.

### Verificación de firmas

Cada webhook incluye un encabezado `webhook-signature`: una firma HMAC SHA256 del payload y la marca de tiempo, firmada con tu clave secreta.

#### Verificación mediante SDK (recomendado)

Todos los SDK oficiales incluyen helpers integrados. Configura `DODO_PAYMENTS_WEBHOOK_KEY` al inicializar el cliente y, después, llama a `unwrap()` para verificar y analizar el payload. Hay dos métodos disponibles:

* `unwrap` — Verifica la firma con tu clave secreta del webhook y después analiza el payload.
* `unsafe_unwrap` — Analiza el payload sin verificarlo. Úsalo solo para realizar pruebas.

Los nombres de los métodos siguen las convenciones de cada lenguaje: `unwrap` / `unsafeUnwrap` en TypeScript, `unwrap` / `unsafe_unwrap` en Python y `Unwrap` / `UnsafeUnwrap` en Go.

<Tip>
  Proporciona tu secreto del webhook mediante `DODO_PAYMENTS_WEBHOOK_KEY` al inicializar el cliente de Dodo Payments.
</Tip>

<CodeGroup>
  ```typescript TypeScript/Node.js theme={null}
  import DodoPayments from 'dodopayments';
  import express from 'express';

  const app = express();
  app.use(express.raw({ type: 'application/json' }));

  const client = new DodoPayments({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
  });

  app.post('/webhook', async (req, res) => {
    try {
      const event = client.webhooks.unwrap(req.body.toString(), {
        headers: {
          'webhook-id': req.headers['webhook-id'] as string,
          'webhook-signature': req.headers['webhook-signature'] as string,
          'webhook-timestamp': req.headers['webhook-timestamp'] as string,
        },
      });
      res.json({ received: true });
    } catch (error) {
      res.status(401).json({ error: 'Invalid signature' });
    }
  });
  ```

  ```python Python theme={null}
  from fastapi import FastAPI, Request, HTTPException
  from dodopayments import DodoPayments
  import os

  app = FastAPI()
  client = DodoPayments(
      bearer_token=os.getenv("DODO_PAYMENTS_API_KEY"),
      webhook_key=os.getenv("DODO_PAYMENTS_WEBHOOK_KEY"),
  )

  @app.post("/webhook")
  async def handle_webhook(request: Request):
      try:
          event = client.webhooks.unwrap(
              await request.body(),
              headers={
                  "webhook-id": request.headers.get("webhook-id", ""),
                  "webhook-signature": request.headers.get("webhook-signature", ""),
                  "webhook-timestamp": request.headers.get("webhook-timestamp", ""),
              },
          )
          return {"received": True}
      except Exception:
          raise HTTPException(status_code=401, detail="Invalid signature")
  ```

  ```go Go theme={null}
  import (
  	"io"
  	"net/http"
  	"os"
  	"github.com/dodopayments/dodopayments-go"
  	"github.com/dodopayments/dodopayments-go/option"
  )

  func webhookHandler(w http.ResponseWriter, r *http.Request) {
  	client := dodopayments.NewClient(
  		option.WithBearerToken(os.Getenv("DODO_PAYMENTS_API_KEY")),
  		option.WithWebhookKey(os.Getenv("DODO_PAYMENTS_WEBHOOK_KEY")),
  	)
  	rawBody, _ := io.ReadAll(r.Body)
  	event, err := client.Webhooks.Unwrap(rawBody, r.Header)
  	if err != nil {
  		http.Error(w, "Invalid signature", http.StatusUnauthorized)
  		return
  	}
  	_ = event // Handle the verified event here.
  	w.WriteHeader(http.StatusOK)
  }
  ```
</CodeGroup>

#### Verificación manual (alternativa)

Si no usas un SDK, verifica la firma por tu cuenta:

1. Construye el contenido firmado uniendo `webhook-id`, `webhook-timestamp` y el cuerpo sin procesar de la solicitud con puntos: `{id}.{timestamp}.{body}`. Usa el cuerpo sin procesar exactamente como se recibió, antes de analizar cualquier JSON.
2. Toma tu secreto del webhook. Si comienza por `whsec_`, elimina ese prefijo y, después, decodifica en base64 el resto para obtener la clave de firma.
3. Calcula el HMAC-SHA256 del contenido firmado con la clave de firma y codifica el resultado en base64.
4. El encabezado `webhook-signature` contiene una o más firmas separadas por espacios, cada una con el formato `v1,<base64-signature>`. La solicitud es válida si alguna firma `v1` coincide con la tuya. Compara mediante una función de tiempo constante.
5. Rechaza la solicitud si `webhook-timestamp` difiere demasiado de la hora actual para evitar ataques de repetición. Las bibliotecas de Standard Webhooks permiten 5 minutos.

Consulta las [bibliotecas de Standard Webhooks](https://github.com/standard-webhooks/standard-webhooks/tree/main/libraries) para ver implementaciones de referencia. Para consultar los formatos de payload de los eventos, visita [Payload del webhook](/developer-resources/webhooks/intents/payment).

### Direcciones IP de origen

La verificación de firmas es el método de autenticación compatible. Demuestra que la solicitud se firmó con tu secreto del webhook, algo que una comprobación a nivel de red no puede hacer.

Las entregas de webhooks provienen de un conjunto de direcciones IP que cambia con el tiempo. No dependas de listas de permitidos de IP para la autenticación. Verifica siempre el encabezado `webhook-signature`, tal como se describe en [Verificación de firmas](#verifying-signatures).

Si tu firewall requiere una lista de permitidos:

* **No codifiques las direcciones de forma permanente.** Los rangos cambian con el tiempo y las reglas obsoletas bloquean las entregas silenciosamente.
* **Solicita los rangos actuales** a [support@dodopayments.com](mailto:support@dodopayments.com) antes de restringir un firewall.
* **Presta atención a los avisos de cambios.** Cuando cambian las direcciones de entrega, notificamos por correo electrónico a los merchants afectados; aplica las actualizaciones antes de la fecha indicada.
* **Mantén activada la verificación de firmas** independientemente de las reglas de red que añadas.

<Tip>
  En las plataformas serverless y de alojamiento administrado, el filtrado de IP entrante suele no estar disponible o no ser práctico. La verificación de firmas es el control adecuado en esos entornos.
</Tip>

<Info>
  Una entrega bloqueada se considera un fallo y se reintenta según el calendario descrito en [Reintentos automáticos](#automatic-retries). Si las reglas del firewall provocaron el fallo de las entregas, puedes volver a enviarlas una vez corregidas las reglas; consulta [Reproducción y recuperación de mensajes](#replaying-and-recovering-messages).
</Info>

### Responder a los webhooks

Tu handler del webhook debe devolver un `2xx status code` para confirmar la recepción. Cualquier otra respuesta se considera un fallo y el webhook se reintentará.

### Prácticas recomendadas

* **Usa únicamente HTTPS.** Los endpoints HTTP son vulnerables a la interceptación.
* **Responde inmediatamente.** Devuelve un código de estado `200` de inmediato y procesa después el evento de forma asíncrona.
* **Implementa la idempotencia.** Usa el encabezado `webhook-id` para detectar y omitir eventos duplicados.
* **Protege tu secreto.** Almacena `DODO_PAYMENTS_WEBHOOK_KEY` en variables de entorno o en un gestor de secretos, nunca en el control de versiones.

## Estructura del payload del webhook

### Formato de la solicitud

```http theme={null}
POST /your-webhook-url
Content-Type: application/json
```

### Encabezados

<ParamField header="webhook-id" type="string" required>
  Identificador único de este evento de webhook. Úsalo para las comprobaciones de idempotencia.
</ParamField>

<ParamField header="webhook-signature" type="string" required>
  Firma HMAC SHA256 para verificar la autenticidad del webhook.
</ParamField>

<ParamField header="webhook-timestamp" type="string" required>
  Marca de tiempo Unix (en segundos) en la que se envió el webhook.
</ParamField>

### Cuerpo de la solicitud

<ResponseField name="business_id" type="string" required>
  Identificador de tu negocio en Dodo Payments.
</ResponseField>

<ResponseField name="type" type="string" required>
  Tipo de evento que activó este webhook (por ejemplo, `payment.succeeded`, `subscription.active`).
</ResponseField>

<ResponseField name="timestamp" type="string" required>
  Marca de tiempo con formato ISO 8601 en la que ocurrió el evento.
</ResponseField>

<ResponseField name="data" type="object" required>
  Payload específico del evento que contiene información detallada sobre el evento.

  <Expandable title="Data object properties">
    <ResponseField name="payload_type" type="string">
      Tipo de recurso. Uno de: `Payment`, `Subscription`, `Refund`, `Dispute`, `LicenseKey`, `CreditLedgerEntry`, `CreditBalanceLow`, `AbandonedCheckout`, `DunningAttempt`, `EntitlementGrant` o `Payout`.
    </ResponseField>

    Los campos adicionales varían según el tipo de evento. Consulta la documentación específica del evento para obtener los esquemas completos.
  </Expandable>
</ResponseField>

### Ejemplo de payload

```json theme={null}
{
  "business_id": "bus_H4ekzPSlcg",
  "type": "payment.succeeded",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "payload_type": "Payment",
    // ... event-specific fields
  }
}
```

<CardGroup cols={2}>
  <Card title="Event Types" icon="list" href="/developer-resources/webhooks/intents/webhook-events-guide">
    Explora todos los tipos de eventos de webhook disponibles
  </Card>

  <Card title="Event Payloads" icon="code" href="/developer-resources/webhooks/intents/payment">
    Consulta esquemas de payload detallados para cada evento
  </Card>

  <Card title="Handle Payment Failures" icon="screwdriver-wrench" href="/developer-resources/handle-payment-failures">
    Responde a `payment.failed` y recupera pagos rechazados
  </Card>
</CardGroup>

## Probar webhooks

### Enviar un evento de ejemplo

Prueba la integración de tu webhook directamente desde el panel:

<Steps>
  <Step title="Navigate to Webhooks">
    Ve a **Developer → Webhooks** y haz clic en tu endpoint.
  </Step>

  <Step title="Open Testing Tab">
    Haz clic en la pestaña **Testing**.
  </Step>

  <Step title="Send Example">
    Selecciona un tipo de evento y haz clic en **Send example**. El payload de ejemplo se entrega a la URL de tu endpoint exactamente como un evento real y se firma de la misma manera.
  </Step>

  <Step title="Check Your Endpoint">
    Confirma que el evento llegó, que la verificación de la firma se realizó correctamente y que devolviste un código de estado `2xx`.
  </Step>
</Steps>

<Note>
  Los mensajes fallidos enviados desde la pestaña Testing se reintentan según el calendario normal de reintentos, como cualquier otro webhook.
</Note>

### Ejemplo de implementación

Implementación completa en Express.js con verificación y gestión de webhooks:

<CodeGroup>
  ```typescript Express.js Webhook Handler theme={null}
  import { Webhook } from "standardwebhooks";
  import express from "express";

  const app = express();

  const webhook = new Webhook(process.env.DODO_PAYMENTS_WEBHOOK_KEY);

  // Use express.raw() for the webhook route so the exact bytes Dodo Payments
  // signed are preserved. Parsing with express.json() first and then calling
  // JSON.stringify(req.body) can alter the payload (e.g. whitespace), which
  // breaks signature verification.
  app.post(
    '/webhook/dodo-payments',
    express.raw({ type: "application/json" }),
    async (req, res) => {
      try {
        // Extract webhook headers
        const webhookHeaders = {
          "webhook-id": req.headers["webhook-id"] as string,
          "webhook-signature": req.headers["webhook-signature"] as string,
          "webhook-timestamp": req.headers["webhook-timestamp"] as string,
        };

        // Verify the webhook signature against the raw, unmodified body
        const payload = req.body.toString("utf8");
        await webhook.verify(payload, webhookHeaders);

        // Parse the payload only after verification succeeds
        const data = JSON.parse(payload);

        // Acknowledge receipt immediately
        res.status(200).json({ received: true });

        // Process webhook asynchronously
        processWebhookAsync(data).catch(console.error);

      } catch (error) {
        console.error('Webhook verification failed:', error);
        res.status(401).json({ error: 'Invalid signature' });
      }
    }
  );

  // Register express.json() for other routes after the webhook route so it
  // doesn't consume the raw body needed for signature verification above.
  app.use(express.json());

  async function processWebhookAsync(data: any) {
    // Handle the webhook event based on type
    switch (data.type) {
      case 'payment.succeeded':
        await handlePaymentSucceeded(data);
        break;
      case 'subscription.active':
        await handleSubscriptionActive(data);
        break;
      // Add more event handlers...
    }
  }
  ```

  ```javascript Testing Webhooks Locally theme={null}
  const { Webhook } = require("standardwebhooks");
  const axios = require("axios");
  const crypto = require("crypto");

  // Generate test webhook
  const timestamp = new Date();
  const webhookId = crypto.randomUUID();
  const payload = {
    business_id: "bus_H4ekzPSlcg",
    type: "payment.succeeded",
    timestamp: timestamp.toISOString(),
    data: {
      payload_type: "Payment",
      payment_id: "pay_test456",
      amount: 2999
    }
  };

  // Sign the payload
  const webhookSecret = process.env.DODO_PAYMENTS_WEBHOOK_KEY;
  const webhookInstance = new Webhook(webhookSecret);
  const payloadString = JSON.stringify(payload);
  const signature = webhookInstance.sign(webhookId, timestamp, payloadString);

  // Send test webhook. CommonJS scripts don't support top-level await, so use .then().
  axios.post('http://localhost:3000/webhook/dodo-payments', payload, {
    headers: {
      "webhook-id": webhookId,
      "webhook-timestamp": Math.floor(timestamp.getTime() / 1000),
      "webhook-signature": signature,
      "Content-Type": "application/json"
    }
  }).then((response) => {
    console.log("Test webhook sent successfully:", response.data);
  });
  ```
</CodeGroup>

<Tip>
  Prueba exhaustivamente tu handler del webhook mediante la interfaz de pruebas del panel antes de procesar eventos de producción. Esto ayuda a identificar y corregir los problemas de forma temprana.
</Tip>

## Probar webhooks con la CLI

La [CLI de Dodo Payments](/developer-resources/sdks/cli) tiene dos comandos para probar webhooks durante el desarrollo local.

### Escuchar webhooks en tiempo real localmente

Reenvía eventos de webhook reales desde tu cuenta en modo de prueba a tu servidor de desarrollo local:

```bash theme={null}
dodo wh listen
```

La CLI abre una conexión WebSocket y reenvía cada evento de webhook a tu endpoint local (por ejemplo, `http://localhost:3000/webhook`), conservando todos los encabezados para probar la verificación de firmas.

<Info>
  El listener solo funciona con API keys del modo de prueba. Ejecuta `dodo login` y selecciona primero Test Mode.
</Info>

### Activar eventos de webhook simulados

Envía payloads de webhook simulados a cualquier endpoint sin crear transacciones reales:

```bash theme={null}
dodo wh trigger
```

Esta herramienta interactiva te permite elegir un tipo de evento y envía un payload simulado realista a tu endpoint. Se repite para que puedas probar varios eventos en una misma sesión.

El comando de activación incluye las familias de suscripciones, pagos, reembolsos, disputas, claves de licencia, payouts, créditos, checkouts abandonados, dunning y concesiones de entitlements. No envía `subscription.past_due` ni `subscription.unpaused`. Consulta [Eventos de webhook compatibles](/developer-resources/sdks/cli#supported-webhook-events) para ver la lista exacta.

<Warning>
  Los payloads de webhook simulados de `dodo wh trigger` no están firmados. Usa el método de análisis no verificado (`unsafeUnwrap` en TypeScript, `unsafe_unwrap` en Python, `UnsafeUnwrap` en Go) en tu handler del webhook únicamente durante las pruebas.
</Warning>

<Card title="CLI Webhook Testing Docs" icon="terminal" href="/developer-resources/sdks/cli#webhooks">
  Consulta la documentación completa de pruebas de webhooks de la CLI
</Card>

## Configuración avanzada

La pestaña **Advanced** ofrece opciones de configuración adicionales para ajustar el comportamiento de tu endpoint de webhook.

### Limitación de velocidad (throttling)

Controla la velocidad a la que se entregan los eventos de webhook a tu endpoint. De forma predeterminada, los webhooks no tienen ningún límite de velocidad aplicado y los eventos se entregan tan pronto como ocurren.

<Steps>
  <Step title="Open Advanced Tab">
    En la página de detalles de tu endpoint, haz clic en la pestaña **Advanced**.
  </Step>

  <Step title="Configure Rate Limit">
    Expande la sección **Endpoint throttling**.
  </Step>

  <Step title="Set Your Limit">
    Introduce el número máximo de mensajes por segundo y haz clic en **Save**. Las entregas que superen esta velocidad se ponen en cola en lugar de descartarse.
  </Step>
</Steps>

### Encabezados personalizados

Añade encabezados HTTP personalizados a todas las solicitudes de webhook enviadas a tu endpoint. Resulta útil para la autenticación, el enrutamiento o la adición de metadatos.

<Steps>
  <Step title="Add Headers">
    En la sección **Custom headers**, introduce un nombre y un valor de encabezado.
  </Step>

  <Step title="Add Multiple Headers">
    Haz clic en **Add header** para cada encabezado adicional y, después, haz clic en **Save**.
  </Step>
</Steps>

### Transformaciones

Las transformaciones te permiten modificar el payload de un webhook y, opcionalmente, redirigirlo a una URL diferente. Usa transformaciones para:

* Modificar la estructura del payload antes de procesarlo
* Enrutar los webhooks a distintos endpoints según el contenido
* Añadir o eliminar campos del payload
* Transformar formatos de datos

<Steps>
  <Step title="Enable Transformations">
    En la sección **Transformation**, activa **Enable transformation**.
  </Step>

  <Step title="Configure Transformation">
    Escribe tus reglas de transformación en JavaScript en el editor de código y haz clic en **Save**. El código debe devolver el objeto de webhook desde `handler()`.
  </Step>

  <Step title="Test Transformation">
    Usa la interfaz de pruebas de transformación para comprobar que la transformación funciona correctamente antes de ponerla en producción.
  </Step>
</Steps>

<Warning>
  Las transformaciones pueden afectar al rendimiento de la entrega de webhooks. Realiza pruebas exhaustivas y mantén la lógica de transformación sencilla y eficiente.
</Warning>

## Supervisar los registros de webhooks

La pestaña **Logs** proporciona visibilidad sobre el estado de entrega de tus webhooks.

<Steps>
  <Step title="Navigate to Logs Tab">
    Ve a **Developer → Webhooks** y abre la pestaña **Logs**.
  </Step>

  <Step title="Browse Delivery History">
    Consulta una tabla con todos los intentos de entrega de webhooks y columnas para Event type, Message ID, Event ID, Sent at, Attempted at, Response code y Duration.
  </Step>

  <Step title="Search and Filter">
    Usa la barra de búsqueda para encontrar mensajes específicos por ID o tipo de evento. Filtra por estado (Succeeded, Failed, Pending, etc.) para centrarte en los eventos que necesitas investigar.
  </Step>

  <Step title="View Message Details">
    Haz clic en cualquier mensaje para abrir la página de detalles del mensaje, que muestra:

    * El payload completo del webhook
    * Cada intento de entrega con el código de respuesta y la duración
    * La marca de tiempo de cada intento
    * Cualquier mensaje de error de tu endpoint

    Cada intento incluye una acción **Replay** para volver a enviar ese mensaje sin salir de la página.
  </Step>
</Steps>

## Supervisión de actividad

Ve a **Developer → Webhooks** y abre la pestaña **Activity** para consultar el rendimiento de entrega en todos tus endpoints.

**Delivery activity** representa los intentos a lo largo del tiempo, agrupados como **Attempts per 5 minutes**, **Attempts per hour** o **Attempts per day**, según el intervalo. Cada barra se divide por resultado y, al pasar el cursor sobre un segmento, se muestran el estado, el número de intentos y su proporción del total. En un endpoint, **Delivery stats (last 24h)** en la pestaña **Overview** resume la misma información del último día.

<Tip>
  La columna **Error rate (24h)** de la pestaña **Endpoints** muestra de un vistazo qué endpoints requieren atención.
</Tip>

## Reproducción y recuperación de mensajes

La forma de volver a enviar un mensaje depende de cuántos necesites:

* **Un mensaje** — ábrelo desde la pestaña **Logs** y usa la acción **Replay** en el intento.
* **Un intervalo de mensajes** — abre el endpoint, ya que los modos en bloque actúan sobre un solo endpoint cada vez.

### Reproducción en bloque

Abre el endpoint desde **Developer → Webhooks**. Hay tres modos disponibles, cada uno de los cuales actúa únicamente sobre ese endpoint:

| Modo | Qué hace | Qué configuras |
| - | - | - |
| **Recover failed messages** | Vuelve a reproducir todos los mensajes de este endpoint que fallaron. | Un punto de inicio: **8 hours ago**, **Yesterday**, **3 days ago**, **Last week** o **2 weeks ago** |
| **Replay missing messages** | Vuelve a reproducir los mensajes que nunca se enviaron a este endpoint, por ejemplo, después de suscribirlo a un nuevo tipo de evento. | Los mismos puntos de inicio |
| **Bulk replay messages** | Vuelve a reproducir los mensajes que coinciden con los filtros seleccionados, incluidos los que ya se entregaron correctamente. | Límites **Since** y **Until**, establecidos de forma predeterminada en las últimas dos semanas, además de tipos de evento, canal o etiqueta opcionales |

<Steps>
  <Step title="Open More Actions">
    En el endpoint, abre **More actions** y selecciona uno de los tres modos anteriores.
  </Step>

  <Step title="Set the Range">
    Completa el intervalo que solicita el modo, tal como se indica en la tabla.
  </Step>

  <Step title="Start the Run">
    Haz clic en **Recover** o **Replay**, según el modo que hayas elegido.
  </Step>
</Steps>

Cada ejecución aparece en **Replay history**, en la pestaña **Overview** del endpoint, junto con su modo, intervalo de tiempo, estado y número de mensajes reenviados.

## Alertas por correo electrónico

El panel de webhooks no ofrece alertas por correo electrónico para las entregas fallidas. Para supervisar las entregas, ve a **Developer → Webhooks** y consulta las pestañas **Logs** y **Activity**.

## Implementar en plataformas cloud

Guías específicas de cada plataforma para implementar handlers de webhooks en proveedores cloud populares:

<CardGroup cols={2}>
  <Card title="Vercel" icon="triangle" href="/developer-resources/webhooks/examples/vercel-example">
    Implementa webhooks en Vercel con funciones serverless
  </Card>

  <Card title="Cloudflare Workers" icon="cloud" href="/developer-resources/webhooks/examples/cloudflare-example">
    Ejecuta webhooks en la red perimetral de Cloudflare
  </Card>

  <Card title="Supabase Edge Functions" icon="database" href="/developer-resources/webhooks/examples/supabase-example">
    Integra webhooks con Supabase
  </Card>

  <Card title="Netlify Functions" icon="circle-nodes" href="/developer-resources/webhooks/examples/netlify-example">
    Implementa webhooks como funciones serverless de Netlify
  </Card>
</CardGroup>

## Referencia de API relacionada

<CardGroup cols={2}>
  <Card title="Create Webhook" icon="code" href="/api-reference/webhooks/create-webhook">
    Crea y configura endpoints de webhook mediante programación
  </Card>

  <Card title="List Webhooks" icon="list" href="/api-reference/webhooks/list-webhooks">
    Recupera y gestiona tus endpoints de webhook
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.