> ## 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 necesidad de polling. Cuando una transferencia se completa, falla o requiere atención, tu endpoint recibe una notificación automáticamente.

## 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, P2P)

* **Activación**: registro de transferencia creado 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, P2P)

* **Activación**: retención de transacción Midaz exitosa; la transferencia avanza hacia la finalización.
* **Acción**: muestra al cliente que la transferencia está siendo procesada.

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

* **Activación**: JD SPB retornó un rechazo 4xx (datos inválidos, violación de regla).
* **Acción**: notifica al cliente que la transferencia fue rechazada; los fondos ya están liberados.

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

* **Activación**: transferencia liquidada exitosamente.
* **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 fue marcada para conciliación.
* **Acción**: registra que la transferencia está pendiente de resolución; no asumas éxito ni falla.

#### `transfer.reconciliation_resolved`

* **Activación**: la conciliación se completó 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 rindió tras el número máximo de intentos.
* **Acción**: escala para revisión manual de un operador.

#### `transfer.reconciliation_failed`

* **Activación**: un intento de conciliación falló en sí mismo.
* **Acción**: monitorea; el worker reintentará en el próximo ciclo.

### Transferencias entrantes (TED IN)

#### `transfer_incoming.completed`

* **Activación**: TED entrante recibido, destinatario encontrado, crédito aplicado.
* **Acción**: notifica al destinatario que los fondos han llegado; actualiza la visualización del saldo.

#### `transfer_incoming.chargeback`

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

#### `transfer_incoming.undeliverable`

* **Activación**: el TED entrante no pudo acreditarse (p. ej., cuenta del destinatario no encontrada).
* **Acción**: investiga; la transferencia puede ser devuelta al banco de origen.

### Devoluciones e iniciación

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

* **Activación**: se notificó 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**: se creó una iniciación de pago (paso previo a la transferencia).
* **Acción**: opcional — registra las iniciaciones que esperan confirmación.

<Note>
  Para TED OUT, el evento `transfer.completed` aún no se emite. La finalización de TED OUT se confirma de forma asíncrona por SPB y será soportada en una versión futura. Hasta entonces, monitorea el estado de TED OUT a través del endpoint [Get Transfer](/es/reference/midaz/plugins/ted/retrieve-transfer) o el endpoint de conciliación.
</Note>

## Configurar webhooks

***

Los webhooks se configuran por tenant. Hay dos formas de registrar un destino.

**API self-service (recomendado).** Registra uno o más endpoints HTTPS a través de la API de registro de webhooks. Al crearse, el servidor genera un `signingSecret` y lo devuelve **una sola vez** — guárdalo de forma segura y ú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 tenant propietario de cada registro se deriva 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).** La entrega saliente se activa con `WEBHOOK_ENABLED=true`, que 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. El ajuste por entrega (timeout, máximo de reintentos) se gestiona en runtime vía systemplane, no por variables de entorno. Consulta [Configuración de Bank Transfer](/es/rails/ted/jd/ted-configuration).

## Estructura del payload

***

Todos los eventos webhook comparten el mismo envelope. Los campos del envelope son estables entre tipos de evento; el payload específico de cada evento vive dentro de `payload`.

| Campo           | Tipo                  | Notas                                                                                                   |
| --------------- | --------------------- | ------------------------------------------------------------------------------------------------------- |
| `eventId`       | string (UUID)         | Identificador único de esta emisión de evento. Úsalo para deduplicar entregas at-least-once en tu lado. |
| `version`       | string                | Versión del schema del envelope. Actualmente `v1`.                                                      |
| `type`          | string                | Tipo de evento, p. ej., `transfer.completed`.                                                           |
| `tenantId`      | string (UUID)         | Organización propietaria de la transferencia.                                                           |
| `transferId`    | string (UUID)         | Presente en eventos con alcance de transferencia; omitido en eventos con alcance de tenant.             |
| `correlationId` | string                | Correlaciona la cadena de eventos producida por una solicitud originaria.                               |
| `causationId`   | string                | Opcional. Id del evento que causó este (para flujos encadenados).                                       |
| `occurredAt`    | string (RFC3339, UTC) | Cuándo ocurrió el evento del lado del plugin.                                                           |
| `payload`       | object                | Campos específicos del evento. El schema depende de `type` (ve más abajo).                              |
| `metadata`      | object                | Mapa opcional string-a-string que transporta hints de tracing y enrutamiento.                           |

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

```json theme={null}
{
  "eventId": "019c96a0-ee10-7fff-aaaa-1111aaaa2222",
  "version": "v1",
  "type": "transfer.completed",
  "tenantId": "019c96a0-0a98-7287-9a31-786e0809c769",
  "transferId": "019c96a0-ab10-7cde-f1a2-0e1f2a3b4c5d",
  "correlationId": "019c96a0-aa10-7abc-d1e2-8c9d0e1f2a3b",
  "occurredAt": "2026-01-21T17:35:00Z",
  "payload": {
    "status": "COMPLETED",
    "transferType": "P2P",
    "midazTransactionId": "019c96a0-cd10-7eee-bbbb-3333bbbb4444",
    "confirmationNumber": "20260121001"
  },
  "metadata": {}
}
```

La forma de `payload` depende del tipo de evento. Para `transfer.completed`, los campos son `status`, `transferType`, `midazTransactionId` y `confirmationNumber` (cada uno emitido solo cuando está definido). Para obtener montos, tarifas, datos del destinatario o marcas de tiempo, recupera la transferencia mediante [Get Transfer](/es/reference/midaz/plugins/ted/retrieve-transfer) usando el `transferId` del envelope.

<Note>
  Consulta la Referencia de API para los esquemas completos de payload de cada tipo de evento.
</Note>

## Manejo de fallas de entrega

***

Si tu endpoint no responde con un estado 2xx dentro de 5 segundos (`WEBHOOK_TIMEOUT_MS=5000`), el evento se reintenta automáticamente con retroceso exponencial y full jitter. Tras el intento inicial, el plugin realiza hasta `WEBHOOK_MAX_RETRIES` reintentos (predeterminado `3`) — hasta **4 intentos de entrega** en total. La base del retroceso es **1 segundo**, duplicada en cada reintento, con full jitter aplicado 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 antes de que afecten tus operaciones. Ajusta `WEBHOOK_MAX_RETRIES` si tu endpoint necesita un presupuesto de reintentos más largo o más corto. (`WEBHOOK_RETRY_BACKOFF_MS` controla el retroceso de reconexión al broker, no el cronograma de reintentos HTTP por entrega mostrado arriba.)

Para garantizar una entrega confiable: responde dentro de 5 segundos, usa HTTPS con un certificado válido, y devuelve 200 incluso para los eventos que decidas ignorar. Delega cualquier procesamiento pesado a una cola en segundo plano — mantén tu manejador de webhooks ágil.

## Idempotencia

***

<Note>
  Tu endpoint puede recibir el mismo evento más de una vez. Usa el `transferId` (y el nombre del evento) 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).
