> ## 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

> Reacciona a eventos de Bank Transfer en tiempo real con webhooks — notificaciones de completado, falla, chargeback y reconciliación sin polling.

Los webhooks permiten que tu sistema reaccione a los eventos de transferencia en tiempo real, sin polling. El plugin envía una notificación a tu endpoint cuando una transferencia se completa, falla o requiere atención.

## Eventos disponibles

***

Cada evento indica los tipos de transferencia a los que aplica (entre paréntesis), cuándo se activa y la acción recomendada.

### Ciclo de vida de la transferencia (TED OUT, P2P)

#### `transfer.initiated` (TED OUT)

* **Activación**: el plugin creó el registro de transferencia TED OUT después de confirmar la iniciación.
* **Acción**: actualiza el estado de la transferencia en tu sistema. Muestra "transferencia en curso" al cliente.

#### `transfer.processing_started` (TED OUT)

* **Activación**: la transferencia TED OUT entró en procesamiento (ruta de estado CREATED a PENDING a PROCESSING).
* **Acción**: muestra al cliente que la transferencia está en curso.

#### `transfer.rejected` (TED OUT)

* **Activación**: JD SPB rechazó la solicitud de transferencia antes de aceptarla (datos inválidos o violación de regla).
* **Acción**: notifica al cliente el rechazo. El plugin ya canceló la retención de fondos.

#### `transfer.completed` (P2P)

* **Activación**: la transferencia P2P se liquidó con éxito.
* **Acción**: notifica al cliente. Genera un recibo. Actualiza la visualización del saldo.

### Conciliación (TED OUT, TED IN)

#### `transfer.reconciliation_required`

* **Activación**: una transferencia con resultado desconocido pasó a conciliación.
* **Acción**: registra la transferencia como pendiente. No asumas éxito ni falla.

#### `transfer.reconciliation_resolved`

* **Activación**: la conciliación finalizó y la transferencia alcanzó un resultado definitivo.
* **Acción**: actualiza la transferencia a su estado final.

#### `transfer.reconciliation_exhausted`

* **Activación**: la conciliación se detuvo tras el número máximo de intentos.
* **Acción**: escala la transferencia para revisión manual de un operador.

#### `transfer.reconciliation_failed`

* **Activación**: un intento de conciliación encontró un error determinista, que falló la transferencia.
* **Acción**: trata la transferencia como fallida e investiga.

### Transferencias entrantes (TED IN)

#### `transfer_incoming.completed`

* **Activación**: el plugin recibió una TED entrante, encontró al destinatario y aplicó el crédito.
* **Acción**: notifica al destinatario que los fondos llegaron. Actualiza la visualización del saldo.

#### `transfer_incoming.chargeback`

* **Activación**: llegó un mensaje de contracargo para un TED IN completado (STR0010R2).
* **Acción**: congela el monto acreditado. Inicia una revisión con tu equipo de cumplimiento.

#### `transfer_incoming.undeliverable`

* **Activación**: el plugin no pudo acreditar una TED entrante (por ejemplo, no encontró la cuenta del destinatario).
* **Acción**: investiga la transferencia. El plugin puede devolverla al banco de origen.

### Devoluciones e iniciación

#### `transfer_outgoing.devolution_notified` (TED OUT)

* **Activación**: llegó una devolución para una transferencia saliente.
* **Acción**: concilia los fondos devueltos contra la transferencia original.

#### `payment_initiation.created` (TED OUT, P2P)

* **Activación**: el plugin creó una iniciación de pago (el paso previo a la transferencia).
* **Acción**: opcional. Registra las iniciaciones que esperan confirmación.

<Note>
  Para TED OUT, el plugin aún no emite `transfer.completed`. SPB confirma la finalización de TED OUT de forma asíncrona, y una versión futura agregará este evento. Hasta entonces, consulta el estado de TED OUT con el endpoint [Get Transfer](/es/reference/midaz/plugins/ted/retrieve-transfer) o el endpoint de conciliación.
</Note>

## Configurar webhooks

***

Los webhooks funcionan por tenant. Registras un destino de una de dos formas.

**API self-service (recomendada).** Registra uno o más endpoints HTTPS a través de la API de registro de webhooks. El servidor genera un `signingSecret` al crearlo y lo devuelve **una sola vez**. Guárdalo de forma segura. Úsalo para verificar la firma en cada evento entregado. También puedes listar, actualizar, deshabilitar y eliminar registros, rotar el secreto de firma y consultar los tipos de evento aceptados. El plugin deriva el tenant propietario del bearer token, nunca de un header de solicitud.

* [Crear un registro de webhook](/es/reference/midaz/plugins/ted/create-webhook) — `POST /v1/webhooks`
* [Listar registros de webhook](/es/reference/midaz/plugins/ted/list-webhooks) — `GET /v1/webhooks`
* [Obtener](/es/reference/midaz/plugins/ted/get-webhook), [actualizar](/es/reference/midaz/plugins/ted/update-webhook) y [eliminar](/es/reference/midaz/plugins/ted/delete-webhook) un registro
* [Rotar el secreto de firma](/es/reference/midaz/plugins/ted/rotate-webhook-signing-secret) — `POST /v1/webhooks/{webhookId}/signing-secret/rotate`
* [Listar tipos de evento soportados](/es/reference/midaz/plugins/ted/list-webhook-event-types) — `GET /v1/webhooks/event-types`

**Habilitar la entrega (operador/entorno).** Establece `WEBHOOK_ENABLED=true` para activar la entrega saliente. La entrega también requiere RabbitMQ y el outbox de streaming (`STREAMING_ENABLED=true`). Los destinos provienen de los registros anteriores. No existe una única variable de entorno de endpoint estático. Ajustas el comportamiento por entrega — timeout y máximo de reintentos — en runtime a través de systemplane, no por variables de entorno. Consulta [Configuración de Bank Transfer](/es/rails/ted/jd/ted-configuration).

## Estructura del payload

***

El plugin entrega cada evento como un POST HTTPS. El cuerpo de la solicitud es el payload del evento en JSON. El tipo de evento y la firma viajan en headers HTTP, no en el cuerpo.

| Header                | Valor                                                                                                                        |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `Content-Type`        | `application/json`.                                                                                                          |
| `X-Webhook-Event`     | El tipo de evento, por ejemplo `transfer.completed`.                                                                         |
| `X-Webhook-Timestamp` | Hora de entrega como timestamp Unix (segundos). La firma cubre este valor.                                                   |
| `X-Webhook-Signature` | Firma HMAC-SHA256 sobre el timestamp y el cuerpo, con la clave del `signingSecret` del registro. Formato: `v1,sha256=<hex>`. |

Los campos del cuerpo dependen del tipo de evento. Cada payload incluye `tenantId`, y los eventos con alcance de transferencia también incluyen `transferId`. Los montos son strings decimales en la moneda de la cuenta, no centavos (por ejemplo, `100.00`).

A continuación, un ejemplo de cuerpo para `transfer.completed` en una transferencia P2P:

```json theme={null}
{
  "transferId": "019c96a0-ab10-7cde-f1a2-0e1f2a3b4c5d",
  "initiationId": "019c96a0-9a01-7bcd-e0f1-2a3b4c5d6e7f",
  "tenantId": "019c96a0-0a98-7287-9a31-786e0809c769",
  "ledgerId": "019c96a0-1b20-7def-a1b2-c3d4e5f60718",
  "senderAccountId": "019c96a0-2c30-7ef0-b2c3-d4e5f6071829",
  "recipientAccountId": "019c96a0-3d40-7f01-c3d4-e5f60718293a",
  "midazTransactionId": "019c96a0-cd10-7eee-bbbb-3333bbbb4444",
  "confirmationNumber": "20260121001",
  "status": "COMPLETED",
  "transferType": "P2P",
  "amount": "100.00",
  "feeAmount": "0.00",
  "totalAmount": "100.00",
  "completedAt": "2026-01-21T17:35:00Z"
}
```

El payload de `transfer.completed` incluye los montos, las cuentas y el `midazTransactionId`. Para eventos con un payload más pequeño, o para leer el registro completo de la transferencia, recupera la transferencia desde [Get Transfer](/es/reference/midaz/plugins/ted/retrieve-transfer) con su `transferId`.

<Note>
  Los campos del payload difieren según el tipo de evento. Para leer todos los campos de una transferencia, usa el endpoint [Get Transfer](/es/reference/midaz/plugins/ted/retrieve-transfer).
</Note>

## Manejo de fallas de entrega

***

Tu endpoint debe responder con un estado 2xx dentro de 5 segundos (el valor predeterminado de `webhook.timeout_ms`). Si no lo hace, el plugin reintenta la entrega con retroceso exponencial y full jitter. Tras el primer intento, el plugin realiza hasta 3 intentos más (el valor predeterminado de `webhook.max_retries`), lo que da 4 intentos de entrega en total. La base del retroceso es 1 segundo y se duplica en cada intento. Se aplica full jitter a cada demora:

| Intento     | Demora antes de este intento |
| ----------- | ---------------------------- |
| 1 (inicial) | Inmediata                    |
| 2           | Aleatoria en `[0, 1000 ms]`  |
| 3           | Aleatoria en `[0, 2000 ms]`  |
| 4           | Aleatoria en `[0, 4000 ms]`  |

Después de que fallen todos los intentos (4 por defecto), el evento se mueve a una cola de mensajes no procesables (DLQ). Configura alertas en la DLQ para detectar fallas persistentes de entrega a tiempo. Ajusta `webhook.max_retries` a través de systemplane si tu endpoint necesita un presupuesto de reintentos más largo o más corto. El knob `webhook.retry_backoff_ms` controla el retroceso de reconexión al broker, no el cronograma de reintentos HTTP por entrega mostrado arriba.

Para una entrega confiable, sigue estas reglas:

* Responde dentro de 5 segundos.
* Usa HTTPS con un certificado válido.
* Devuelve 200 incluso para los eventos que ignores.
* Mueve el procesamiento pesado a una cola en segundo plano. Mantén el manejador de webhooks rápido.

## Idempotencia

***

<Note>
  Tu endpoint puede recibir el mismo evento más de una vez. Usa el `transferId` del cuerpo y el header `X-Webhook-Event` para deduplicar. Si ya procesaste esa combinación, devuelve 200 y no realices ninguna acción adicional.
</Note>

## Para desarrolladores

***

Para código de validación de firma (JavaScript, Python, Go), implementación de reintentos y la lista de verificación de integración completa, consulta la [guía para desarrolladores TED](/es/rails/ted/jd/ted-developer-guide).
