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

# Webhooks

> Cómo configurar y gestionar webhooks para operaciones de Pix Indirecto a través de BTG, con firma, reintentos y ciclo de vida de entrega documentados.

Los webhooks son el mecanismo principal que el **Plugin de Pix Indirecto (BTG)** usa para notificarte en tiempo real sobre eventos relacionados con Pix.

No dependes de respuestas síncronas. En su lugar, recibes **callbacks asíncronos basados en eventos** cuando ocurren cambios relevantes en las operaciones de Pix: transferencias, reembolsos, reclamos de claves o eventos MED.

Este modelo te da:

* Actualizaciones casi en tiempo real
* Integraciones desacopladas
* Conciliación confiable y trazabilidad operativa

<Warning>
  Estos webhooks aplican solo al **modelo de Pix Indirecto a través de BTG**.

  Los webhooks de Pix Directo pueden diferir según el modelo de conectividad. Una página aparte los documenta.
</Warning>

# Requisitos previos

***

Antes de configurar los webhooks, asegúrate de tener:

* El Plugin de Pix Indirecto configurado y en funcionamiento (consulta [Cómo funciona la participación indirecta](/es/rails/pix/pix-overview))
* Un endpoint HTTPS listo para recibir solicitudes de webhook
* Conocimiento básico del ciclo de vida de los eventos de Pix y de los flujos de transacciones

# Por qué los webhooks son importantes en Pix

***

Pix es un sistema asíncrono y multiparte.

Una solicitud de API puede tener éxito antes de que la transacción alcance su **estado final**. El sistema confirma ese estado más tarde, después de la liquidación y del reconocimiento de la contraparte.

Los webhooks permiten que tu sistema:

* Dé seguimiento al **estado autoritativo de la transacción**
* Reaccione a **reembolsos, reversiones y eventos MED**
* Mantenga la **consistencia del libro mayor y operativa**
* Reduzca el polling y la carga operativa

# Tipos de eventos

***

Recibes eventos agrupados por **flujo** y **entidad**, alineados con los dominios de BACEN (Banco Central do Brasil).

| Flujo    | Entidad                | Descripción                                                                                 |
| -------- | ---------------------- | ------------------------------------------------------------------------------------------- |
| DICT     | CLAIM                  | Eventos de portabilidad de clave Pix y reclamo de titularidad                               |
| DICT     | INFRACTION\_REPORT     | Reportes de infracción de MED (Mecanismo Especial de Devolução) y ciclo de vida de disputas |
| DICT     | REFUND                 | Eventos de solicitud de reembolso de MED                                                    |
| DICT     | FUNDS\_RECOVERY        | Cambios de estado de la entidad Funds Recovery de MED 2.0 (respaldados en base de datos)    |
| DICT     | FUNDS\_RECOVERY\_EVENT | Eventos del ciclo de vida de Funds Recovery de MED 2.0 (pass-through)                       |
| TRANSFER | CASHIN                 | Actualizaciones de estado de pagos Pix entrantes                                            |
| TRANSFER | CASHOUT                | Actualizaciones de estado de pagos Pix salientes                                            |
| REFUND   | CASHIN                 | Actualizaciones de estado de reembolsos Pix entrantes                                       |
| REFUND   | CASHOUT                | Actualizaciones de estado de reembolsos Pix salientes                                       |

Cada evento refleja una **transición de estado** en el ecosistema de Pix. Trata cada evento como la fuente de verdad.

<Note>
  Las dos entidades de **MED 2.0** se comportan de forma diferente. El plugin emite `FUNDS_RECOVERY` después de actualizar su registro local. `FUNDS_RECOVERY_EVENT` es un pass-through de los eventos del ciclo de vida de BTG sin actualización en base de datos. Consulta [MED 2.0 — Funds Recovery](/es/rails/pix/btg/indirect-pix-med-2-funds-recovery) para ver el flujo completo.
</Note>

<Note>
  **DICT** (Diretório de Identificadores de Contas Transacionais) es el directorio de BACEN que gestiona las claves Pix y operaciones relacionadas como reclamos, infracciones y reembolsos.
</Note>

# Configuración de webhooks

***

Para habilitar los webhooks, configura las **URLs de destino** y selecciona qué tipos de eventos recibe tu sistema.

## Variables de entorno

***

Puedes configurar los endpoints de webhook a nivel de **entidad**, **flujo** o **global**.

| Flujo    | Entidad            | Variable de URL a nivel de entidad   |
| -------- | ------------------ | ------------------------------------ |
| DICT     | CLAIM              | `WEBHOOK_DICT_CLAIM_URL`             |
| DICT     | INFRACTION\_REPORT | `WEBHOOK_DICT_INFRACTION_REPORT_URL` |
| DICT     | REFUND             | `WEBHOOK_DICT_REFUND_URL`            |
| TRANSFER | CASHIN             | `WEBHOOK_TRANSFER_CASHIN_URL`        |
| TRANSFER | CASHOUT            | `WEBHOOK_TRANSFER_CASHOUT_URL`       |
| REFUND   | CASHIN             | `WEBHOOK_REFUND_CASHIN_URL`          |
| REFUND   | CASHOUT            | `WEBHOOK_REFUND_CASHOUT_URL`         |

Cada flujo también tiene una **URL a nivel de flujo** para todas sus entidades. El plugin la usa cuando no existe una URL a nivel de entidad: `WEBHOOK_DICT_URL`, `WEBHOOK_TRANSFER_URL` y `WEBHOOK_REFUND_URL`.

## Prioridad de resolución de URL

***

Cuando configuras múltiples URLs, el plugin las resuelve en este orden:

1. **URL a nivel de entidad**

   Ejemplo: `WEBHOOK_DICT_CLAIM_URL`

2. **URL a nivel de flujo**

   Ejemplo: `WEBHOOK_DICT_URL`

3. **URL por defecto**

   `WEBHOOK_DEFAULT_URL`

Esto te da un control de enrutamiento granular y sin infraestructura duplicada.

# Formato de la solicitud

***

## Encabezados

***

Cada solicitud de webhook incluye encabezados estandarizados para trazabilidad y seguridad.

| Encabezado        | Descripción                                       |
| ----------------- | ------------------------------------------------- |
| `Content-Type`    | `application/json`                                |
| `X-Request-ID`    | Identificador único de la solicitud               |
| `X-Entity-Type`   | Entidad del evento (p. ej. `INFRACTION_REPORT`)   |
| `X-Flow-Type`     | Dominio de origen (p. ej. `DICT`)                 |
| `Idempotency-Key` | Identificador único del evento para deduplicación |

## Estructura del cuerpo

***

```json theme={null}
{
  "entityType": "INFRACTION_REPORT",
  "flowType": "DICT",
  "payload": {
    ...
  }
}
```

| Campo        | Descripción                  |
| ------------ | ---------------------------- |
| `entityType` | Entidad del evento           |
| `flowType`   | Dominio de Pix               |
| `payload`    | Datos específicos del evento |

El esquema del payload varía según el tipo de evento, pero siempre representa un **cambio de estado**.

# Respuestas y comportamiento de reintentos

***

## Respuesta esperada

***

Tu endpoint debe devolver un estado **HTTP 2xx** para confirmar la entrega exitosa.

| Respuesta | Resultado                   |
| --------- | --------------------------- |
| 2xx       | Entregado con éxito         |
| No-2xx    | Reintentado automáticamente |

## Estrategia de reintentos

***

El plugin reintenta las entregas fallidas automáticamente con **backoff exponencial**:

| Intento | Retraso    |
| ------- | ---------- |
| 1       | 1 segundo  |
| 2       | 2 segundos |
| 3       | 4 segundos |

**Valores por defecto**

* Máximo de reintentos: 3
* Tiempo de espera por solicitud: 30 segundos

Después de que todos los reintentos fallan, el plugin mueve el evento a una **cola de mensajes fallidos** para seguimiento operativo.

### Configuración personalizada de reintentos

Puedes personalizar los reintentos y los tiempos de espera por evento:

```bash theme={null}
WEBHOOK_DICT_INFRACTION_REPORT_MAX_RETRIES=5
WEBHOOK_DICT_INFRACTION_REPORT_REQUEST_TIMEOUT=60s
```

## Protección con circuit breaker

***

Un **circuit breaker** protege la entrega de webhooks y previene fallos en cascada.

Cuando el Plugin de Pix detecta **fallos repetidos de entrega** (normalmente respuestas `5xx` consecutivas o tiempos de espera agotados), **pausa temporalmente las llamadas de webhook** al endpoint afectado.

Después de un período de enfriamiento configurable, el sistema realiza **intentos de reintento controlados** para verificar si el endpoint se ha recuperado.

Cuando el endpoint vuelve a devolver respuestas exitosas, el plugin reanuda la entrega normal automáticamente.

Este mecanismo te da:

* Protección contra endpoints sobrecargados o inestables
* Recuperación elegante sin intervención manual
* Mayor estabilidad general del sistema en entornos de producción

<Note>
  El circuit breaker funciona junto con los reintentos y el backoff exponencial. Agrega una capa de seguridad adicional para la entrega de webhooks.
</Note>

## Errores de transporte y eventos huérfanos

***

Cuando el plugin recibe un webhook de reembolso, busca la transferencia original a lo largo de la cadena cash-in → cash-out. Si ninguna fuente local coincide, el plugin persiste el reembolso como un **registro huérfano** para la auditabilidad de BACEN. No descarta el reembolso, de modo que el registro permanece visible para conciliación y seguimiento. Si una búsqueda de fuente falla en la capa de transporte, el plugin omite esa fuente y continúa. Cuando ninguna fuente coincide — por una ausencia limpia o un error de transporte descartado — el plugin registra el reembolso como huérfano. El plugin solo aborta cuando el puente de búsqueda de transferencias no está configurado.

`originalEndToEndId` es la clave canónica para todas las búsquedas de reembolso. El plugin resuelve los reembolsos desde ambas direcciones, cash-in → refund y cash-out → refund, con este campo. Indexa siempre los reembolsos por `originalEndToEndId` (el ID de extremo a extremo de la transferencia original), no por una única ruta de búsqueda específica de dirección.

# Reportes de transacciones internas (intra-PSP)

***

El plugin liquida las transferencias intra-PSP (P2P) internamente. Nunca llegan a BTG para su liquidación, pero el plugin aún las reporta a BACEN a través de la abstracción **TRCK002**. BTG confirma el estado del reporte mediante un webhook **CAMT025** que lleva la entidad `PixInternalTransactionsReport`.

| Campo                            | Descripción                                                    |
| -------------------------------- | -------------------------------------------------------------- |
| `pactualId`                      | Identificador del reporte asignado por BTG                     |
| `clientRequestId`                | Tu clave de idempotencia, enviada durante el envío del reporte |
| `entity`                         | Siempre `PixInternalTransactionsReport`                        |
| `status`                         | `PROCESSING`, `CONFIRMED` o `ERROR`                            |
| `errorCode` / `errorDescription` | Se completa cuando `status = ERROR`                            |

El plugin actualiza el estado del reporte cuando el webhook de reporte CAMT025 confirma o falla. Los webhooks salientes se emiten antes, cuando la transferencia intra-PSP se liquida: `cashin.completed` para el lado de cash-in y `cashout.completed` o `cashout.failed` para el lado de cash-out. Para ver el flujo interno completo, consulta [Transferencias intra-PSP](/es/rails/pix/btg/indirect-pix-intra-psp).

# Buenas prácticas

***

| Práctica                       | Por qué es importante                                                                                            |
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| **Ignora campos desconocidos** | Mantente compatible hacia adelante a medida que se agregan nuevos campos                                         |
| **Procesamiento idempotente**  | Usa `Idempotency-Key` para evitar procesar duplicados                                                            |
| **Reconocimiento rápido**      | Devuelve `202 Accepted` y procesa de forma asíncrona                                                             |
| **Procesamiento asíncrono**    | Evita bloquear el hilo del webhook                                                                               |
| **Gestiona la compresión**     | Los payloads >1KB se comprimen con gzip. Verifica el encabezado `Content-Encoding` y descomprime en consecuencia |

# Ejemplos de eventos

***

A continuación se muestran ejemplos representativos de los payloads de webhook que recibes del Plugin de Pix Indirecto. Expande cada entrada para ver su payload.

<AccordionGroup>
  <Accordion title="Reclamo DICT">
    Eventos del ciclo de vida de titularidad o portabilidad. Úsalos para hacer seguimiento de las disputas de clave Pix entre instituciones.

    ```json theme={null}
    {
      "entityType": "CLAIM",
      "flowType": "DICT",
      "payload": {
        "id": "claim-7f8a9b2c-1234-5678-abcd-ef0123456789",
        "key": "+5511999998888",
        "keyType": "PHONE",
        "claimType": "PORTABILITY",
        "claimer": {
          "ispb": "12345678",
          "name": "Banco Exemplo S.A."
        },
        "donor": {
          "ispb": "87654321",
          "name": "Outra Instituição S.A."
        },
        "status": "CONFIRMED",
        "createdAt": "2024-01-15T10:30:00Z",
        "updatedAt": "2024-01-15T14:45:00Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Reporte de infracción DICT (MED)">
    Eventos de señalización de disputas y fraude alineados con las reglas de MED de BACEN.

    ```json theme={null}
    {
      "entityType": "INFRACTION_REPORT",
      "flowType": "DICT",
      "payload": {
        "id": "infraction-3e4f5a6b-7890-1234-cdef-567890abcdef",
        "endToEndId": "E12345678202401151030abcdefghij12",
        "infractionType": "FRAUD",
        "reportedBy": {
          "ispb": "12345678",
          "name": "Banco Exemplo S.A."
        },
        "reportedAgainst": {
          "ispb": "87654321",
          "name": "Outra Instituição S.A."
        },
        "status": "OPEN",
        "analysisResult": null,
        "createdAt": "2024-01-15T10:30:00Z",
        "updatedAt": "2024-01-15T10:30:00Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Reembolso DICT (MED)">
    Solicitudes y decisiones de reembolso relacionadas con casos de MED.

    ```json theme={null}
    {
      "entityType": "REFUND",
      "flowType": "DICT",
      "payload": {
        "id": "refund-9a8b7c6d-5432-1098-fedc-ba0987654321",
        "endToEndId": "E12345678202401151030abcdefghij12",
        "infractionId": "infraction-3e4f5a6b-7890-1234-cdef-567890abcdef",
        "refundAmount": 150.00,
        "refundReason": "FRAUD",
        "status": "REQUESTED",
        "requestedBy": {
          "ispb": "12345678",
          "name": "Banco Exemplo S.A."
        },
        "createdAt": "2024-01-16T09:00:00Z",
        "updatedAt": "2024-01-16T09:00:00Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Funds recovery DICT (MED 2.0)">
    Cambios de estado de la entidad Funds Recovery. El plugin actualiza su registro local antes de reenviar la entidad completa.

    ```json theme={null}
    {
      "entityType": "FUNDS_RECOVERY",
      "flowType": "DICT",
      "payload": {
        "id": "91d65e98-97c0-4b0f-b577-73625da1f9fc",
        "externalId": "ca1b9c01-ff9e-4a58-90ab-d31512e15ce0",
        "accountId": "01989f9e-6508-79f8-9540-835be49fbd0d",
        "status": "CREATED",
        "rootTransactionId": "E9999901012341234123412345678900",
        "situationType": "SCAM",
        "reporterParticipant": "99999010",
        "contactInformation": {},
        "reportDetails": "Details to help receiving participants",
        "createdAt": "2020-01-17T10:00:00.000Z",
        "updatedAt": "2020-01-17T10:00:00.000Z"
      }
    }
    ```

    Los eventos del ciclo de vida llegan como `entityType: FUNDS_RECOVERY_EVENT` (pass-through, sin actualización en base de datos), con valores de `event` como `FUNDS_RECOVERY_ANALYSED` y `FUNDS_RECOVERY_COMPLETED`.
  </Accordion>

  <Accordion title="Cash-in y cash-out de transferencia">
    Eventos de transferencias Pix entrantes y salientes.

    **Cash-in (transferencia entrante):**

    ```json theme={null}
    {
      "entityType": "CASHIN",
      "flowType": "TRANSFER",
      "payload": {
        "id": "transfer-1a2b3c4d-5678-90ab-cdef-1234567890ab",
        "endToEndId": "E12345678202401151030abcdefghij12",
        "amount": 250.00,
        "payer": {
          "ispb": "87654321",
          "name": "João Silva",
          "cpfCnpj": "12345678901"
        },
        "payee": {
          "ispb": "12345678",
          "name": "Maria Santos",
          "cpfCnpj": "98765432100",
          "accountNumber": "12345-6"
        },
        "status": "SETTLED",
        "createdAt": "2024-01-15T10:30:00Z",
        "settledAt": "2024-01-15T10:30:05Z"
      }
    }
    ```

    **Cash-out (transferencia saliente):**

    ```json theme={null}
    {
      "entityType": "CASHOUT",
      "flowType": "TRANSFER",
      "payload": {
        "id": "transfer-2b3c4d5e-6789-01bc-def0-2345678901bc",
        "endToEndId": "E87654321202401151045zyxwvutsrqp98",
        "amount": 500.00,
        "payer": {
          "ispb": "12345678",
          "name": "Maria Santos",
          "cpfCnpj": "98765432100",
          "accountNumber": "12345-6"
        },
        "payee": {
          "ispb": "87654321",
          "name": "Empresa ABC Ltda",
          "cpfCnpj": "12345678000199"
        },
        "status": "SETTLED",
        "createdAt": "2024-01-15T10:45:00Z",
        "settledAt": "2024-01-15T10:45:03Z"
      }
    }
    ```
  </Accordion>

  <Accordion title="Cash-in y cash-out de reembolso">
    Eventos de liquidación de reembolso para transacciones Pix.

    **Cash-in de reembolso (recibir un reembolso):**

    ```json theme={null}
    {
      "entityType": "CASHIN",
      "flowType": "REFUND",
      "payload": {
        "id": "refund-4d5e6f7g-8901-23cd-ef01-4567890123cd",
        "originalEndToEndId": "E87654321202401151045zyxwvutsrqp98",
        "refundEndToEndId": "D12345678202401161000refund123456",
        "amount": 500.00,
        "reason": "CUSTOMER_REQUEST",
        "status": "SETTLED",
        "createdAt": "2024-01-16T10:00:00Z",
        "settledAt": "2024-01-16T10:00:02Z"
      }
    }
    ```

    **Cash-out de reembolso (enviar un reembolso):**

    ```json theme={null}
    {
      "entityType": "CASHOUT",
      "flowType": "REFUND",
      "payload": {
        "id": "refund-5e6f7g8h-9012-34de-f012-5678901234de",
        "originalEndToEndId": "E12345678202401151030abcdefghij12",
        "refundEndToEndId": "D87654321202401161015refund789012",
        "amount": 250.00,
        "reason": "OPERATIONAL_FLAW",
        "status": "SETTLED",
        "createdAt": "2024-01-16T10:15:00Z",
        "settledAt": "2024-01-16T10:15:04Z"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

# Conclusión clave

***

Los webhooks **no son opcionales** en las operaciones de Pix Indirecto.

Son el **canal autoritativo** para el estado de las transacciones, los reembolsos y la gestión de disputas.

Una implementación correcta de webhooks te da:

* Conciliación precisa
* Cumplimiento normativo
* Resiliencia operativa
* Experiencia del cliente predecible

Para entornos de producción, diseña siempre los consumidores de webhooks como **sistemas idempotentes, asíncronos y observables**.

# Próximos pasos

***

Ahora que entiendes cómo funcionan los webhooks en Pix Indirecto, explora estos temas relacionados:

* [Dominios principales de Pix: transferencias](/es/rails/pix/main-domains-transactions) - Análisis detallado de las operaciones de transferencia
* [Dominios principales de Pix: DICT](/es/rails/pix/main-domains-dict) - Comprensión de las operaciones de DICT y la gestión de claves
* [Dominios principales de Pix: MED](/es/rails/pix/main-domains-med) - Gestión de disputas y reembolsos de MED
* [MED 2.0 — Funds Recovery](/es/rails/pix/btg/indirect-pix-med-2-funds-recovery) - Recuperación de fondos por fraude entre cuentas y sus webhooks
* [Transferencias intra-PSP](/es/rails/pix/btg/indirect-pix-intra-psp) - Liquidación P2P interna y reportes TRCK002
* [Referencia de API](/es/reference/midaz/plugins/indirect-pix/create-entry) — Documentación completa de la API para operaciones de DICT, Reclamos, Transacciones, Códigos QR y MED
