Saltar al contenido principal
El Plugin Pix Indirecto (BTG) procesa los reembolsos Pix (devoluções) a través del endpoint existente Reembolsar una transferencia Pix recibida. Dos capacidades extienden ese flujo para escenarios reales de MED y fraude:
  • Reembolsos parciales distribuidos — devuelve un reembolso desde múltiples cuentas internas en una sola operación
  • Desbloqueo — recupera un reembolso o una transferencia que está atascado en PROCESSING

Reembolsos parciales distribuidos


Cuando un Pix recibido se distribuye internamente entre varias cuentas — por ejemplo, el monto principal a la cuenta del cliente y una tarifa a una cuenta de tarifas — un reembolso posterior por MED/fraude puede necesitar debitarse parcialmente de cada una de esas cuentas. El flujo estándar de reembolso debita desde una sola cuenta. Para dividir el débito, envía un array opcional operations en el cuerpo de la solicitud. La presencia de operations es la única señal — no hay un nuevo endpoint, variable de entorno ni feature flag.

Solicitud


POST /v1/transfers/{transfer_id}/refunds
{
  "amount": "1000.82",
  "description": "MED Cappta",
  "operations": [
    { "accountAlias": "alias-conta-cliente", "amount": "0.82" },
    { "accountAlias": "alias-conta-fee", "amount": "1000.00" }
  ]
}
  • Sin operations → el flujo actual de cuenta única se ejecuta sin cambios.
  • Con operations → el plugin debita cada accountAlias por su amount en Midaz, y BTG recibe un único pacs.004 por el valor total del reembolso.

Reglas de validación


ReglaError
sum(operations[].amount) debe ser igual a amount400 OPERATIONS_SUM_MISMATCH
accountAlias no debe repetirse dentro de la solicitud400 DUPLICATE_ACCOUNT_ALIAS
cada amount debe ser mayor que 0400
cada amount debe tener como máximo 2 posiciones decimales400
cada accountAlias debe haber participado en la transacción original422 ACCOUNT_ALIAS_NOT_IN_ORIGINAL_TRANSACTION
la transacción original debe existir en Midaz422 ORIGINAL_TRANSACTION_NOT_FOUND
El endpoint, el flujo de BTG (pacs.004 con el valor total), la idempotencia y la autenticación son idénticos al reembolso estándar. Solo cambia la composición del débito interno en Midaz.

Ejemplo — Cappta


Un cash-in de R50.000,00sedividioˊenR 50.000,00 se dividió en R 49.000,00 a la cuenta del cliente y R1.000,00aunacuentadetarifas.Trasunfraude,elreembolsorequeridoesdeR 1.000,00 a una cuenta de tarifas. Tras un fraude, el reembolso requerido es de R 1.000,82, pero solo quedan R0,82enlacuentadelcliente.ElarrayoperationsdebitaR 0,82 en la cuenta del cliente. El array `operations` debita R 0,82 de la cuenta del cliente y R1.000,00delacuentadetarifas,mientrasBTGrecibeunuˊnicoreembolsodeR 1.000,00 de la cuenta de tarifas, mientras BTG recibe un único reembolso de R 1.000,82 — sin necesidad de consolidación manual del libro mayor.

Desbloqueo de operaciones atascadas


Un reembolso o una transferencia cuya llamada de reversión a BTG expira antes de la confirmación puede quedar atascado en PROCESSING, con la retención todavía aplicada en Midaz. Dos endpoints dedicados vuelven a consultar a BTG y llevan la operación a su estado terminal correcto.
MétodoEndpointDesbloquea
POST/v1/refunds/{refund_id}/unblockUn reembolso atascado en PROCESSING
POST/v1/transfers/{transfer_id}/unblockUna transferencia atascada en PENDING/PROCESSING
Ambos requieren el encabezado X-Account-Id.

Cómo funciona el desbloqueo


El plugin vuelve a consultar el estado de la reversión/transferencia en BTG y:
  • Si BTG reporta CONFIRMED o ERROR → despacha la liquidación correspondiente y lleva la operación a su estado terminal.
  • Si BTG todavía reporta INITIATED/PROCESSING → devuelve HTTP 200 sin acción; reintenta más tarde.
Una protección de consistencia aborta la operación si el entity, el returnIdentification o el originalEndToEndId de BTG difieren del registro local, evitando la liquidación contra la transacción equivocada.
POST /v1/refunds/{refund_id}/unblock
X-Account-Id: <account-id>
La respuesta incluye el refund actualizado, un message y el btgStatus.

Manejo de un 404 de BTG


Cuando BTG ya no tiene la reversión/transferencia (devuelve 404), el comportamiento depende del tipo de operación y del flag opcional allowNotFoundUnblock en el cuerpo de la solicitud:
OperaciónPor defecto (estricto)Con allowNotFoundUnblock: true
Transferencia (/v1/transfers/{id}/unblock)Devuelve un errorRevierte la retención de Midaz (best-effort, idempotente), marca el cashout como FAILED con BTG_NOT_FOUND, emite un webhook saliente CASHOUT/TRANSFER y devuelve 200 con btgStatus: "NOT_FOUND"
Reembolso (/v1/refunds/{id}/unblock)Devuelve PIX-1012 (ErrProviderRefundNotFound)Revierte la retención y lleva el reembolso a su estado terminal
POST /v1/transfers/{transfer_id}/unblock
{
  "allowNotFoundUnblock": true
}
allowNotFoundUnblock tiene por defecto false. Un cuerpo vacío/ausente o false preserva el comportamiento estricto (un 404 de BTG devuelve un error y nunca revierte la retención). Solo opta por activarlo cuando hayas confirmado que la operación debe liberarse.
La recuperación opcional ante un 404 aplica solo a operaciones CASHOUT en PENDING/PROCESSING con un endToEndId no vacío. Los cash-ins y los estados terminales nunca entran en esta rama.

Limitación intra-PSP


El flujo de desbloqueo de transferencias consulta a BTG por el estado, lo cual no aplica a las transferencias intra-PSP (internas) — no hay transacción de BTG. Llamar al desbloqueo sobre una transferencia intra-PSP devuelve un error síncrono (PIX-0418). La lógica adecuada de desbloqueo intra-PSP es una mejora futura. Consulta Transferencias intra-PSP.

Próximos pasos