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

# Operações de devolução

> Trate os casos de borda da devolução Pix via BTG: devoluções parciais distribuídas (refunds) entre contas internas e desbloqueio de operações travadas.

O Plugin Pix Indireto (BTG) processa devoluções Pix (refunds) pelo endpoint [Devolver uma transferência Pix recebida](https://docs.lerian.studio/pt/reference/interfaces/pix-btg/refund-a-received-pix-transfer.md). Dois recursos estendem esse fluxo para cenários de MED e de fraude:

* **Devoluções parciais distribuídas**: devolva um valor a partir de várias contas internas em uma única operação
* **Desbloqueio**: recupere uma devolução ou transferência travada em `CREATED`, `PENDING` ou `PROCESSING`

# Devoluções parciais distribuídas

***

Um Pix recebido pode ser dividido internamente entre várias contas. Por exemplo, o valor principal vai para a conta do cliente e uma tarifa vai para uma conta de tarifas. Uma devolução posterior de MED ou de fraude pode então debitar parte do valor de cada conta.

O fluxo padrão de devolução debita uma conta. Para dividir o débito, envie um array `operations` opcional no corpo da requisição. O array `operations` é o único sinal. Não há novo endpoint, variável de ambiente nem feature flag.

## Requisição

***

```json theme={null}
POST /v1/transfers/{transfer_id}/refunds
X-Account-Id: <account-id>
X-Reason: FR01
X-Idempotency: 3f6c9a52-71d4-4a0e-b8f2-5e1d7c9a4b60
{
  "amount": "1000.82",
  "description": "MED refund",
  "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 mudança.
* 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

***

| Regra | Erro |
| - | - |
| `sum(operations[].amount)` deve ser igual a `amount` | `400 PIX-0447` Operations Sum Mismatch |
| `accountAlias` não deve se repetir dentro da requisição | `400 PIX-0448` Duplicate Account Alias |
| cada `amount` deve ser maior que `0` | `400 PIX-0004` Invalid Field Values |
| cada `amount` deve ter no máximo 2 casas decimais | `400 PIX-0004` Invalid Field Values |
| a requisição deve conter no máximo 50 operações | `400 PIX-0004` Invalid Field Values |
| o cash-in original deve existir | `404 PIX-0425` Cashin Not Found |
| a requisição deve levar `X-Idempotency` ou `X-Return-End-To-End` | `400 PIX-0001` Missing Headers in Request |

## Reenviar uma devolução

***

Uma requisição de devolução leva `X-Idempotency`, `X-Return-End-To-End` ou ambos. Uma requisição com nenhum dos dois é recusada com `400` `PIX-0001`, e nenhum dinheiro se move.

Quando a primeira devolução não está `FAILED`, um reenvio com a mesma âncora e a mesma requisição a devolve e não cria uma segunda.

* A mesma chave `X-Idempotency` para a mesma conta e a mesma transferência, com `amount` ou `description` diferente, é recusada com `422` `PIX-3004`.
* Um `X-Return-End-To-End` que pertence a uma devolução com requisição diferente, ou a uma devolução `FAILED`, é recusado com `409` `PIX-0423`.

> [!NOTE]
>
> O endpoint, o fluxo no BTG (pacs.004 com o valor total), a idempotência e a autenticação são iguais aos da devolução padrão. Apenas a composição do débito interno no Midaz muda.

## Exemplo: divisão de tarifa

***

O plugin dividiu um cash-in de R$ 50.000,00: R$ 49.000,00 para a conta do cliente e R$ 1.000,00 para uma conta de tarifas. Depois da fraude, a devolução deve ser de R$ 1.000,82. Restam apenas R$ 0,82 na conta do cliente. O array `operations` debita R$ 0,82 da conta do cliente e R$ 1.000,00 da conta de tarifas. O BTG recebe uma única devolução de R$ 1.000,82, sem consolidação manual no ledger.

# Desbloqueio de operações travadas

***

Uma chamada de estorno ao BTG pode dar timeout antes de o BTG confirmá-la. A devolução ou a transferência fica então travada em `PROCESSING`, e o Midaz continua retendo os fundos. Dois endpoints levam uma operação travada ao seu estado terminal.

| Método | Endpoint | Desbloqueia |
| - | - | - |
| `POST` | [`/v1/refunds/{refund_id}/unblock`](https://docs.lerian.studio/pt/reference/interfaces/pix-btg/unblock-a-pix-refund) | Uma devolução travada em `PROCESSING`, uma devolução em `PENDING` por mais de 150 segundos ou uma devolução intra-PSP que não é final |
| `POST` | [`/v1/transfers/{transfer_id}/unblock`](https://docs.lerian.studio/pt/reference/interfaces/pix-btg/unblock-a-pix-transfer) | Uma transferência travada em `PROCESSING`, um cash-out em `PENDING` por mais de 150 segundos, um cash-in em `CREATED` ou um cash-out intra-PSP em `CREATED` |

Os dois exigem o header `X-Account-Id` da conta dona da operação.

## Como o desbloqueio funciona

***

O plugin reconsulta o status do estorno ou da transferência no BTG e:

* Se o BTG informar `CONFIRMED` ou `ERROR` → dispara a liquidação correspondente e move a operação para o estado terminal.
* Se o BTG ainda informar `INITIATED`/`PROCESSING` → retorna **HTTP 200** sem ação. Tente de novo mais tarde.

Uma trava de consistência aborta a operação se `entity`, `returnIdentification` ou `originalEndToEndId` do BTG divergirem do registro local. Isso evita a liquidação contra a transação errada.

```json theme={null}
POST /v1/refunds/{refund_id}/unblock
X-Account-Id: <account-id>
```

A resposta inclui o `refund` atualizado, uma `message` e o `btgStatus`.

Quando o plugin liquida um cash-in mais de 300 segundos após a criação, ele primeiro procura um crédito que o Midaz já tenha para ele. Se encontra um, conclui o cash-in nesse crédito e não credita de novo. Se a consulta falha, ou o crédito encontrado foi revertido, o unblock falha e não credita nada.

## Operações paradas em `CREATED`

***

Um cash-out ou uma devolução de cash-out fica em `CREATED` quando o plugin não consegue saber o resultado do débito no Midaz. O plugin não envia nenhum Pix para ele. O desbloqueio recusa um cash-out ou uma devolução inter-PSP em `CREATED` com `422` `PIX-0470`. Abra um chamado de suporte com a Lerian e informe o id da transferência ou da devolução.

## Recusas

***

O desbloqueio também responde `422` `PIX-0470` nestes casos:

* Um cash-out ou uma devolução inter-PSP está em `PENDING` e mudou há menos de 150 segundos. A chamada de criação ainda pode estar enviando para o BTG. Tente de novo depois desse prazo.
* O cash-out ou a devolução já está final. Se uma chamada anterior respondeu `500` depois que o cash-out ficou final, repita a chamada.

## Como tratar um 404 do BTG

***

O BTG pode retornar `404` quando não tem mais o estorno ou a transferência. O resultado depende então do tipo da operação e da flag de adesão explícita `allowNotFoundUnblock` no corpo da requisição.

| Operação | Padrão (estrito) | Com `allowNotFoundUnblock: true` |
| - | - | - |
| **Transferência** ([`/v1/transfers/{id}/unblock`](https://docs.lerian.studio/pt/reference/interfaces/pix-btg/unblock-a-pix-transfer)) | Retorna um erro | Reverte a retenção no Midaz, marca o cash-out como `FAILED` com `BTG_NOT_FOUND`, emite um webhook de saída `CASHOUT` e retorna `200` com `btgStatus: "NOT_FOUND"`. Se a reversão falha, responde `502` `PIX-0602` e deixa o cash-out como estava |
| **Devolução** ([`/v1/refunds/{id}/unblock`](https://docs.lerian.studio/pt/reference/interfaces/pix-btg/unblock-a-pix-refund)) | Retorna `PIX-1012` | Para uma devolução `CASHOUT`: reverte a retenção no Midaz, marca a devolução como falha e emite um webhook de saída `CASHOUT`. Se a reversão falha, responde `502` `PIX-0602` e deixa a devolução como estava. Uma devolução `CASHIN` continua retornando `PIX-1012` |

```json theme={null}
POST /v1/transfers/{transfer_id}/unblock
{
  "allowNotFoundUnblock": true
}
```

> [!WARNING]
>
> `allowNotFoundUnblock` tem `false` como padrão. Um corpo vazio ou ausente, ou `false`, preserva o comportamento estrito. Um 404 do BTG retorna então um erro e nunca reverte a retenção. Adira apenas quando você tiver confirmado que a operação deve ser liberada.

> [!NOTE]
>
> A recuperação de 404 por adesão explícita se aplica apenas a operações `CASHOUT` em `PENDING`/`PROCESSING` com um `endToEndId` não vazio. Cash-ins e status terminais nunca entram nesse ramo.

## Operações intra-PSP

***

O desbloqueio liquida um cash-out ou uma devolução intra-PSP somente no Midaz e não consulta o BTG. Veja [Transferências intra-PSP](https://docs.lerian.studio/pt/interfaces/pix-btg/indirect-pix-intra-psp.md).

# Próximos passos

***

* [Transferências intra-PSP](https://docs.lerian.studio/pt/interfaces/pix-btg/indirect-pix-intra-psp.md): Transferências e devoluções P2P internas
* [MED 2.0: Recuperação de Fundos](https://docs.lerian.studio/pt/interfaces/pix-btg/indirect-pix-med-2-funds-recovery.md): Recuperação de fraude entre contas
* [Webhooks](https://docs.lerian.studio/pt/interfaces/pix-btg/indirect-pix-webhooks.md): Tratamento de eventos de devolução e transferência
* [Referência da API](https://docs.lerian.studio/pt/reference/interfaces/pix-btg/create-entry.md): Documentação completa da API


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.