Para recuperar vendas recusadas no HeroPay, deixe o checkout retentar na hora, escute o webhook payment_credit_cart_refused, que traz o motivo da operadora, e dispare uma régua com o mesmo link e o Pix como saída.
Recuperação de vendas recusadas é trazer de volta o comprador que quis pagar e teve o cartão negado. No HeroPay, ela tem três camadas: o checkout retenta sozinho (retentativa pós-recusa, Parcelamento Inteligente para limite, 2 cartões e Pix como saída na mesma tela); o webhook payment_credit_cart_refused entrega o motivo da operadora em tempo real para você disparar uma régua de mensagens; e os relatórios de recusadas com motivo (GET /reports/purchase/refused/reasons_count) mostram onde está o dinheiro perdido. Você não precisa escrever job de retentativa; precisa decidir o que falar com quem ficou para trás.
Criar conta sandbox Ler a documentação
Antes de começar
- Conta sandbox e token JWT em app.heropay.tech, em
HEROPAY_API_URLeHEROPAY_JWT_TOKENno servidor. - Um canal de mensagem (e-mail, WhatsApp ou CRM) que o seu backend consiga acionar.
- Links com
src, para saber de qual oferta ou pedido veio cada recusa e reenviar o link certo.
Passo a passo
1. Diagnostique: quanto e por quê
curl -G "$HEROPAY_API_URL/reports/purchase/refused/reasons_count" \
-H "Authorization: Bearer $HEROPAY_JWT_TOKEN" \
-H "Accept: application/vnd.herospark.com; version=1" \
-d "start_date=2026-08-01" -d "end_date=2026-08-31"A resposta agrupa as recusas do período por motivo; GET /reports/purchase/refused/sales, com os mesmos filtros, traz as vendas recusadas. Rode os dois uma vez no sandbox e confira o formato da resposta antes de automatizar a leitura; a lista completa está na documentação de relatórios de compras.
Leia o resultado em dois grupos. Recuperáveis: limite insuficiente, suspeita de fraude do emissor, dados digitados errado. Irrecuperáveis no mesmo cartão: cartão cancelado, bloqueado, vencido. O primeiro grupo pede retentativa e parcelamento; o segundo pede outro cartão ou Pix. Retentar cartão cancelado só queima tentativa.
A conta que justifica o trabalho, ilustrativa: 40 recusas por mês num produto de R$ 197 são R$ 7.880 parados. Recuperar um quarto delas devolve R$ 1.970 por mês, R$ 23.640 por ano, sem um centavo a mais de tráfego.
2. Deixe o checkout fazer a primeira recuperação
Antes de qualquer mensagem, o checkout hospedado já trabalha na hora da recusa:
- Retentativa pós-recusa no próprio checkout, sem o comprador recomeçar.
- Parcelamento Inteligente na recusa por limite: cobra a parcela do mês em vez de reservar o limite total, com até 3 retentativas por parcela.
- 2 cartões (50/50, parcelamento independente) em ofertas acima de R$ 100.
- Pix e boleto na mesma tela, quando o link aceita. Crie os links com
"payment_methods": ["credit_card", "pix"]no mínimo: o Pix é a saída mais barata para quem teve o cartão negado (R$ 0 por transação).
É por isso que a aprovação no cartão fica em 93%+. O que sobra depois disso é o que a régua recupera.
3. Escute a recusa por webhook
curl -X POST "$HEROPAY_API_URL/webhook" \
-H "Authorization: Bearer $HEROPAY_JWT_TOKEN" \
-H "Accept: application/vnd.herospark.com; version=1" \
-H "Content-Type: application/json" \
-d '{
"webhook": {
"trigger": "payment_credit_cart_refused",
"webhook_url": "https://seuapp.com/webhooks/heropay",
"request_method": "post"
}
}'Atenção à grafia: cart, não card. Com card, a API responde 422 com Trigger is not included in the list. Cadastre também spark_payment_confirmed, para parar a régua quando a venda for paga.
Recorte dos campos que a régua usa (valores ilustrativos, campos reais do template; o payload completo está na documentação de webhooks):
{
"buyer": { "name": "Ana Souza", "email": "ana@exemplo.com", "phone_raw": "11988887777" },
"payment": { "id": "8812501", "method": "credit_card" },
"offer": { "title": "Curso de Excel" },
"cart": { "src": "ads-setembro" },
"payment_methods": {
"credit_card": { "refused_message": "Saldo insuficiente" }
}
}Valide X-HeroPay-Signature, deduplique por payment.id + gatilho e agende a régua. O texto de refused_message vem da operadora e varia: classifique por palavras-chave (limite, saldo, vencido, cancelado), deixe uma categoria "outros" como padrão e nunca faça a régua depender de uma frase exata.
4. Monte a régua
O webhook não traz a URL do checkout; guarde data.offer.url junto do src quando criar o link e reenvie a mesma URL. Uma régua enxuta, como ponto de partida para testar:
| Quando | Mensagem | Condição para parar |
|---|---|---|
| Na hora | "Seu banco recusou por {motivo}. Tente parcelar ou pague no Pix: {link}" | spark_payment_confirmed com o mesmo src e e-mail |
| +1 hora | Lembrete curto com o mesmo link e o Pix em destaque | Idem |
| +24 horas | Último contato, com a dúvida mais comum respondida | Idem, ou pedido de descadastro |
Personalize pelo motivo: limite pede "parcele" ou "divida em 2 cartões"; cartão cancelado pede "use outro cartão ou o Pix". Mensagem genérica de "pagamento recusado" recupera menos. Use o contato só para concluir a compra que a pessoa iniciou e ofereça saída da lista, em linha com a LGPD.
5. Recupere também quem abandonou
Quem preencheu os dados e saiu sem tentar pagar não gera recusa. Puxe os abandonos do dia:
curl -G "$HEROPAY_API_URL/reports/tracking/abandoned_carts" \
-H "Authorization: Bearer $HEROPAY_JWT_TOKEN" \
-H "Accept: application/vnd.herospark.com; version=1" \
-d "start_date=2026-09-23" -d "end_date=2026-09-23"Um carrinho conta como abandonado quando o comprador acessa o checkout, preenche e-mail ou telefone e não paga. Pelo painel, a automação de carrinho abandonado dispara em 15 minutos. Para a lista de recusadas com contato do comprador, GET /transactions/by_status?status=refused traz buyer, cart.src e transaction.payment_method de cada tentativa.
Variações
Por prompt, com o llms.txt
Cole https://heropay.ai/llms.txt no Claude, ChatGPT, Cursor, Lovable e outros (mais em /ai) e peça:
Me mostra os motivos de recusa de agosto agrupados, quanto isso soma em reais
e a lista de recusadas de ontem com e-mail e oferta, para eu revisar a régua.Com o contrato da API no contexto, a IA escreve as consultas aos relatórios de recusadas e a /transactions/by_status, que são só leitura. Revise antes de rodar. Um MCP server oficial está em desenvolvimento.
Sem código, pelo painel
Em app.heropay.tech, abra o relatório de recusadas com motivo e ligue as automações por evento de recusa e de carrinho abandonado (gatilho em 15 minutos, com cerca de 25 variáveis para personalizar a mensagem).
Erros comuns e como ler a mensagem
| Status | Mensagem (real) | Causa e correção |
|---|---|---|
422 (webhook) | Trigger is not included in the list | Gatilho escrito payment_credit_card_refused. O certo é payment_credit_cart_refused. |
401 (webhook) | Failed to create webhook | Token ausente, sem Bearer ou de outro ambiente. |
422 | Start date deve ser uma data válida no formato YYYY-MM-DD | Data em formato brasileiro em /transactions/by_status. |
| régua que não para | nenhuma | Faltou cadastrar spark_payment_confirmed ou casar por src + e-mail. Resultado: cobrar quem já pagou. |
| mensagem repetida | nenhuma | O webhook tem retentativa e pode chegar duas vezes. Deduplique por payment.id + gatilho. |
Perguntas frequentes
Por que o cartão do meu cliente foi recusado?
Os motivos mais comuns são limite insuficiente, bloqueio preventivo do banco emissor por suspeita de fraude, dados digitados errado e cartão vencido, cancelado ou bloqueado. No HeroPay, o motivo informado pela operadora chega em payment_methods.credit_card.refused_message no webhook payment_credit_cart_refused, e GET /reports/purchase/refused/reasons_count agrupa os motivos de um período. Saber o motivo muda a mensagem: limite se resolve com parcelamento, cartão cancelado só com outro meio.
Dá para retentar a cobrança de um cartão recusado pela API?
Não existe endpoint de "retentar agora" na v1. A retentativa acontece em dois lugares: no checkout, na hora da compra (retentativa pós-recusa, Parcelamento Inteligente e 2 cartões), e na renovação de assinatura, que é reprocessada automaticamente. Para a venda avulsa que ficou para trás, a recuperação é reenviar o mesmo link, com Pix como alternativa. Detalhes da assinatura em /como/cobrar-assinatura-com-retentativa.
Quanto custa uma tentativa recusada?
Nada. A tarifa do cartão, 3,49%, incide só sobre transação aprovada. Retentativas que falham e vendas recusadas não pagam. Se o comprador recuperado pagar no Pix, a tarifa é R$ 0 e o valor entra inteiro. Por isso vale colocar o Pix em destaque na régua: é a saída mais barata para você e a que não depende do limite do cliente. Tabela em /precos.
Qual a diferença entre venda recusada e carrinho abandonado?
Venda recusada é quando o comprador tentou pagar e o cartão foi negado: gera o evento payment_credit_cart_refused, com o motivo. Carrinho abandonado é quando ele preencheu os dados de contato no checkout e saiu sem tentar pagar: aparece em GET /reports/tracking/abandoned_carts. As mensagens são diferentes. Para quem teve recusa, você oferece outro meio; para quem abandonou, você responde a dúvida ou a objeção que o fez sair.
Quanto tempo esperar para mandar a primeira mensagem?
Na recusa, a hora certa é logo: a pessoa ainda está com a intenção de compra e, muitas vezes, com o celular na mão. Uma mensagem imediata com o motivo e a alternativa (parcelar ou Pix) costuma ser a de maior efeito. Para o carrinho abandonado, o gatilho do painel dispara em 15 minutos. Depois disso, espace os lembretes e pare no terceiro contato. Teste a régua na sua base antes de fixar os intervalos.
Posso usar o motivo da recusa na mensagem ao cliente?
Pode, traduzido para linguagem de gente. "Seu banco recusou por limite; parcele em mais vezes ou pague no Pix" converte mais que "transação não autorizada". Evite repetir códigos técnicos da operadora e nunca sugira que o cliente fez algo errado. Para suspeita de fraude do emissor, a orientação honesta é "confirme a compra no app do seu banco e tente de novo".