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

# Transferencias intra-PSP

> Cómo el Plugin Pix Indirecto vía BTG liquida internamente las transferencias intra-PSP (P2P) y las devoluciones sin liquidación en BTG, e informa a BACEN mediante TRCK002.

Una transferencia intra-PSP (también llamada P2P) es una transferencia Pix entre un pagador y un receptor en el **mismo participante**. El ISPB de origen y el de destino son idénticos. El dinero nunca sale de la institución, por lo que el plugin liquida la transferencia internamente y no la enruta a BTG. Aun así, el plugin informa la transferencia a BACEN por cumplimiento regulatorio.

<Note>
  El plugin admite transferencias y devoluciones intra-PSP. Las liquida internamente e informa cada una a BACEN mediante TRCK002.
</Note>

# Detección

***

El plugin marca una transferencia como intra-PSP cuando el ISPB de destino coincide con el `PIX_ISPB` que configuraste:

| Tipo de iniciación | Origen del ISPB de destino                              |
| ------------------ | ------------------------------------------------------- |
| `KEY` / `QR_CODE`  | Respuesta de la consulta a DICT (`account.participant`) |
| `MANUAL`           | `destination.ispb` en el payload de la solicitud        |

La detección es interna. La respuesta de iniciación y el estado del cashout coinciden con los de una transferencia externa. El plugin enruta una transferencia intra-PSP por la ruta de liquidación interna en lugar de BTG.

# Modelo de procesamiento

***

Una transferencia intra-PSP usa el mismo enrutamiento en Midaz que una transferencia externa, a través de la cuenta de tránsito `@external`. El comportamiento del ledger es idéntico. El plugin liquida la transferencia de forma síncrona y no espera webhooks de BTG.

El plugin crea dos transacciones de Midaz por transferencia:

1. **Cashout**: `source → @external` (`pending: false`)
2. **Cashin**: `@external → destination` (`pending: false`)

El cash-in interno reutiliza los mismos pipelines `CashinApprovalCommand` y `CashinSettlementCommand` que un cash-in externo. Estos pipelines ejecutan la validación de alias en el CRM, las verificaciones de saldo, la titularidad de la clave Pix, la finalización del cobro y el cálculo de comisiones.

## Flujo

***

```
Process Cashout (intra-PSP detected)
  → Midaz debit: source → @external
  → Write inbound record to the webhook queue
  → Cashout status → PROCESSING (intermediary)
  → Return PROCESSING to client

Inbound worker (existing)
  → Picks up the record and delivers it (HTTP + HMAC)
    to POST /v1/payment/intra-psp/transfers/webhooks

Intra-PSP endpoint (orchestrates the full lifecycle)
  → CashinApprovalCommand → ACCEPTED / DENIED
  → ACCEPTED  → CashinSettlementCommand → Midaz credit → Cashout COMPLETED
  → DENIED / settlement fails → revert Midaz debit → Cashout FAILED
  → Report to BTG TRCK002 (async, non-blocking)
  → Outbound webhooks: cashout.completed/failed + cashin.completed
```

<Note>
  El cashout responde con `PROCESSING`, igual que un cashout externo que espera a BTG. El plugin entrega el estado final (`COMPLETED` o `FAILED`) de forma asíncrona mediante un webhook saliente. El endpoint intra-PSP es idempotente, por lo que los reintentos del worker nunca duplican transacciones.
</Note>

# Informes regulatorios TRCK002

***

El plugin informa cada transacción intra-PSP exitosa a BACEN mediante el endpoint **TRCK002** de BTG.

* El envío de informes TRCK002 es **no bloqueante**. Una falla del informe nunca revierte la transacción de Midaz ni la finalización de la transferencia. El plugin reintenta un informe fallido.
* El plugin crea un `TransactionReport` por cada transacción. Después de que BTG acepta el envío, el estado del informe pasa a `PROCESSING` y lleva un `pactualId`.
* BTG envía actualizaciones del estado del informe mediante un webhook **CAMT025**, con el tipo `PIX_INTERNAL_TRANSACTIONS_REPORT`. El webhook lleva el informe a `CONFIRMED` (terminal) o `ERROR` (recuperable).
* También puedes consultar un informe por ID end-to-end o por identificación de devolución cuando un webhook no llega.

# Devoluciones intra-PSP

***

El plugin también procesa una devolución internamente cuando el cash-in original fue intra-PSP:

* El plugin detecta intra-PSP a partir de la transferencia original, cuando su ISPB de origen y el de destino coinciden.
* Debita al solicitante de la devolución (`requester → @external`). Luego entrega el cash-in de la devolución al remitente original mediante el mismo patrón de cola y endpoint.
* El plugin informa la devolución a TRCK002 con un `returnIdentification`.
* El plugin persiste un webhook saliente `REFUND` (flujo DICT) para notificar al solicitante, y la liquidación del cash-in intra-PSP encola `cashin.completed` para el remitente original.

<Warning>
  No llames al desbloqueo para una transferencia intra-PSP. El flujo de desbloqueo consulta a BTG por el estado de la transferencia. BTG nunca procesa una transacción interna, por lo que la consulta no aplica. Consulta [Operaciones de devolución](/es/interfaces/pix-btg/indirect-pix-refund-operations).
</Warning>

# Motivos de falla

***

El plugin entrega una falla de validación del cash-in de forma asíncrona mediante el webhook `cashout.failed`. Para una falla intra-PSP, el webhook lleva el motivo `INTRA_PSP_REJECTED` y un mensaje saneado. Mensajes comunes:

| Mensaje                                      | Significado                                       |
| -------------------------------------------- | ------------------------------------------------- |
| `pix key not found`                          | La clave Pix no existe en DICT.                   |
| `pix key is not active`                      | La clave Pix existe pero está inactiva.           |
| `pix key does not match account`             | La clave Pix no pertenece a la cuenta de destino. |
| `account cannot receive payment`             | La cuenta de destino no puede recibir el pago.    |
| `collection validation rejected the payment` | El cobro con código QR dinámico rechazó el pago.  |
| `duplicate transaction`                      | Ya existe un cash-in con el mismo ID end-to-end.  |

# Próximos pasos

***

* [Webhooks](/es/interfaces/pix-btg/indirect-pix-webhooks): Envelope del evento, reintentos y enrutamiento
* [Operaciones de devolución](/es/interfaces/pix-btg/indirect-pix-refund-operations): Devoluciones distribuidas y desbloqueo
* [Configurar la integración](/es/interfaces/pix-btg/indirect-pix-integration): Configuración del ISPB y del worker
* [Referencia de API](/es/reference/interfaces/pix-btg/create-entry): Documentación completa de la API
