> ## 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 /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. |
| `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. Dos 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.

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