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

# Eventos de TED JD

> CloudEvents que emite el plugin Bank Transfer para TED OUT, TED IN, P2P, TED entre cores, devoluciones y conciliación.

El plugin Bank Transfer emite 21 hechos de negocio JSON como CloudEvents 1.0 en modo binario de contenido sobre Kafka. Los mismos hechos alimentan sus [webhooks](https://docs.lerian.studio/es/interfaces/ted-jd/ted-webhooks.md).

## Contrato de transporte

| Campo | Valor |
| - | - |
| `ce-source` | `plugin-br-bank-transfer` |
| Tópico | `lerian.streaming.plugin-br-bank-transfer` |
| `ce-type` | `studio.lerian.plugin-br-bank-transfer.<event-key>` |
| Versión del schema | Por evento, en el catálogo de abajo |
| Content type | `application/json` |
| `ce-subject` | El id de la transferencia. `payment_initiation.created` lleva el id de la iniciación, y `transfer_incoming.undeliverable` lleva su `jdIncomingMessageId` |
| `ce-tenantid` | Tu tenant, en el modo multi-tenant |
| Entrega | Por el outbox de PostgreSQL. El relay del outbox es el único publisher del broker |
| Manifiesto en runtime | `GET /v1/streaming/manifest` |

Define `STREAMING_ENABLED=true` y las [variables de streaming](https://docs.lerian.studio/es/interfaces/ted-jd/ted-environment-variables.md#streaming-outbox). Con el streaming desactivado, el plugin descarta los eventos. Si defines `STREAMING_CLOUDEVENTS_SOURCE`, su valor debe ser exactamente `plugin-br-bank-transfer`. En producción, el plugin sirve el manifiesto solo cuando la autenticación está activada.

Algunos eventos son de mejor esfuerzo: cuando su escritura en el outbox falla, el plugin mantiene el cambio que anuncian y no publica el evento. Si un evento esperado no llega, lee la transferencia con [Get Transfer](https://docs.lerian.studio/es/reference/interfaces/ted-jd/retrieve-transfer.md).

## Catálogo de eventos

### Iniciación y ciclo de vida de la transferencia

| Clave del evento | Schema | Se dispara cuando |
| - | - | - |
| `payment_initiation.created` | `1.0.0` | [Initiate Transfer](https://docs.lerian.studio/es/reference/interfaces/ted-jd/initiate-transfer.md) creó una iniciación, antes de su confirmación. |
| `transfer.initiated` | `1.0.0` | El plugin creó una transferencia TED OUT o [TED entre cores](https://docs.lerian.studio/es/interfaces/ted-jd/ted-cross-core.md) a partir de una iniciación confirmada. |
| `transfer.processing_started` | `1.0.0` | Una TED OUT entró en procesamiento (`CREATED` a `PENDING` a `PROCESSING`). |
| `transfer.completed` | `1.2.0` | Una TED OUT, un P2P o una TED entre cores se completó. Para una TED OUT, el STR la liquidó, o un operador la liquidó manualmente. Para una TED entre cores, el otro core acreditó al destinatario. |
| `transfer.rejected` | `1.1.0` | Una TED OUT o una TED entre cores se rechazó, y su retención se canceló. Para una TED OUT, JD la rechazó en el envío, o el STR rechazó la liquidación. Para una TED entre cores, el otro core rechazó el crédito, o JD Courier no alcanzó a ningún destinatario. |

### Conciliación

| Clave del evento | Schema | Se dispara cuando |
| - | - | - |
| `transfer.reconciliation_required` | `1.0.0` | Una TED OUT con resultado desconocido pasó a conciliación. |
| `transfer.reconciliation_resolved` | `1.5.0` | El worker de conciliación o un operador resolvió una transferencia. |
| `transfer.reconciliation_exhausted` | `1.1.0` | El worker de conciliación se detuvo después del número máximo de intentos y pasó la transferencia a revisión manual. |
| `transfer.reconciliation_failed` | `1.0.0` | El worker de conciliación falló una TED OUT por un error determinista. |
| `transfer.reconciliation_manual_retry_requested` | `1.0.0` | Un operador devolvió una TED OUT de la revisión manual a la cola de conciliación. |
| `transfer.scope_repaired` | `1.0.0` | Un operador corrigió el ledger en el que está registrada una transferencia. No se movió dinero. |

### Transferencias entrantes

| Clave del evento | Schema | Se dispara cuando |
| - | - | - |
| `transfer_incoming.completed` | `1.0.0` | El plugin acreditó una TED IN o un [crédito al cliente](https://docs.lerian.studio/es/interfaces/ted-jd/ted-in.md#customer-credits), o registró un crédito o una devolución entre cores del otro core (`transferType` `CROSS_CORE_IN`). |
| `transfer_incoming.chargeback` | `1.1.0` | Una TED IN completada falló por un chargeback STR0010R2. Lo envía el worker de TED IN, y también un operador que cierra manualmente un chargeback estacionado. |
| `transfer_incoming.undeliverable` | `1.0.0` | El plugin registró un crédito entrante que no pudo entregar. |
| `transfer_incoming.return_requested` | `1.0.0` | La [devolución de una TED IN](https://docs.lerian.studio/es/interfaces/ted-jd/ted-in.md#return-a-received-transfer) entró en procesamiento: la retención está puesta, y el STR0010 está por enviarse. |
| `transfer_incoming.returned` | `1.0.0` | El STR liquidó la devolución de una TED IN, y el crédito original se revirtió. |
| `transfer_incoming.return_rejected` | `1.0.0` | La devolución de una TED IN se rechazó, y su retención se canceló. |
| `transfer_incoming.return_manual_review` | `1.0.0` | La devolución de una TED IN espera a un operador. |

### Devoluciones de TED OUT y de P2P

| Clave del evento | Schema | Se dispara cuando |
| - | - | - |
| `transfer_outgoing.devolution_notified` | `1.1.0` | El plugin registró una devolución (STR0010R2) de una TED OUT en la transferencia original. Para una devolución que llega antes de que la TED OUT se complete, informa la decisión sobre la comisión antes de cualquier reembolso. |
| `transfer_internal.returned` | `1.0.0` | La devolución de un P2P se completó, y el ledger revirtió la transacción original. |
| `transfer_internal.return_failed` | `1.0.0` | El ledger rechazó la devolución de un P2P. No se movió nada, y el P2P puede devolverse otra vez. |

## Deduplicación

Deduplica por `(ce-source, ce-id)` y mantén los consumidores idempotentes. Tres eventos también necesitan una clave de negocio:

* **`transfer_incoming.chargeback`**: el worker de TED IN y un operador pueden anunciar cada uno el mismo chargeback, con dos ids. Deduplica por `tenantId`, `transferId` y `status`.
* **`transfer.reconciliation_resolved`**: una resolución de operador puede llegar dos veces. `convergedOntoExistingResolution` marca la copia que encontró la resolución ya escrita. Deduplica por `tenantId`, `transferId`, `status` y `reconciliationStatus`, no por ese marcador.
* **`transfer_outgoing.devolution_notified`**: una devolución puede anunciarse dos veces, una al llegar y otra cuando se asienta su reembolso, con dos ids. Deduplica por `tenantId`, `transferId`, `controlNumber` y `transferStatus`.

## Contratos de payload

Los montos son strings decimales, por ejemplo `"1500.00"`. Los timestamps son strings RFC 3339 en UTC. Los campos marcados con `?` son opcionales. `tenantId` queda vacío en el modo single-tenant.

```typescript theme={null}
// payment_initiation.created
interface PaymentInitiationCreated {
  paymentInitiationId: string
  tenantId: string
  organizationId?: string
  ledgerId: string
  senderAccountId: string
  recipientAccountId?: string
  recipientIspb: string
  amount: string
  feeAmount: string
  totalAmount: string
  transferType: string
  status: string
  purpose?: string
  expiresAt: string
  createdAt: string
}

// transfer.initiated
interface TransferInitiated {
  transferId: string
  paymentInitiationId: string
  tenantId: string
  organizationId?: string
  ledgerId: string
  senderAccountId: string
  recipientAccountId?: string
  amount: string
  feeAmount: string
  totalAmount: string
  transferType: string
  status: string
  confirmationNumber: string
  controlNumber: string
  midazTransactionId?: string
  signingArtifactId?: string
  createdAt: string
}

// transfer.processing_started
interface TransferProcessingStarted {
  transferId: string
  tenantId: string
  transferType: string
  status: string
  controlNumber: string
  statusPath: string
  processingStartedAt: string
}

// transfer.completed
interface TransferCompleted {
  transferId: string
  initiationId: string
  tenantId: string
  organizationId?: string
  ledgerId: string // on a P2P between ledgers, the payer's ledger
  senderAccountId: string
  recipientAccountId?: string
  midazTransactionId: string
  confirmationNumber: string
  status: string
  transferType: string // TED_OUT, P2P, or CROSS_CORE
  amount: string
  feeAmount: string
  totalAmount: string
  packageAppliedId?: string
  completedAt: string
  // TED OUT only
  source?: "str0008r1" | "reconciliation" | "manual"
  controlNumber?: string
  clearingControlNumber?: string
  messageSequence?: string
  settledAt?: string
  // P2P between ledgers only
  recipientLedgerId?: string
  ledgerGroupId?: string
}

// transfer.rejected
interface TransferRejected {
  transferId: string
  tenantId: string
  transferType: string // TED_OUT or CROSS_CORE
  status: string
  failureCode: string // BTF-4005 on a cross-core TED
  failureMessage: string
  errorCategory: string
  midazCancelled: boolean
  midazTransactionId?: string
  rejectedAt: string
  // TED OUT only
  source?: "dispatch" | "str0008r1" | "reconciliation"
  rejectedBy?: "jd" | "bacen"
  settlementRejectionCode?: string
  controlNumber?: string
  clearingControlNumber?: string
  messageSequence?: string
}

// transfer.reconciliation_required
interface TransferReconciliationRequired {
  transferId: string
  tenantId: string
  transferType: string
  status: string
  reconciliationStatus: string
  controlNumber?: string
  counterpartySystem: string
  failureClass: string
  failureCode: string
  errorCategory: string
  reason: string
  reconciliationEnqueuedAt: string
}

// transfer.reconciliation_resolved
interface TransferReconciliationResolved {
  transferId: string
  tenantId: string
  status: string
  transferType: string
  reconciliationStatus: string
  resolution: string
  reasonCategory: string
  attempts: number
  jdResponseCode?: string
  controlNumber?: string
  jdSequenceNumber?: string
  clearingControlNumber?: string
  // operator resolution only
  actor?: string
  operatorReason?: string
  evidenceReference?: string
  convergedOntoExistingResolution?: boolean
  resolutionAuthorizedBy?: string
  // resolution manual_repost only
  previousCompensationTransactionId?: string
  compensationTransactionId?: string
}

// transfer.reconciliation_exhausted
interface TransferReconciliationExhausted {
  transferId: string
  tenantId: string
  status: string
  transferType: string
  reconciliationStatus: string
  resolution: string
  reasonCategory: string
  attempts: number
  maxAttempts: number
  holdPreserved: boolean
  jdResponseCode?: string
  controlNumber?: string
  jdSequenceNumber?: string
}

// transfer.reconciliation_failed
interface TransferReconciliationFailed {
  transferId: string
  tenantId: string
  status: string
  reconciliationStatus: string
  resolution: string
  reasonCategory: string
  attempts: number
  errorCategory: string
  jdResponseCode?: string
  controlNumber?: string
  jdSequenceNumber?: string
}

// transfer.reconciliation_manual_retry_requested
interface TransferReconciliationManualRetryRequested {
  transferId: string
  tenantId: string
  status: string
  transferType: string
  reconciliationStatus: string
  operatorReason: string
  previousAttempts: number
  requestId?: string
  requeuedAt: string
}

// transfer.scope_repaired
interface TransferScopeRepaired {
  transferId: string
  tenantId: string
  ledgerId: string
  status: string
  transferType: string
  actor: string
  operatorReason: string
  evidenceReference?: string
  requestId?: string
  repairedAt: string
}

// transfer_incoming.completed
interface TransferIncomingCompleted {
  transferId: string
  tenantId: string
  status: string
  transferType: string // TED_IN, TED_IN_STR0005 to TED_IN_STR0051, or CROSS_CORE_IN
  amount: string
  feeAmount: string
  grossAmount: string
  controlNumber: string // empty on CROSS_CORE_IN
  messageSequence: string // empty on CROSS_CORE_IN
  repairedBy: string
}

// transfer_incoming.chargeback
interface TransferIncomingChargeback {
  transferId: string
  tenantId: string
  status: string
  transferType: string
  // absent when an operator closes the chargeback
  chargebackCode?: string
  messageSequence?: string
  controlNumber?: string
}

// transfer_incoming.undeliverable
interface TransferIncomingUndeliverable {
  undeliverableId: string
  tenantId: string
  jdIncomingMessageId: string
  rejectionReason: string
  rejectionCategory: string
  controlNumber: string
  messageSequence: string
  grossAmount: string
  senderISPB: string
}

// transfer_incoming.return_requested, returned, return_rejected, return_manual_review
interface TransferIncomingReturn {
  transferId: string // the return, a TED_OUT
  originalTransferId: string // the TED IN that it returns
  tenantId: string
  organizationId?: string
  transferType: string
  status: string
  controlNumber: string
  amount: string // the gross amount that leaves your institution
  returnReasonCode: string
  requestedVia: string
  externalReference?: string
  clearingControlNumber?: string
  reversalTransactionId?: string
  reconciliationReasonCode?: string
  reconciliationReasonClass?: string
  revertFailureClass?: string
  failureCode?: string
  rejectionCause?: "not_found" | "str_refused" | "jd_refused" | "local_verdict" | "operator"
  occurredAt: string
}

// transfer_outgoing.devolution_notified
interface TransferOutgoingDevolutionNotified {
  transferId: string
  tenantId: string
  codDevTransf: string
  chargebackCode: string
  senderISPB: string
  recipientISPB: string
  amount: string
  controlNumber: string
  transferStatus: string
  transferType: string
  feeRetained: boolean
  feeRefunded: boolean
  feeRefundedAmount?: string
  via: string
}

// transfer_internal.returned, return_failed
interface TransferInternalReturn {
  transferId: string // the return, a P2P
  originalTransferId: string
  tenantId: string
  organizationId: string
  ledgerId: string // the ledger of the debited account
  recipientLedgerId?: string // between ledgers only: the ledger of the credited account
  amount: string
  reversalTransactionId?: string
  requestedVia: string
  revertFailureClass?: string
  failureCode?: string
  occurredAt: string
}
```


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