> ## 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 (BTG) procesa transferencias y reembolsos intra-PSP (P2P) de forma interna — sin liquidación de BTG — mientras sigue reportando a BACEN vía TRCK002.

Las transferencias intra-PSP (también llamadas P2P) son transferencias Pix donde el pagador y el beneficiario pertenecen al **mismo participante** — el ISPB de origen y el de destino son idénticos. Como el dinero nunca sale de la institución, estas transferencias se liquidan internamente en lugar de enrutarse a BTG para su liquidación. Aun así deben reportarse a BACEN por cumplimiento regulatorio.

<Note>
  Versiones anteriores del plugin rechazaban las transferencias intra-PSP con el error `PIX-0406: Intra PSP Not Supported`. Ese error fue eliminado — las transferencias y reembolsos intra-PSP ahora están totalmente soportados.
</Note>

# Detección

***

El plugin marca una transferencia como intra-PSP cuando el ISPB de destino es igual a tu `PIX_ISPB` configurado:

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

Cuando se detecta, la respuesta de iniciación incluye `isIntraPSP: true`:

```json theme={null}
POST /v1/transfers/cashout/initiate
→ 201 Created
{
  "id": "uuid",
  "status": "PENDING",
  "isIntraPSP": true,
  "expiresAt": "2026-02-25T12:05:00Z"
}
```

El flag `isIntraPSP` se propaga a las entidades `Transfer`, `Cashout`, `Cashin` y `Refund` para consulta y reconciliación.

# Modelo de procesamiento

***

Las transferencias intra-PSP siguen el **mismo enrutamiento de Midaz que las transferencias externas** (a través de la cuenta de tránsito `@external`), por lo que el comportamiento del libro mayor es idéntico. La única diferencia es que la liquidación ocurre de forma síncrona dentro del plugin en lugar de a través de webhooks de BTG.

Se crean dos transacciones de Midaz por transferencia:

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

El cash-in interno reutiliza exactamente los mismos pipelines `CashinApprovalCommand` y `CashinSettlementCommand` que los cash-ins externos, incluyendo la validación de alias de CRM, las verificaciones de saldo, la titularidad de la clave PIX, la finalización del cobro y el cálculo de tarifas.

## Flujo

***

```
Process Cashout (isIntraPSP = true)
  → 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/webhooks/intra-psp/events

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`, exactamente como un cashout externo a la espera de BTG. El estado final (`COMPLETED`/`FAILED`) se entrega de forma asíncrona vía webhook saliente. El endpoint intra-PSP es totalmente idempotente, por lo que los reintentos del worker nunca duplican transacciones.
</Note>

# Reporte regulatorio TRCK002

***

Cada transacción intra-PSP exitosa se reporta a BACEN a través del endpoint de abstracción **TRCK002** de BTG, dentro del SLA regulatorio de **P99 ≤ 300 segundos**.

* El reporte TRCK002 es **no bloqueante** — una falla de reporte nunca revierte la transacción de Midaz ni la finalización de la transferencia. Los reportes fallidos se reintentan con backoff exponencial.
* BTG devuelve una entidad `PixInternalTransactionsReport` con un `pactualId` y un estado inicial de `PROCESSING`.
* Las actualizaciones de estado del reporte llegan vía un webhook **CAMT025** (`PixInternalTransactionsReport`) en el endpoint de eventos de BTG, transicionando el reporte a `CONFIRMED` o `ERROR`.
* Como respaldo cuando se pierden webhooks, el estado del reporte se puede consultar por end-to-end ID o por identificación de devolución.

# Reembolsos intra-PSP

***

Un reembolso (devolução) de una transferencia cuyo cash-in original fue intra-PSP también se procesa internamente:

* El plugin detecta intra-PSP cuando el cash-in original tiene `isIntraPSP = true`.
* Debita al solicitante del reembolso (`requester → @external`), luego orquesta el cash-in del reembolso al remitente original a través del mismo patrón de cola + endpoint.
* El reembolso se reporta a TRCK002 con un `returnIdentification`.
* Webhooks salientes: `refund.completed`/`refund.failed` al solicitante y `cashin.completed` al remitente original.

<Warning>
  El desbloqueo no está soportado para transferencias intra-PSP. El flujo de desbloqueo consulta a BTG por el estado, lo cual no aplica a transacciones internas, por lo que llamarlo devuelve el error `PIX-0418`. Consulta [Operaciones de reembolso](/es/midaz/plugins/pix/indirect/indirect-pix-refund-operations).
</Warning>

# Motivos de falla

***

Las fallas de validación de cash-in se entregan de forma asíncrona vía el webhook `cashout.failed`. Motivos comunes de falla intra-PSP:

| Código                         | Descripción                                                                    |
| ------------------------------ | ------------------------------------------------------------------------------ |
| `RECIPIENT_ACCOUNT_INVALID`    | Falló la validación de alias de CRM (cuenta no encontrada, cerrada, bloqueada) |
| `RECIPIENT_CANNOT_RECEIVE`     | Falló la validación de saldo del libro mayor                                   |
| `PIX_KEY_OWNERSHIP_INVALID`    | La clave PIX no pertenece a la cuenta de destino                               |
| `COLLECTION_INVALID`           | Falló la validación del cobro de QR code dinámico                              |
| `INTERNAL_CREDIT_FAILED`       | Falló la transacción de crédito del libro mayor                                |
| `INTERNAL_DEBIT_REVERT_FAILED` | Crítico — falló la reversión del débito; requiere reconciliación manual        |

# Próximos pasos

***

* [Webhooks](/es/midaz/plugins/pix/indirect/indirect-pix-webhooks) — Envoltorio de eventos, reintentos y enrutamiento
* [Operaciones de reembolso](/es/midaz/plugins/pix/indirect/indirect-pix-refund-operations) — Reembolsos distribuidos y desbloqueo
* [Configurar la integración](/es/midaz/plugins/pix/indirect/indirect-pix-integration) — Configuración de ISPB y del worker
* [Referencia de API](/es/reference/midaz/plugins/indirect-pix/create-entry) — Documentación completa de la API
