Pular para o conteúdo principal
O Plugin Pix Indireto (BTG) processa devoluções Pix por meio do endpoint existente Devolver uma transferência Pix recebida. Dois recursos estendem esse fluxo para cenários reais de MED e fraude:
  • Devoluções parciais distribuídas — devolver um valor a partir de múltiplas contas internas em uma única operação
  • Desbloqueio — recuperar uma devolução ou transferência presa em PROCESSING

Devoluções parciais distribuídas


Quando um Pix recebido é distribuído internamente entre várias contas — por exemplo, o valor principal para a conta do cliente e uma tarifa para uma conta de tarifas — uma devolução posterior por MED/fraude pode precisar ser debitada parcialmente de cada uma dessas contas. O fluxo de devolução padrão debita de uma única conta. Para dividir o débito, envie um array opcional operations no corpo da requisição. A presença de operations é o único sinal — não há novo endpoint, variável de ambiente ou feature flag.

Requisição


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" }
  ]
}
  • Sem operations → o fluxo atual de conta única roda sem alterações.
  • Com operations → o plugin debita cada accountAlias pelo seu amount no Midaz, e o BTG recebe um único pacs.004 com o valor total da devolução.

Regras de validação


RegraErro
sum(operations[].amount) deve ser igual a amount400 OPERATIONS_SUM_MISMATCH
accountAlias não pode se repetir dentro da requisição400 DUPLICATE_ACCOUNT_ALIAS
cada amount deve ser maior que 0400
cada amount deve ter no máximo 2 casas decimais400
cada accountAlias deve ter participado da transação original422 ACCOUNT_ALIAS_NOT_IN_ORIGINAL_TRANSACTION
a transação original deve existir no Midaz422 ORIGINAL_TRANSACTION_NOT_FOUND
O endpoint, o fluxo do BTG (pacs.004 com o valor total), a idempotência e a autenticação são idênticos aos da devolução padrão. Apenas a composição do débito interno no Midaz muda.

Exemplo — Cappta


Um cash-in de R50.000,00foidivididocomoR 50.000,00 foi dividido como R 49.000,00 para a conta do cliente e R1.000,00paraumacontadetarifas.Apoˊsumafraude,adevoluc\ca~oexigidaeˊdeR 1.000,00 para uma conta de tarifas. Após uma fraude, a devolução exigida é de R 1.000,82, mas apenas R0,82restamnacontadocliente.OarrayoperationsdebitaR 0,82 restam na conta do cliente. O array `operations` debita R 0,82 da conta do cliente e R1.000,00dacontadetarifas,enquantooBTGrecebeumauˊnicadevoluc\ca~odeR 1.000,00 da conta de tarifas, enquanto o BTG recebe uma única devolução de R 1.000,82 — sem necessidade de consolidação manual no ledger.

Desbloqueio de operações presas


Uma devolução ou transferência cuja chamada de reversão ao BTG expira antes da confirmação pode permanecer presa em PROCESSING, com a retenção ainda aplicada no Midaz. Dois endpoints dedicados reconsultam o BTG e levam a operação ao seu estado terminal correto.
MétodoEndpointDesbloqueia
POST/v1/refunds/{refund_id}/unblockUma devolução presa em PROCESSING
POST/v1/transfers/{transfer_id}/unblockUma transferência presa em PENDING/PROCESSING
Ambos exigem o cabeçalho X-Account-Id.

Como o desbloqueio funciona


O plugin reconsulta o status da reversão/transferência no BTG e:
  • Se o BTG reportar CONFIRMED ou ERROR → dispara a liquidação correspondente e move a operação para seu estado terminal.
  • Se o BTG ainda reportar INITIATED/PROCESSING → retorna HTTP 200 sem ação; tente novamente mais tarde.
Uma proteção de consistência aborta a operação se entity, returnIdentification ou originalEndToEndId do BTG divergirem do registro local, evitando liquidação contra a transação errada.
POST /v1/refunds/{refund_id}/unblock
X-Account-Id: <account-id>
A resposta inclui a refund atualizada, uma message e o btgStatus.

Tratamento de um 404 do BTG


Quando o BTG não tem mais a reversão/transferência (retorna 404), o comportamento depende do tipo de operação e da flag opcional allowNotFoundUnblock no corpo da requisição:
OperaçãoPadrão (estrito)Com allowNotFoundUnblock: true
Transferência (/v1/transfers/{id}/unblock)Retorna um erroReverte a retenção no Midaz (best-effort, idempotente), marca o cashout como FAILED com BTG_NOT_FOUND, emite um webhook de saída CASHOUT/TRANSFER e retorna 200 com btgStatus: "NOT_FOUND"
Devolução (/v1/refunds/{id}/unblock)Retorna PIX-1012 (ErrProviderRefundNotFound)Reverte a retenção e leva a devolução ao seu estado terminal
POST /v1/transfers/{transfer_id}/unblock
{
  "allowNotFoundUnblock": true
}
allowNotFoundUnblock tem valor padrão false. Um corpo vazio/ausente ou false preserva o comportamento estrito (um 404 do BTG retorna um erro e nunca reverte a retenção). Só habilite quando tiver confirmado que a operação deve ser liberada.
A recuperação opcional de 404 se aplica apenas a operações CASHOUT em PENDING/PROCESSING com um endToEndId não vazio. Cash-ins e status terminais nunca entram neste fluxo.

Limitação intra-PSP


O fluxo de desbloqueio de transferência consulta o BTG pelo status, o que não se aplica a transferências intra-PSP (internas) — não há transação no BTG. Chamar o desbloqueio em uma transferência intra-PSP retorna um erro síncrono (PIX-0418). A lógica adequada de desbloqueio intra-PSP é um aprimoramento futuro. Consulte Transferências intra-PSP.

Próximos passos