Devolva parte ou todo o valor capturado em uma charge e acompanhe a liquidação.
Um reembolso (refund) devolve dinheiro que já foi capturado em uma charge: ele reverte parte ou todo o valor cobrado e aponta sempre para a charge de origem. É o objeto que responde “essa cobrança foi devolvida, deu certo, e quanto voltou?”.
Refund ≠ cancelamentoCancelar interrompe uma cobrança que ainda não capturou dinheiro (um payment_intent ou uma charge em andamento). Um refund atua sobre valor que já entrou: ele devolve o que foi capturado. Por isso o refund só existe para uma charge succeeded, paga e capturada.
Cada refund nasce de uma charge e carrega de volta as referências que aquela charge tinha: o payment_intent que a originou e, quando existem, a invoice, o customer e o payment_method.
Uma mesma charge pode ter vários refunds parciais. O valor disponível para reembolsar é o valor capturado menos os refunds já pending, requires_action ou succeeded.
Refund é uma ação que materializa um recurso próprio: você o cria com POST /v1/refunds apontando para uma charge capturada ou para um payment_intent que já tenha uma charge reembolsável. Sem amount, o refund usa todo o valor ainda disponível da charge resolvida.
Campo
Tipo
Regra
charge
string
Charge a reembolsar (ch_*). Envie charge ou payment_intent, não ambos.
payment_intent
string
Payment Intent a reembolsar (pi_*). A Chargefy resolve internamente a charge capturada.
amount
integer
Valor em centavos, inteiro > 0. Omitido = valor disponível inteiro (refund total).
reason
string
Motivo público do refund: duplicate, fraudulent ou requested_by_customer.
metadata
object
Pares chave→valor livres para correlacionar com o seu sistema.
Use o header Idempotency-Key (ou idempotency_key no body) para criar o refund com segurança em caso de retry. Repetir a mesma chave devolve o refund já criado em vez de gerar uma cobrança em duplicidade.
Chargeback/dispute não é reason de refund. Use fraudulent quando você estiver fazendo uma devolução voluntária por fraude; disputa de cartão é outro fluxo financeiro.
O refund só prossegue se a charge estiver de fato capturada. A charge precisa estar succeeded, paga, capturada e com valor capturado > 0. Fora disso, a criação falha:
Situação
HTTP
message
Charge não encontrada na organização
404
No such charge.
Charge não está capturada/paga
409
Charge is not refundable.
Charge sem valor disponível (já totalmente reembolsada)
409
Charge has no refundable amount remaining.
amount maior que o valor disponível
400
Refund amount exceeds refundable amount.
amount não inteiro ou ≤ 0
400
amount must be a positive integer.
Charge não pode ser reembolsada automaticamente
422
Charge cannot be refunded automatically.
Quando o payment_intent ainda está em requires_capture, ele não tem valor capturado para refund. Cancele o intent com POST /v1/payment-intents/{id}/cancel em vez de criar um refund.
Reembolso é irreversível. Não há endpoint para “desfazer” um refund: uma vez que ele liquida, o dinheiro voltou. Para devolver mais valor da mesma charge, crie um novo refund parcial enquanto houver valor disponível.
A criação devolve o refund já com o estado retornado pela liquidação — que pode ser imediato ou assíncrono, dependendo do meio. Quando ainda não há confirmação final, o refund nasce pending ou requires_action e migra de estado depois, comunicado por webhook.
Status
Significado
pending
Refund registrado, aguardando a confirmação da devolução.
requires_action
Refund aguardando ação para continuar.
succeeded
Valor devolvido com sucesso.
failed
Não foi possível concluir a devolução. Veja failure_reason.
canceled
A reversão foi cancelada antes de concluir.
Como a liquidação pode ser assíncrona, não faça polling: trate o status retornado na criação como provisório e reaja aos webhooks refund.created, refund.updated e refund.failed para acompanhar a transição até succeeded, failed ou canceled.
Mudanças no refund disparam eventos cujo data.object carrega o objeto refund completo, no mesmo shape do GET /v1/refunds/{id}.
Evento
Quando dispara
refund.created
O refund foi criado.
refund.failed
O refund chegou ao estado failed.
refund.updated
Algum campo público do refund mudou (tipicamente status).
charge.refunded
A charge recebeu um refund parcial ou total.
O evento refund.updated também traz data.previous_attributes com os valores anteriores dos campos alterados — por exemplo, status saindo de pending para succeeded.
Reaja aos webhooks em vez de fazer polling. Ao receber refund.created, refund.updated ou refund.failed, consulte o refund pelo id do payload para conciliar com o seu pedido — metadata é o caminho para correlacionar com o seu sistema.