Earlier plugin versions rejected intra-PSP transfers with error
PIX-0406: Intra PSP Not Supported. That error has been removed — intra-PSP transfers and refunds are now fully supported.Detection
The plugin flags a transfer as intra-PSP when the destination ISPB equals your configured
PIX_ISPB:
| Initiation type | Source of destination ISPB |
|---|---|
KEY / QR_CODE | DICT lookup response (account.participant) |
MANUAL | destination.ispb in the request payload |
isIntraPSP: true:
isIntraPSP flag is propagated to the Transfer, Cashout, Cashin, and Refund entities for querying and reconciliation.
Processing model
Intra-PSP transfers follow the same Midaz routing as external transfers (through the
@external transit account), so the ledger behavior is identical. The only difference is that settlement happens synchronously inside the plugin instead of via BTG webhooks.
Two Midaz transactions are created per transfer:
- Cashout —
source → @external(pending: false) - Cashin —
@external → destination(pending: false)
CashinApprovalCommand and CashinSettlementCommand pipelines as external cash-ins, including CRM alias validation, balance checks, Pix key ownership, collection completion, and fee calculation.
Flow
The cashout responds with
PROCESSING, exactly like an external cashout awaiting BTG. The final status (COMPLETED/FAILED) is delivered asynchronously via outbound webhook. The intra-PSP endpoint is fully idempotent, so worker retries never duplicate transactions.TRCK002 regulatory reporting
Every successful intra-PSP transaction is reported to BACEN through BTG’s TRCK002 abstraction endpoint, within the regulatory SLA of P99 ≤ 300 seconds.
- TRCK002 reporting is non-blocking — a reporting failure never rolls back the Midaz transaction or transfer completion. Failed reports are retried with exponential backoff.
- BTG returns a
PixInternalTransactionsReportentity with apactualIdand an initial status ofPROCESSING. - Report status updates arrive via a CAMT025 webhook (
PixInternalTransactionsReport) on the BTG events endpoint, transitioning the report toCONFIRMEDorERROR. - As a fallback when webhooks are missed, report status is queryable by end-to-end ID or return identification.
Intra-PSP refunds
A refund (devolução) for a transfer whose original cash-in was intra-PSP is also processed internally:
- The plugin detects intra-PSP when the original cash-in has
isIntraPSP = true. - It debits the refund requester (
requester → @external), then orchestrates the refund cash-in to the original sender through the same queue + endpoint pattern. - The refund is reported to TRCK002 with a
returnIdentification. - Outbound webhooks:
refund.completed/refund.failedto the requester andcashin.completedto the original sender.
Failure reasons
Cash-in validation failures are delivered asynchronously via the
cashout.failed webhook. Common intra-PSP failure reasons:
| Code | Description |
|---|---|
RECIPIENT_ACCOUNT_INVALID | CRM alias validation failed (account not found, closed, blocked) |
RECIPIENT_CANNOT_RECEIVE | Ledger balance validation failed |
PIX_KEY_OWNERSHIP_INVALID | Pix key does not belong to the destination account |
COLLECTION_INVALID | Dynamic QR code collection validation failed |
INTERNAL_CREDIT_FAILED | Ledger credit transaction failed |
INTERNAL_DEBIT_REVERT_FAILED | Critical — debit revert failed; requires manual reconciliation |
Next steps
- Webhooks — Event envelope, retries, and routing
- Refund operations — Distributed refunds and unblocking
- Setting up the integration — ISPB and worker configuration
- API reference — Full API documentation

