Um reembolso no Google Play acontece silenciosamente. A cobrança é revertida, o cliente continua usando o app, e nada muda do seu lado a menos que você verifique deliberadamente. Verificar é exatamente para isso que a Voided Purchases API existe. Ela retorna os pedidos que foram cancelados, reembolsados ou estornados, para que você possa retirar o acesso a tudo que o cliente parou de pagar. Conecte um job programado a ela, leia o que retorna e revogue o direito de uso. Esse é todo o mecanismo.
Uma coisa pega quase todas as equipes de surpresa, e ela está na política, não no código. Essa API só lista pedidos que foram efetivamente revogados. Reembolse uma compra no Play Console sem marcar a opção de revoke e esse pedido nunca aparece aqui, então seu job roda perfeitamente limpo enquanto um cliente reembolsado sai levando tudo o que você vendeu. A seguir, cobrimos a API campo por campo, os limites que a delimitam e por onde o dinheiro escoa silenciosamente quando ela não está conectada.
Principais conclusões
A Voided Purchases API, acessada pelo método purchases.voidedpurchases.list, lista pedidos que o Google Play cancelou, reembolsou ou estornou, o que permite que você construa um sistema que retira o acesso a compras que o cliente não possui mais.
Apenas pedidos revogados aparecem. Um reembolso feito pelo desenvolvedor sem revogar permanece invisível aqui, então retirar o acesso significa reembolsar com o revoke ativado.
Seu alcance é uma janela móvel de 30 dias. Como o startTime não pode retroceder mais de 30 dias, qualquer servidor que fique offline por mais de um mês perde essas anulações permanentemente, e é por isso que o polling precisa rodar em uma programação.
voidedSource identifica quem disparou a anulação: 0 para o usuário, 1 para o desenvolvedor, 2 para o Google. voidedReason explica o motivo, variando de 0 para Other até 7 para Chargeback e 8 para Unacknowledged_purchase.
As notificações de desenvolvedor em tempo real disparam uma VoidedPurchaseNotification no instante em que uma compra é anulada, mas trate isso como um alerta. Confirme na Voided Purchases API antes de revogar qualquer coisa.
Diferencie as renovações de assinatura pelo orderId, nunca pelo purchaseToken. Um único purchaseToken abrange todas as renovações de uma assinatura, então o token sozinho não consegue separar um período do outro.
Os limites são 6,000 consultas por dia e 30 em qualquer intervalo de 30 segundos, então delimite cada requisição a uma janela de tempo e percorra as páginas usando o token de continuação, nunca uma requisição por pedido.
O que a API retorna
O endpoint resolve uma única pergunta: quais pedidos deste app foram anulados recentemente. Uma anulação reúne três resultados que devolvem o dinheiro do cliente: um cancelamento, um reembolso ou um chargeback. Ela alcança tanto produtos avulsos dentro do app quanto assinaturas, e um parâmetro define o escopo. Deixe type em 0, o padrão, e só as compras de produtos avulsos anuladas retornam. Defina type como 1 e você recebe compras avulsas anuladas e compras de assinatura anuladas juntas.
Cada item na resposta é um objeto de compra anulada com um conjunto curto e valioso de campos:
orderId identifica de forma exclusiva uma compra avulsa, uma assinatura ou uma renovação individual dentro dela. Trate isso como sua chave de junção.
purchaseToken identifica uma compra avulsa ou uma assinatura, mas não separa renovações, então use orderId para isso.
purchaseTimeMillis registra quando a compra aconteceu, em milissegundos desde o epoch.
voidedTimeMillis registra quando ela foi cancelada, reembolsada ou estornada, também em milissegundos desde o epoch.
voidedSource indica quem iniciou a anulação, onde 0 é o usuário, 1 é o desenvolvedor e 2 é o Google.
voidedReason indica a causa como um número inteiro de 0 a 8.
voidedQuantity traz a quantidade anulada de um reembolso parcial baseado em quantidade, e só aparece quando includeQuantityBasedPartialRefund é true.
Como um purchaseToken cobre uma assinatura inteira, enquanto cada renovação recebe um orderId recém-gerado, basear seus direitos de uso no token fará você revogar o período errado. Use o orderId como chave em vez disso.
Leia o voidedReason antes de mexer em qualquer coisa
O voidedReason é o que transforma uma lista simples em uma decisão real, porque um reembolso por arrependimento e um chargeback bancário compartilham o mesmo feed, mas não têm nada em comum. O conjunto completo é o seguinte:
1. Other não carrega nenhuma categoria atribuída. Revogue e siga em frente.
2. Remorse é um cliente que mudou de ideia, um reembolso do dia a dia.
3. Not_received é uma alegação de que o produto nunca chegou, algo que vale a pena investigar na sua entrega.
4. Defective significa que não funcionou, um sinal de qualidade que você deve registrar.
5. Accidental_purchase é uma compra não intencional, com frequência em um dispositivo compartilhado.
6. Fraud é uma transação que o Google sinalizou como fraudulenta.
7. Friendly_fraud é um chargeback em que o verdadeiro titular do cartão contesta uma cobrança que ele mesmo fez.
8. Chargeback é o banco do cliente revertendo o pagamento, definitivo perante o banco e agora cobrado de você.
9. Unacknowledged_purchase é o Google reembolsando automaticamente uma compra que seu app nunca confirmou (acknowledge).
O motivo 9 é um reembolso que você mesmo provocou. Qualquer compra que seu app deixa sem confirmação (unacknowledged) tem o dinheiro devolvido pelo Google, então um unacknowledged_purchase neste feed é receita perdida por uma única chamada não feita, não por qualquer escolha do comprador.
A janela de 30 dias que esvazia a lista silenciosamente
A API não alcança mais do que os últimos 30 dias. O startTime tem como padrão o momento atual menos 30 dias e recusa qualquer valor anterior a esse, e o endTime tem como padrão o momento presente, então o que você tem é uma janela móvel de um mês, não um arquivo permanente.
A implicação é dura. Deixe um job de polling quebrar e passar despercebido por cinco semanas, e as anulações da primeira semana já terão saído da API, sem nenhuma chamada capaz de recuperá-las. Esses pedidos ficam sem revogação, e você nem saberia que aconteceram, a menos que os tivesse capturado em outro lugar. A rede tem um buraco exatamente do tamanho da sua maior interrupção. Faça polling pelo menos uma vez por dia e reconcilie com as notificações em tempo real, tratando os 30 dias como o relógio rígido de exclusão que eles realmente são.
Se um pedido aparece ou não depende do revoke
Esse é o motivo número um pelo qual as equipes chamam a API de quebrada. Ela retorna pedidos revogados e mais nada. Reembolsos iniciados por usuários, cancelamentos, chargebacks e reembolsos iniciados pelo Google revogam automaticamente, então sempre aparecem no feed. Um reembolso iniciado pelo desenvolvedor é a exceção. Emitir o reembolso você mesmo, seja pelo Play Console ou pela Orders API, deixa a escolha de revogar como uma decisão separada que você precisa tomar. Recuse essa opção e o pedido fica quitado com o cliente, mas nunca aparece neste feed.
A conclusão é curta. Quando seu objetivo é cortar o acesso, reembolse com o revoke ativado. Ignore isso e você terá devolvido o dinheiro deixando a porta aberta, e o seu job de revogação, por mais cuidadosamente construído que seja, não terá nada com que trabalhar.
Fazendo polling sem estourar a cota
O endpoint tem limite de taxa, e os limites são baixos o suficiente para que um loop descuidado os estoure. Você tem 6,000 consultas por dia, contadas no horário do Pacífico, e nunca mais que 30 em qualquer intervalo de 30 segundos. Esse orçamento favorece o polling em janelas e penaliza qualquer design de uma chamada por pedido.
Janelas de tempo e o token de continuação
O maxResults fica em 1,000 por padrão, e esse também é o valor máximo permitido. Caso uma janela contenha mais anulações do que uma página comporta, a resposta vem com um objeto tokenPagination contendo um nextPageToken. Devolva esse token na sua próxima chamada para avançar pelas páginas. Fixe os limites da janela com startTime e endTime, continue paginando até o token se esgotar, e só então avance a janela. Essa cadência mantém você longe tanto do limite de rajada de 30 segundos quanto da cota diária.
As notificações em tempo real fecham a lacuna diária
Mesmo um polling diário deixa você cego por até 24 horas, e lacunas longas são exatamente o que a janela de 30 dias penaliza. As notificações de desenvolvedor em tempo real fecham essa defasagem. No instante em que uma compra é anulada, uma VoidedPurchaseNotification é publicada em um tópico do Cloud Pub/Sub sob seu controle, e seu backend a consome em segundos. O payload dela permanece compacto:
purchaseToken é o token da compra original.
orderId é o id da transação anulada, gerado de forma inédita a cada renovação de assinatura.
productType é 1 para uma assinatura e 2 para uma compra avulsa.
refundType distingue um reembolso total, marcado como 1, de um reembolso parcial baseado em quantidade, marcado como 2.
Trate a notificação como um alerta, não como verdade absoluta. Assim que uma VoidedPurchaseNotification chega, consulte a Voided Purchases API para verificar a situação real do pedido, e só então revogue. O alerta diz para você verificar; a API diz a verdade.
Quanto isso custa em dinheiro
A API é encanamento, mas o motivo para instalar esse encanamento é uma conta, e dois dos números dela estão subindo.
A partir de 3 de agosto de 2026, a conta do chargeback é sua
A partir de 3 de agosto de 2026, o Google transfere o custo de um chargeback para o desenvolvedor. Você perde o valor da compra e ainda cobre a taxa de chargeback do banco. Um voidedReason igual a 7 deixa de ser apenas uma venda perdida e passa a ser um item de custo com uma taxa anexada. O chargeback em si não pode ser revertido, já que é definitivo perante o banco, mas identificar a anulação rapidamente permite revogar o direito de uso e, para tudo que ainda está sendo entregue, parar de gastar com um cliente que foi reembolsado e depois estornado.
Você continua bancando um cliente que já foi reembolsado
O valor da venda desaparece no momento em que a anulação chega. O que ainda está sob seu controle é o custo de continuar entregando o produto. Para cada hora que um direito de uso reembolsado permanece ativo, as contas que o cliente parou de pagar continuam chegando do seu lado: o processamento, as chamadas ao provedor de modelo, o armazenamento e qualquer pagamento a criadores ou parceiros que a atividade dele dispara. Construir o pipeline de revogação sobre essa API é como esse gasto é interrompido. Ignore isso e você estará bancando o produto para pessoas que a loja já reembolsou.
Friendly fraud é uma tendência, não um incidente
Um voidedReason igual a 5 ou 6 raramente aparece sozinho. Fraude e friendly fraud se concentram em torno de contas, dispositivos e, ocasionalmente, promoções específicas. Como a API anexa voidedSource e voidedReason a cada anulação, você tem o suficiente para identificar tendências de abuso por conta, em vez de absorver cada estorno como uma perda isolada. Uma conta que sofre um chargeback pela segunda vez está te dizendo o que o primeiro reembolso não disse.
Juntando tudo
O modelo inteiro é pequeno depois que as peças estão em mãos. Escute a VoidedPurchaseNotification em tempo real para que nada fique esperando um dia inteiro. Trate a Voided Purchases API como a fonte da verdade, indexada por orderId para que as renovações nunca se misturem. Leia voidedSource e voidedReason para que um chargeback seja tratado separadamente de um reembolso por arrependimento. Faça polling em uma cadência apertada o suficiente para que a janela de 30 dias nunca morda, e reembolse com o revoke ativado sempre que sua intenção for cortar o acesso.
Essa é a camada que o Refund Sensor administra para você. Ele consome as notificações em tempo real, reconcilia cada anulação com a API, revoga o pedido exato em vez do produto inteiro, e mantém um chargeback bancário separado de um reembolso comum, para que os casos mais caros apareçam em vez de se esconder. Você tem o acesso retirado em segundos e um registro completo de quem anulou o quê e por quê, sem precisar montar nenhum pipeline de Pub/Sub ou job de polling.
Onde essas regras estão documentadas
Perguntas frequentes
Porque o feed traz apenas pedidos revogados. Reembolsos iniciados pelo usuário, junto com cancelamentos, chargebacks e reembolsos iniciados pelo Google, revogam sozinhos e sempre aparecem. Um reembolso que você mesmo emite só aparece se você também optar por revogá-lo. Reembolse sem revogar e o pedido fica quitado, mas invisível aqui, então ative o revoke sempre que seu objetivo for retirar o acesso.
Trinta dias, e nada além disso. Por padrão, o startTime fica no momento atual menos 30 dias e recusa qualquer valor anterior, então o endpoint se comporta como uma janela móvel de um mês, não como um arquivo. Assim que uma anulação ultrapassa os 30 dias, ela desaparece sem nenhuma forma de recuperá-la, e é exatamente por isso que você faz polling em uma programação e reforça isso com notificações em tempo real.
As duas têm um papel. Uma VoidedPurchaseNotification chega até você em segundos e diz para você verificar, mas a orientação do Google é tratá-la como um sinal, não como a verdade. Confirme o estado atual pela Voided Purchases API e só então revogue. A notificação elimina o atraso; a API fornece o voidedSource e o voidedReason oficiais sobre os quais você realmente age.
Olhe o voidedReason. Um 7 é um chargeback, em que o banco do cliente reverteu o pagamento, e um 6 é friendly fraud. Um 1 é um reembolso comum por mudança de ideia. Essa distinção importa porque, a partir de 3 de agosto de 2026, o Google repassa o valor do chargeback e a taxa do banco para o desenvolvedor, então um 7 custa mais caro do que um reembolso simples.
Sim. Defina o parâmetro type como 1 e você recebe compras avulsas anuladas junto com compras de assinatura anuladas; o padrão, 0, retorna apenas produtos avulsos. Para assinaturas, identifique o período exato da anulação pelo orderId, já que um único purchaseToken abrange todas as renovações, enquanto cada transação de renovação tem seu próprio orderId.






