# Webhooks de Pago (México)

Un **webhook** es una devolución de llamada web que Belvo utiliza para enviar notificaciones sobre un enlace específico. Necesitarás configurar webhooks para poder usar las APIs de Belvo.

Servicios de Webhook
Puedes usar servicios como Webhook.site o Pipedream para crear endpoints temporales para pruebas.

## Configurando tus webhooks

Para configurar tu URL de webhook:

1. Inicia sesión en tu Portal de Débito Directo. (Inicio de sesión Sandbox | Inicio de sesión Producción)
2. Ve a Desarrolladores -> Webhooks. (Webhooks Sandbox | Webhooks Producción)
3. Ingresa tu URL.
4. Haz clic en **Set**.


✅ Tu URL de webhook se ha agregado exitosamente.

## Carga Útil del Webhook

Ejemplo de Carga Útil del Webhook (Éxito)
```json Ejemplo de Carga Útil del Webhook (Éxito)
{
  "eventType": "payment_request_update",
  "eventCode": "payment_request_successful",
  "datetime": "2022-01-01T12:34:56.789Z",
  "details": {
    "id": "3118128a-6792-4b06-bd61-4acf6f6ad6b5",
    "reference": "your_reference_here",
    "status": "successful",
    "amount": 100.5,
    "failedReason": null,
    "failedMessage": null
  }
}
```

Ejemplo de Carga Útil del Webhook (Fallo)
```json Ejemplo de Carga Útil del Webhook (Fallo)
{
  "eventType": "payment_request_update",
  "eventCode": "payment_request_failed",
  "datetime": "2022-01-01T12:34:56.789Z",
  "details": {
    "id": "3118128a-6792-4b06-bd61-4acf6f6ad6b5",
    "reference": "your_reference_here",
    "status": "failed",
    "amount": 100.5,
    "failedReason": "01",
    "failedMessage": "Cuenta inexistente"
  }
}
```

Ejemplo de Carga Útil del Webhook (Validación de Centavo Exitosa)
```json Ejemplo de Carga Útil del Webhook (Validación de Centavo Exitosa)
{
  "eventType": "payment_method_update",
  "eventCode": "payment_method_registration_successful",
  "datetime": "2022-01-01T12:34:56.789Z",
  "details": {
    "id": "3118128a-6792-4b06-bd61-4acf6f6ad6b5",
    "reference": "your_reference_here",
    "status": "active",
    "failedReason": null,
    "failedMessage": null
  }
}
```

Ejemplo de Carga Útil del Webhook (Fallo de Validación de Centavo)
```json Ejemplo de Carga Útil del Webhook (Fallo de Validación de Centavo)
{
  "eventType": "payment_method_update",
  "eventCode": "payment_method_registration_failed",
  "datetime": "2022-01-01T12:34:56.789Z",
  "details": {
    "id": "3118128a-6792-4b06-bd61-4acf6f6ad6b5",
    "reference": "your_reference_here",
    "status": "error",
    "failedReason": "account_validation_failed",
    "failedMessage": "Account owner validation was not successful"
  }
}
```

Ejemplo de Carga Útil del Webhook (Cliente)
```json Ejemplo de Carga Útil del Webhook (Cliente)
{
  "eventType": "customer_update",
  "eventCode": "customer_blocked",
  "datetime": "2022-01-01T12:34:56.789Z",
  "details": {
    "documentNumber": "RFC/CURP of Customer"
  }
}
```

Ejemplo de Carga Útil del Webhook (Consentimiento)
```json Ejemplo de Carga Útil del Webhook (Consentimiento)
{
  "eventType": "consent_update",
  "eventCode": "consent_submitted",
  "datetime": "2025-10-30T12:34:56.789Z",
  "details": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "paymentMethodId": "660e8400-e29b-41d4-a716-446655440000",
    "status": "submitted"
  }
}
```

Ejemplo de Carga Útil del Webhook (Retiro)
```json Ejemplo de Carga Útil del Webhook (Retiro)
{
  "eventType": "withdrawal_update",
  "eventCode": "withdrawal_created",
  "datetime": "2022-01-01T12:34:56.789Z",
  "details": {
    "id": "3118128a-6792-4b06-bd61-4acf6f6ad6b5",
    "fromDatetime": "2022-01-01T00:00:00.000Z",
    "toDatetime": "2022-01-01T23:59:59.999Z",
    "extra": {}
  }
}
```

Resultados de Validación de Centavo
El resultado de una validación de centavo se entrega a través de los webhooks de registro de métodos de pago. Una validación exitosa envía `payment_method_registration_successful` (el método de pago se vuelve `active`), mientras que una validación fallida envía `payment_method_registration_failed` con un `failedReason` de `account_validation_failed`. Para más información, consulta nuestra guía dedicada de Validación de Centavo.

| Parámetro  | Tipo | Descripción |
|  --- | --- | --- |
| `eventType` | string | El tipo de evento del recurso de la API. Puede ser uno de: `consent_update`, `customer_update`, `payment_method_update`, `payment_request_update`, o `withdrawal_update`. |
| `eventCode` | string | El código del evento del webhook. Para detalles sobre los posibles valores, consulta la sección de Códigos de Evento del Webhook a continuación. |
| `datetime` | string | La marca de tiempo ISO-8601 cuando se envió el evento. |
| `details` | object | Un objeto que contiene datos específicos sobre el evento. |
| `details.id` | string | El ID de Belvo del recurso de la API (Cliente, Método de Pago, Solicitud de Pago o Retiro) al que está relacionado el evento. |
| `details.reference` | string | Si proporcionaste una `reference` al crear el recurso, una descripción opcional del objeto. |
| `details.status` | string | El estado del recurso. |
| `details.amount` | number | El monto de la solicitud de pago. Este campo está presente para todos los códigos de evento de payment_request. |
| `details.failedReason`
 | string
 | Si el estado es `failed` o `canceled`, este campo contiene un código de fallo. Este campo es `null` si el `status` no es `failed` o `canceled`.
Para detalles sobre el `failedReason` y `failedMessage` esperados (incluyendo la lista de posibles valores), consulta nuestra guía de Errores Bancarios de Débito Directo.
 |
| `details.failedMessage`
 | string
 | Si el estado es `failed` o `canceled`, este campo contiene una descripción del fallo. Este campo es `null` si el `status` no es `failed` o `canceled`.
Para detalles sobre el `failedReason` y `failedMessage` esperados (incluyendo la lista de posibles valores), consulta nuestra guía de Errores Bancarios de Débito Directo.
 |
| `details.documentNumber` | string | Si el evento está relacionado con un cliente, este campo contiene el RFC o CURP del cliente relacionado con el método de pago por débito directo. **Este campo solo está disponible para eventos relacionados con clientes.** |
| `details.paymentMethodId` | string | Si el evento está relacionado con un consentimiento, este campo contiene el ID del método de pago asociado. **Este campo solo está disponible para eventos relacionados con consentimientos.** |
| `details.fromDatetime` | string | Si el evento está relacionado con un retiro, este campo contiene la marca de tiempo ISO-8601 del inicio del período de liquidación. **Este campo solo está disponible para eventos relacionados con retiros.** |
| `details.toDatetime` | string | Si el evento está relacionado con un retiro, este campo contiene la marca de tiempo ISO-8601 del final del período de liquidación. **Este campo solo está disponible para eventos relacionados con retiros.** |
| `details.extra` | object | Si el evento está relacionado con un retiro, este campo contiene información adicional sobre el retiro. **Este campo solo está disponible para eventos relacionados con retiros.** |


Para obtener información sobre cargas útiles específicas para un recurso de API y código de webhook determinado, simplemente haz clic en el **Código de Evento** del webhook en la tabla a continuación.

## Códigos de Eventos de Webhook

| Recurso | Tipo de Evento  | Código de Evento  | Se envía cuando... |
|  --- | --- | --- | --- |
| Clientes | `customer_update` | `customer_blocked` | el cliente relacionado con el método de pago por débito directo fue bloqueado debido a actividad sospechosa. Este webhook se envía globalmente a todos los comerciantes, incluso si no tienen registrado al cliente bloqueado, ya que la lista de bloqueos se comparte entre todos los comerciantes. |
| Clientes | `customer_update` | `customer_unblocked` | el cliente relacionado con el método de pago por débito directo fue desbloqueado tras la revisión por las partes relevantes. |
| Consentimientos | `consent_update` | `consent_submitted` | se han cargado todos los documentos requeridos para el consentimiento. |
| Consentimientos | `consent_update` | `consent_confirmed` | el consentimiento ha sido aprobado y ahora está activo. |
| Consentimientos | `consent_update` | `consent_incomplete_information` | faltan documentos o son inválidos para el consentimiento. |
| Consentimientos | `consent_update` | `consent_rejected` | el consentimiento ha sido denegado. |
| Métodos de Pago | `payment_method_update` | `payment_method_registration_successful` | el registro del método de pago por débito directo fue exitoso. |
| Métodos de Pago | `payment_method_update` | `payment_method_registration_failed` | el registro del método de pago por débito directo falló. |
| Métodos de Pago | `payment_method_update` | `payment_method_registration_canceled` | el registro del débito directo fue cancelado (usualmente por el propietario). |
| Solicitudes de Pago | `payment_request_update` | `payment_request_successful` | el pago fue exitoso y recibimos confirmación del proveedor de infraestructura de pago. |
| Solicitudes de Pago | `payment_request_update` | `payment_request_failed` | se reporta un error por parte del proveedor de infraestructura de pago. |
| Solicitudes de Pago | `payment_request_update` | `payment_request_chargeback` | se ha realizado un contracargo por parte de tu cliente. |
| Retiros | `withdrawal_update` | `withdrawal_created` | se ha creado un retiro y los fondos están siendo liquidados al comerciante. |


Notificaciones Globales de Bloqueo de Clientes
Cuando un cliente es bloqueado debido a un contracargo, **todos los comerciantes reciben el webhook `customer_blocked`**, independientemente de si tienen registrado a ese cliente. Esto se debe a que Belvo mantiene una lista de bloqueos global compartida entre todos los comerciantes para proteger a todo el ecosistema de actividades fraudulentas.

La carga útil del webhook incluye el `documentNumber` (RFC o CURP) del cliente bloqueado para que puedas verificar si el cliente existe en tu sistema y tomar las acciones apropiadas.

El webhook `customer_blocked` se envía solo una vez a cada comerciante (en otras palabras, si ya recibiste uno y ocurre un nuevo contracargo para el mismo cliente pero para otro comerciante, no recibirás otro webhook para ese cliente).

Notas de Estado de Webhook de Consentimiento
El sistema envía notificaciones de webhook cada vez que cambia el estado de un consentimiento para permitir el seguimiento en tiempo real del ciclo de vida del consentimiento. No se envía un webhook para el estado inicial `awaiting_information`.

Si está configurado, los webhooks de consentimiento incluyen un encabezado `Authorization` con el secreto del webhook del comerciante para una verificación segura.

## Mejores Prácticas

Cuando recibas un webhook de Belvo, asegúrate de responder con un código de estado 2XX (por ejemplo, un `200`). Si el sistema de Belvo no recibe una respuesta `200` de tu servidor, automáticamente intentaremos reenviar la solicitud. Para más detalles, consulta nuestra sección de Política de reintento.

## Política de reintento

Cuando Belvo no recibe una respuesta `2XX` de tu servidor, intentamos enviar el webhook nuevamente cada 60 minutos hasta un máximo de 3 intentos.

Por ejemplo, si el primer intento (inicial) falla, nuestro sistema espera 60 minutos antes de intentar de nuevo y continuará con este patrón hasta que reciba una respuesta exitosa o alcance el máximo de 2 reintentos.