Devolução PIX
Inicia uma devolução (total ou parcial) de uma transação PIX recebida.
Endpoint
POST /api/external/pix/refundHeaders
| Header | Tipo | Obrigatório | Descrição |
|---|---|---|---|
Authorization | String | Sim | ApiKey {client_id}:{client_secret} |
Content-Type | String | Sim | application/json |
hmac | String | Sim | Assinatura HMAC-SHA512 do body (saiba mais) |
Idempotency-Key | String | Sim | Chave única do comando de devolução: 8 a 180 chars, charset A-Za-z0-9._:-. Sem ela (ou fora do formato) a API responde 400 idempotency_key_required. Reenviar a MESMA chave faz replay do mesmo comando durável. |
X-Key-Case | String | Não | Defina como camelCase para receber os campos da resposta em camelCase (padrão é snake_case) |
Request Body
| Campo | Tipo | Obrigatório | Descrição | Exemplo |
|---|---|---|---|---|
original_transaction_id | String | Sim | Referência da transação PIX original: transactionId, E2E ou TXID da cobrança (veja abaixo) | "E18236120202608210335s13ed93de5b" |
amount | Integer | Não | Valor a devolver em centavos no request. Se omitido, devolve o valor total da transação original. | 3000 (R$ 30,00) |
reason | String | Não | Código de devolução BACEN (veja tabela abaixo). Padrão: MD06. Validado localmente: código fora da lista aceita responde 422 síncrono. | "MD06" |
description | String | Não | Descrição da devolução (até 140 caracteres na API; o texto enviado no campo ISO é limitado pelo leiaute). Padrão: "Devolução PIX". | "Devolução solicitada pelo cliente" |
Aliases aceitos
Para flexibilidade de integração, o backend aceita múltiplos nomes para cada campo (primeiro encontrado vence):
original_transaction_id(canônico)- valor aceito:
transactionIddo webhook, E2E (prefixoE) outxIdda cobrança QR original_e2e_id- alias para o E2E ID da transação originaloriginalTransactionId- camelCasetransaction_id- fallbackend_to_end_id- fallback
- valor aceito:
reason(canônico)return_code- alias direto
Validação de ownership
O backend valida se a transação original pertence ao mesmo merchant da API Key que está chamando o endpoint. Se você tentar devolver uma transação de outro merchant, recebe HTTP 404 "original transaction not found" - mesma resposta de transação inexistente (por segurança).
Valores monetários (request × response)
O amount do request é em centavos (R$ 1,00 = 100). O amount da response e dos webhooks é em subcentavos / unidades base (R$ 1,00 = 10000). Exemplo: envie 3000 para devolver R$ 30,00; a response retorna 300000.
NUNCA envie float/decimal. Sempre envie inteiro em centavos no request e divida valores de resposta por 10.000 para exibir em reais.
Devolução parcial -- como acompanhar o valor remanescente
Para devolução parcial, informe um amount menor que o valor original. O valor total das devoluções de uma mesma transação não pode exceder o valor original recebido.
O backend rastreia o acumulado em total_refunded e remaining_refundable nos webhooks pix.refund.completed e pix.return.received:
total_refunded= soma de todas as devoluções já executadas para aqueleend_to_end_idoriginalremaining_refundable=amount_original - total_refunded(quanto ainda pode ser devolvido)is_partial=truese essa devolução foi parcial
Antes de fazer uma segunda devolução parcial, consulte o último webhook pix.refund.completed para saber o remaining_refundable - se você exceder, o backend retorna HTTP 422 "Valor da devolução excede o valor original da transação".
Códigos de Devolução
| Código | Descrição |
|---|---|
BE08 | Devolução MED por falha operacional do PSP pagador ou recebedor |
FR01 | Devolução MED por fundada suspeita de fraude |
MD06 | Devolução solicitada pelo usuário recebedor |
SL02 | Devolução por erro ou desacordo em Pix Saque ou Pix Troco |
Validação do reason code
O Monetarie valida o campo reason localmente contra a lista de códigos aceitos e encaminha o código ao BACEN via PACS.004.
- Códigos válidos no
ExternalReturnReason1Codeda PACS.004:BE08,FR01,MD06,SL02. - Códigos de rejeição de outros leiautes, como
AC03,AM09eRR04, não são aceitos como motivo de uma nova PACS.004.
O controller também aceita return_code como alias de reason.
Um código fora da lista aceita (BE08, FR01, MD06, SL02) é recusado sincronamente com 422 e nenhum comando é criado.
Exemplo
BODY='{"amount":3000,"description":"Devolução acordo","original_transaction_id":"E18236120202608210335s13ed93de5b","reason":"MD06"}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha512 -hmac "$CLIENT_SECRET" | awk '{print $2}')
curl -X POST https://api.monetarie.com/api/external/pix/refund \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: refund-$(uuidgen)" \
-H "hmac: $HMAC" \
-d "$BODY"Resposta de Sucesso -- 202
Uma requisição aceita responde 202: a devolução vira um comando durável e o resultado terminal chega pelos webhooks. Falhas de validação continuam respondendo com os códigos 4xx documentados abaixo.
{
"worked": true,
"transaction_id": "PIXRET8f4c1b2a9d0e7f3a1c5b",
"end_to_end_id": null,
"original_end_to_end_id": "E18236120202608210335s13ed93de5b",
"amount": 300000,
"status": "held",
"detail": "Devolucao registrada para processamento duravel"
}HTTP 202 - acompanhe o resultado via GET /pix/refund/:id (use o transaction_id retornado), via GET /transactions/:id, ou aguarde pix.refund.completed / pix.refund.failed. O webhook preserva transactionId e endToEndId da devolução e inclui refundTransactionId, refundEndToEndId, returnId, originalTransactionId, originalEndToEndId, externalId e originalExternalId, permitindo correlacionar a devolução com a cobrança original sem depender de busca por texto.
Consulta da devolução
GET /api/external/pix/refund/:idUse o transaction_id com prefixo PIXRET retornado pelo POST. A consulta exige a permissão transfer:read, não usa Idempotency-Key nem HMAC, e aplica o mesmo escopo da conta vinculada à API Key. Uma devolução de outra conta e um identificador inexistente produzem o mesmo HTTP 404.
{
"worked": true,
"data": {
"transaction_id": "PIXRET8f4c1b2a9d0e7f3a1c5b",
"refund_transaction_id": "PIXRET8f4c1b2a9d0e7f3a1c5b",
"refund_end_to_end_id": "D46026562202609030331refund0001",
"return_id": "D46026562202609030331refund0001",
"original_transaction_id": "PIXINoriginal",
"original_end_to_end_id": "E18236120202608210335s13ed93de5b",
"external_id": "refund-order-1",
"original_external_id": "order-1",
"amount": 300000,
"status": "settled",
"reason_code": "MD06",
"reason_description": "Devolução solicitada pelo usuário recebedor",
"requested_at": "2026-09-03T03:30:00.000000Z",
"completed_at": "2026-09-03T03:30:02.000000Z",
"original_payer": {
"name": "Pagador",
"document": "123***09"
},
"original_recipient": {
"name": "Recebedor",
"document": "123***09"
}
}
}refund_end_to_end_id e return_id representam o mesmo RtrId de devolução, com prefixo D. Enquanto a cabine ainda não o tiver atribuído, ambos podem ser null. Documentos de pessoas naturais das partes originais são mascarados.
E2E ID com prefixo D
Diferente de uma transação PIX OUT comum (E2E prefixo E), uma devolução tem E2E com prefixo D (de "Devolução"). Esse prefixo identifica o tipo ISO 20022 pacs.004 no BACEN. O transaction_id interno também tem prefixo PIXRET para facilitar identificação.
| Campo | Tipo | Descrição |
|---|---|---|
worked | Boolean | true indica que a requisição foi aceita |
transaction_id | String | Identificador da devolução (prefixo PIXRET). Use para consultar status. |
end_to_end_id | Null | Sempre null no POST: o E2E da devolução (prefixo D) é cunhado pela cabine PIX e chega nos webhooks terminais (refundEndToEndId). |
original_end_to_end_id | String | E2E da transação original devolvida |
amount | Integer | Valor da devolução em subcentavos (÷ 10.000 para reais). 300000 = R$ 30,00 |
status | String | Estado da esteira durável no instante da resposta: requested, held ou dispatched |
detail | String | Mensagem descritiva |
Resposta de Erro (404)
{
"worked": false,
"errors": {
"not_found": "Transação original não encontrada"
}
}Resposta de Erro (422) -- Saldo insuficiente
{
"worked": false,
"errors": {
"unprocessable_entity": "insufficient balance"
}
}Ocorre quando o saldo seguro (min(TB, PG) - ver Saldo) é menor que o amount solicitado. Devolução exige que a conta origem tenha saldo ≥ valor a devolver.
Resposta de Erro (422) -- Valor excedido
{
"worked": false,
"errors": {
"unprocessable_entity": "Valor da devolução excede o valor original da transação"
}
}Ocorre quando o total de devoluções (atual + anteriores) excederia o amount da transação original. Devoluções parciais são permitidas, mas a soma não pode ultrapassar o valor recebido.
Resposta de Erro (400) -- Idempotency-Key ausente ou inválida
{
"worked": false,
"errors": {
"idempotency_key_required": "Idempotency-Key valido e obrigatorio"
}
}Resposta de Erro (409) -- Idempotency-Key divergente
{
"worked": false,
"errors": {
"idempotency_key_mismatch": "Idempotency-Key diverge do comando persistido"
}
}Ocorre quando a mesma Idempotency-Key é reenviada com corpo diferente do comando já persistido.
Resposta de Erro (400) -- original_transaction_id ausente
{
"worked": false,
"errors": {
"bad_request": "original_transaction_id is required"
}
}Resposta de Erro (401)
{
"worked": false,
"errors": {
"unauthorized": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
}
}Prazo para devolução
A esteira da cabine revalida a janela antes de montar a PACS.004:
- devoluções comuns: até 90 dias corridos da transação original;
- Pix Saque (
OTHR) e Pix Troco (GSCB): até 1 hora do instante da operação original.
Este endpoint externo não faz essa validação de prazo antes do aceite. Portanto, uma solicitação pode responder 202 e depois terminar em pix.refund.failed por expiração da janela, sem envio da PACS.004. Use o webhook terminal como autoridade do resultado.
PACS.004 x MED: devoluções iniciadas por infração BACEN
Se a devolução que você está iniciando é consequência de uma infração BACEN (notificação via pix.refund.requested), não chame este endpoint. A devolução MED é executada automaticamente pelo backend quando o analysis_result=AGREED é decidido (defesa não submetida no prazo OU acatamento manual via merchant portal). Chamar POST /pix/refund em paralelo pode gerar duplicidade.
Este endpoint é para devoluções voluntárias iniciadas por você (ex: devolver um PIX recebido a mais, cancelar uma venda, acerto comercial). Ver Infrações (fluxo completo) para distinguir os dois cenários.