Skip to main content
Cancelar uma tentativa significa encerrar um payment_intent que ainda não terminou em pagamento concluído. É a operação certa quando o comprador abandonou o fluxo, a cobrança foi criada em duplicidade, existe suspeita de fraude antes da captura ou uma autorização de cartão não deve mais ser capturada. O cancelamento não substitui uma devolução. Se o dinheiro já entrou e o payment_intent está succeeded, use um refund.
Cancelamento evita ou encerra uma cobrança que ainda não foi concluída. Refund devolve uma cobrança que já foi paga. O status atual do Payment Intent decide qual operação usar.

Decisão rápida

O que exatamente é cancelado

A API cancela o Payment Intent identificado pelo pi_*. Ela não cancela automaticamente outros objetos do seu produto.
  • O pedido no seu sistema continua sendo responsabilidade da sua aplicação.
  • Um payment link reutilizável continua ativo e pode criar novas sessões.
  • Uma checkout session pode ter seu próprio estado e precisa ser reconciliada pelos eventos de checkout.
  • Uma assinatura ou invoice não deve ter seu lifecycle alterado diretamente só porque um Payment Intent foi cancelado; use a operação própria do recurso.
Se um payment link gerou várias compras, localize o Payment Intent da compra correta. Não cancele um pi_* apenas porque ele pertence ao mesmo link.

O que acontece com o dinheiro em cada estado

Antes da confirmação

Em requires_payment_method ou requires_confirmation, ainda não existe valor capturado. O cancelamento encerra o processo na Chargefy e impede novas ações naquele Payment Intent. Nenhum dinheiro precisa voltar ao comprador.

Cartão autorizado, mas não capturado

Em requires_capture, o cartão passou pela autorização, mas o valor ainda não foi capturado. Ao cancelar, a Chargefy envia o desfazimento da autorização e zera amount_capturable. Isso evita a captura. O tempo para o limite aparecer novamente para o comprador pode variar conforme o emissor do cartão, mesmo que a API já retorne status: "canceled".

PIX pendente

Em pending, ainda não há dinheiro confirmado. O cancelamento muda o Payment Intent para canceled na Chargefy, mas não deve ser usado como prova de que um QR code PIX já emitido ficou instantaneamente inutilizável. O comprador ainda pode pagar uma instrução que permaneça válida até sua expiração. Por isso, mantenha o receiver de webhooks ativo e trate uma confirmação tardia como dinheiro recebido: localize a charge concluída e crie um refund.
Para PIX pendente, payment.intent.canceled confirma o estado do Payment Intent na Chargefy; não garante, sozinho, a invalidação imediata do QR code. Continue processando eventos de sucesso e conciliando a charge até a expiração da instrução.
O mesmo cuidado vale para outros meios assíncronos, como boleto: concluir o cancelamento no seu sistema não elimina a necessidade de observar uma liquidação tardia.

Pagamento em processamento

processing representa uma corrida: a tentativa já foi iniciada, mas o resultado final ainda pode chegar. A API aceita o cancelamento, porém sua integração deve continuar acompanhando eventos. Se uma charge terminar paga, devolva o valor com um refund.

Antes de começar

Você precisa de:
  • uma API key com permissão de escrita;
  • o ID do Payment Intent (pi_*);
  • o status mais recente do objeto;
  • um motivo de cancelamento, quando disponível;
  • uma chave de idempotência única para a operação.
Para plataformas, envie também o header Organization da organização conectada dona do Payment Intent.

Passo a passo

1

Consulte o estado mais recente

Faça um GET imediatamente antes de decidir. Não use um status salvo há vários minutos: cartão e PIX podem mudar de estado enquanto o comprador conclui o pagamento.
Se o retorno já estiver succeeded, pare e crie um refund. Se estiver canceled, não envie uma nova operação de cancelamento.
2

Interrompa novas ações no seu produto

Remova o botão de pagar, feche a etapa de checkout ou marque o pedido como cancelamento solicitado. Isso reduz a chance de o comprador confirmar a cobrança enquanto seu backend envia o cancelamento.Não apague os IDs financeiros: você ainda precisa deles para auditoria, webhooks e eventual refund.
3

Envie o cancelamento com idempotência

Faça POST /v1/payment-intents/{id}/cancel. Envie cancellation_reason no corpo e uma chave única no header Idempotency-Key.
4

Atualize o pedido com a resposta completa

A resposta é o Payment Intent completo, agora com status: "canceled", canceled_at preenchido e cancellation_reason registrado.Guarde esse objeto e separe o estado comercial do pedido do estado financeiro da tentativa.
5

Processe o webhook de cancelamento

Trate payment.intent.canceled de forma idempotente. Ele permite que outros serviços do seu sistema cheguem ao mesmo estado mesmo quando não fizeram a chamada diretamente.
6

Cubra pagamentos tardios

Para PIX, boleto e qualquer tentativa em processing, continue tratando eventos de sucesso. Se uma charge for confirmada depois do cancelamento do pedido, crie um refund em vez de tentar cancelar novamente.

Payload do cancelamento

Os motivos aceitos são: O campo é opcional, mas registrá-lo melhora auditoria, suporte e análise de conversão. Ele descreve por que a tentativa foi encerrada; não altera a regra financeira da operação. Existe um segundo conjunto de motivos — automatic, expired, failed_invoice e void_invoice — que a Chargefy escreve sozinha e você só recebe. Enviar um deles na requisição responde 400. A diferença é de autoridade: abandoned afirma que o comprador desistiu, e essa é a sua leitura do negócio; expired afirma que o prazo acabou, e esse fato é nosso.

Exemplo de resposta

O endpoint retorna 200 OK com o mesmo shape completo de GET /v1/payment-intents/{id}. Este é um recorte dos campos mais importantes:

O que a resposta confirma

  • O Payment Intent foi encerrado na Chargefy.
  • Ele não pode ser confirmado ou capturado novamente.
  • Em requires_capture, a autorização foi desfeita antes de a resposta de sucesso ser retornada.
  • O motivo e o horário do cancelamento foram registrados.

O que a resposta não confirma

  • Que o pedido comercial foi cancelado no seu sistema.
  • Que um payment link reutilizável foi desativado.
  • Que um QR code PIX já emitido ficou imediatamente inválido.
  • Que não haverá confirmação tardia de uma tentativa que estava pending ou processing.
  • Que um pagamento já concluído foi devolvido.

Webhooks e reconciliação

O evento principal é payment.intent.canceled:
No receiver:
  1. valide a assinatura;
  2. deduplique pelo event.id;
  3. atualize a tentativa por data.object.id;
  4. preserve charge, latest_charge e referências do pedido;
  5. continue aceitando eventos financeiros de sucesso para meios assíncronos;
  6. se o dinheiro entrar depois, abra o fluxo de refund.
Se você usa Checkout Sessions, trate também checkout.session.async.payment.succeeded. Para integrações diretas, mantenha o tratamento dos eventos payment.intent.* e charge.*. Numa corrida de estado, reconcilie a charge paga antes de decidir pelo refund; não confie apenas no status comercial do pedido.

Cenários comuns

O comprador abandonou antes de informar um cartão

O Payment Intent está requires_payment_method. Cancele com cancellation_reason: "abandoned". Nenhum dinheiro foi movimentado e nenhum refund deve ser criado. Se essa tentativa nasceu de um checkout, o caminho é outro — veja o cenário abaixo.

A tentativa nasceu de uma sessão de checkout

A sessão é a dona do ciclo de vida do Payment Intent dela, então o cancelamento direto responde 409 com code: "payment_intent_owned_by_checkout_session" e o message diz qual sessão expirar. Use POST /v1/checkout-sessions/{id}/expire: a sessão vira expired e o intent é cancelado com cancellation_reason: "expired". Isso não é uma restrição arbitrária. Enquanto a sessão está aberta, o comprador pode voltar ao link, trocar de meio de pagamento ou pedir um novo código PIX — e é o intent aberto que sustenta essas três coisas. Fechar o intent por baixo deixaria a sessão viva apontando para uma tentativa morta. A exceção é requires_capture: existe valor autorizado no cartão do comprador para liberar, e essa liberação é uma operação do pagamento. Nesse estado o cancelamento direto funciona normalmente.

Seu backend criou duas tentativas para o mesmo pedido

Escolha qual Payment Intent continuará válido. Cancele o outro com cancellation_reason: "duplicate". Antes, confira se nenhum deles já está succeeded; uma tentativa paga precisa de refund, não de cancelamento.

A análise antifraude interrompeu a compra antes da captura

Se o Payment Intent ainda não está pago, cancele com cancellation_reason: "fraudulent". Se a cobrança já concluiu, a decisão de devolver deve seguir o fluxo de refund e a política de risco da organização.

O cartão foi autorizado para captura manual

O status é requires_capture e amount_capturable é maior que zero. Cancele o Payment Intent para desfazer a autorização. Não crie um refund, porque ainda não existe valor capturado para devolver.

O pedido foi cancelado enquanto o PIX aguardava pagamento

Envie o cancelamento e pare de apresentar o QR code no seu produto. Mesmo assim, mantenha a conciliação ativa até a expiração. Se chegar uma confirmação de pagamento, localize a charge e crie um refund total.

A resposta da API se perdeu

Repita exatamente o mesmo request com o mesmo Idempotency-Key. Se a primeira chamada terminou com sucesso, a API devolve a resposta original com o header Idempotent-Replayed: true. Sem a mesma chave, uma segunda chamada pode encontrar o Payment Intent já canceled e retornar conflito, mesmo que a primeira tenha funcionado.

O cancelamento perdeu a corrida para o pagamento

Se a API retornar 409 porque o Payment Intent já está succeeded, não tente forçar o cancelamento. Crie um refund. Se o sucesso chegar por webhook depois de uma resposta de cancelamento em estado assíncrono, siga a mesma regra: dinheiro confirmado exige devolução.

Erros comuns da API

Exemplo de conflito quando o pagamento já foi concluído:

Modele os estados separadamente

Evite um único campo canceled para representar tudo. No seu sistema, separe: Essa separação evita dois erros comuns: liberar um pedido só porque houve redirecionamento de sucesso e afirmar que o dinheiro foi devolvido só porque o pedido foi cancelado.

Checklist para produção

  • Consultar o Payment Intent imediatamente antes de cancelar.
  • Usar refund quando o status já for succeeded.
  • Enviar Idempotency-Key e repetir a mesma chave em retries.
  • Registrar cancellation_reason quando conhecido.
  • Processar payment.intent.canceled de forma idempotente.
  • Continuar observando sucesso tardio para PIX, boleto e processing.
  • Em captura manual, confirmar que amount_capturable foi zerado.
  • Preservar IDs financeiros mesmo depois de cancelar o pedido.
  • Ter um fluxo automático ou operacional para refund de pagamento tardio.

Próximos passos

Cancelar Payment Intent

Contrato completo do POST /v1/payment-intents/{id}/cancel.

Devolver um pagamento

Crie e acompanhe o refund quando o dinheiro já entrou.

Payment Intents

Entenda os estados e o ciclo completo de uma cobrança.

Idempotência

Repita mutações com segurança quando uma resposta se perder.