Alle artikelen
Deep dive8 min leestijd

Wanneer een Google Play-aankoop wordt terugbetaald of teruggeboekt, is de Voided Purchases API hoe je erachter komt

Google Play maakt een aankoop stilletjes ongeldig wanneer die wordt terugbetaald of teruggeboekt. De Voided Purchases API is de lijst van die bestellingen, zodat je toegang kunt intrekken. Hier vind je elk veld, het venster van 30 dagen, de revoke-optie die bestellingen verbergt, en wat het kost.

Een smartphone naast een papieren grootboek, een gesloten messing hangslot en een wegglijdende munt, ter illustratie van de Google Play Voided Purchases API die terugbetaalde en teruggeboekte bestellingen rapporteert

Belangrijkste inzichten

  • De Voided Purchases API, de methode purchases.voidedpurchases.list, retourneert bestellingen die Google Play heeft geannuleerd, terugbetaald of teruggeboekt, zodat je een intrekkingssysteem kunt bouwen dat toegang afsnijdt tot wat de klant niet langer bezit.
  • Alleen bestellingen met revoke verschijnen. Een terugbetaling door de ontwikkelaar zonder de revoke-optie is onzichtbaar voor deze API, dus als je toegang wilt intrekken, moet je terugbetalen met revoke ingeschakeld.
  • Het venster is 30 dagen. startTime kan niet ouder zijn dan 30 dagen geleden, dus een server die langer dan een maand uitligt, verliest die ongeldig gemaakte bestellingen voorgoed. Poll volgens een schema.
  • voidedSource vertelt je wie de bestelling ongeldig maakte: 0 is de gebruiker, 1 is de ontwikkelaar, 2 is Google. voidedReason vertelt je waarom, van 0 Other tot en met 7 Chargeback en 8 Unacknowledged_purchase.
  • Real-time developer notifications sturen een VoidedPurchaseNotification op het moment dat een aankoop ongeldig wordt gemaakt, maar behandel het als een signaal. Roep de Voided Purchases API aan voor de gezaghebbende lijst voordat je intrekt.
  • Identificeer abonnementsverlengingen op orderId, niet op purchaseToken. Eén purchaseToken dekt elke verlenging van een abonnement, dus het token alleen kan twee verlengingen niet uit elkaar houden.
  • De quota zijn 6,000 query's per dag en 30 query's in elk venster van 30 seconden, dus blader met de continuation token door de resultaten en query per tijdvenster, nooit één aanroep per bestelling.

Een terugbetaling op Google Play klopt niet bij je aan. Het geld verschuift, de klant houdt de app open, en tenzij je gaat kijken, verandert er aan jouw kant niets. De Voided Purchases API is waar je gaat kijken. Hij geeft je een lijst van bestellingen die zijn geannuleerd, terugbetaald of teruggeboekt, zodat je de toegang kunt intrekken tot waar de klant niet langer voor betaalt. Richt een geplande taak erop, lees de lijst, snijd het recht af. Dat is de hele lus.

Er is één addertje dat de meeste teams laat struikelen, en het zit niet in de code. Alleen bestellingen die met revoke zijn behandeld, verschijnen hier. Als je een aankoop in de Play Console terugbetaalt zonder de revoke-optie aan te vinken, bereikt die bestelling deze API nooit, en jouw taak draait smetteloos terwijl een terugbetaalde klant alles houdt wat je hem hebt verkocht. Dit artikel loopt de API veld voor veld door, de getallen die haar begrenzen, en waar het geld weglekt als je haar overslaat.

Wat de Voided Purchases API daadwerkelijk retourneert

De API beantwoordt één vraag: welke bestellingen voor deze app zijn onlangs ongeldig gemaakt. Een ongeldigmaking (void) omvat drie uitkomsten die allemaal eindigen met de klant die zijn geld terugkrijgt. Een annulering, een terugbetaling of een chargeback. Het geldt voor eenmalige in-app-producten en voor abonnementen, en je kiest de reikwijdte met één parameter. Zet type op 0 en je krijgt alleen ongeldig gemaakte in-app-productaankopen, wat de standaard is. Zet het op 1 en je krijgt ongeldig gemaakte in-app-aankopen en ongeldig gemaakte abonnementsaankopen samen.

Elk item in de lijst is een voided purchase-object. De velden zijn weinig in aantal en elk ervan telt.

De velden van een voided purchase

FieldWat het bevat
orderIdDe bestel-id die op unieke wijze een eenmalige aankoop, een abonnementsaankoop of een enkele abonnementsverlenging identificeert. Dit is je join-sleutel
purchaseTokenHet token dat een eenmalige aankoop of een abonnement identificeert. Het maakt geen onderscheid tussen verlengingen, gebruik daarvoor dus orderId
purchaseTimeMillisWanneer de aankoop is gedaan, in milliseconden sinds de epoch
voidedTimeMillisWanneer de aankoop is geannuleerd, terugbetaald of teruggeboekt, in milliseconden sinds de epoch
voidedSourceWie de ongeldigmaking initieerde: 0 gebruiker, 1 ontwikkelaar, 2 Google
voidedReasonWaarom de aankoop ongeldig is gemaakt, een geheel getal van 0 tot 8
voidedQuantityDe ongeldig gemaakte hoeveelheid uit een op hoeveelheid gebaseerde gedeeltelijke terugbetaling, alleen geretourneerd wanneer includeQuantityBasedPartialRefund true is

Lees voidedReason voordat je handelt

voidedReason is het veld dat een ruwe lijst in een beslissing verandert. Een terugbetaling door spijt van de koper en een chargeback van de bank belanden beide in dezelfde lijst, maar het zijn niet dezelfde gebeurtenis, en de augustusprijzen maken een van beide duur. Hier is de volledige set.

voidedReasonLabelWat het voor jou betekent
0OtherEr is geen categorie toegewezen. Trek in en ga verder
1RemorseDe koper is van gedachten veranderd. Een gewone terugbetaling
2Not_receivedDe klant zegt het product nooit te hebben ontvangen. De moeite waard om je levering te controleren
3DefectiveHet product werkte niet. Een kwaliteitssignaal, leg het vast
4Accidental_purchaseEen onbedoelde aankoop, vaak op een gedeeld apparaat
5FraudGoogle markeerde de transactie als frauduleus
6Friendly_fraudEen chargeback waarbij de rechtmatige kaarthouder een afschrijving betwist die hij zelf heeft gedaan
7ChargebackDe bank van de klant heeft de betaling teruggedraaid. Definitief bij de bank, en nu aan jou in rekening gebracht
8Unacknowledged_purchaseGoogle heeft automatisch een aankoop terugbetaald die je app nooit heeft bevestigd (acknowledge)

Het venster van 30 dagen is de valkuil die je lijst leegmaakt

De Voided Purchases API kan alleen ongeldig gemaakte aankopen van de afgelopen 30 dagen tonen. De parameter startTime is standaard de huidige tijd min 30 dagen en kan niet ouder worden ingesteld. endTime is standaard nu. Het endpoint is dus een voortschuivend venster van één maand, geen archief.

Het gevolg is bot. Als je pollingtaak stukgaat en niemand het vijf weken lang merkt, zijn de ongeldigmakingen van week één uit de API verouderd. Er is geen aanroep die ze terugbrengt. Je trekt die bestellingen niet in, en je zult zelfs niet weten dat ze hebben bestaan, tenzij je ze op een andere manier hebt vastgelegd. De API is een vangnet met een gat zo groot als je ergste storing.

De revoke-optie bepaalt of een bestelling überhaupt verschijnt

Dit is de allervaakst voorkomende reden waarom een team de API als defect meldt. Alleen bestellingen met revoke worden geretourneerd. Door de gebruiker geïnitieerde terugbetalingen, annuleringen, chargebacks en door Google geïnitieerde terugbetalingen krijgen altijd revoke, dus ze verschijnen altijd. Een door de ontwikkelaar geïnitieerde terugbetaling is anders. Wanneer je een bestelling zelf terugbetaalt, via de Play Console of de Orders API, kies je of je die ook wilt revoken. Betaal terug zonder revoke, en de bestelling is met de klant afgewikkeld maar duikt nooit op in de Voided Purchases API.

De regel die daaruit volgt, is simpel. Als het je bedoeling is toegang in te trekken, betaal dan terug met de revoke-optie aan. Anders heb je het geld teruggegeven en de deur open laten staan, en heeft je intrekkingstaak, hoe goed ook geschreven, niets om op te handelen.

Hoe je het pollt zonder de quota te overschrijden

Het endpoint is rate-limited, en de limieten zijn laag genoeg dat een naïeve lus ze zal raken. Je krijgt 6,000 query's per dag, geteld in Pacific Time, en niet meer dan 30 query's in elke periode van 30 seconden. Dat budget is prima voor pollen met vensters en vijandig voor ontwerpen met één verzoek per bestelling.

Queryvensters en de continuation token

maxResults is standaard 1,000, wat ook het plafond is. Wanneer een venster meer dan één pagina met ongeldigmakingen bevat, draagt de respons een tokenPagination-object met een nextPageToken. Geef dat token terug bij de volgende aanroep om door de pagina's te lopen. Stel startTime en endTime in om het venster af te bakenen waar het je om gaat, blader tot het token op is, en schuif dan het venster op. Dat patroon houdt je binnen zowel de burstlimiet van 30 seconden als de daglimiet.

Real-time developer notifications dichten het gat

Elke dag pollen laat nog steeds tot een dag blindheid over, en het venster van 30 dagen straft lange onderbrekingen af. Real-time developer notifications halen de vertraging weg. Google publiceert een VoidedPurchaseNotification naar een Cloud Pub/Sub-onderwerp dat jij bezit op het moment dat een aankoop ongeldig wordt gemaakt, en je backend verwerkt die binnen seconden. Het bericht is klein.

RTDN fieldWat het bevat
purchaseTokenHet token van de oorspronkelijke aankoop
orderIdDe bestel-id voor de ongeldig gemaakte transactie, een nieuwe per abonnementsverlenging
productType1 voor een abonnement, 2 voor een eenmalige aankoop
refundType1 voor een volledige terugbetaling, 2 voor een op hoeveelheid gebaseerde gedeeltelijke terugbetaling
Een hand die een messing hangslot dichtdoet over een stapel bonnetjes naast een smartphone, ter illustratie van het intrekken van toegang nadat een Google Play-aankoop ongeldig is gemaakt

Wat dit je in geld kost

De API is leidingwerk, maar de reden om haar aan te sluiten is een rekening. Elke ongeldigmaking in die lijst komt overeen met een echt getal, en twee ervan worden duurder.

De chargeback-rekening komt vanaf 3 augustus 2026 bij jou terecht

Vanaf 3 augustus 2026 verschuift Google de kosten van een chargeback naar de ontwikkelaar. Je verliest de aankoopprijs en je betaalt daarbovenop de chargeback-vergoeding van de bank. Een voidedReason van 7 is niet langer alleen een verloren verkoop, het is een post met een vergoeding eraan vast. Je kunt een chargeback niet terugdraaien, hij is definitief bij de bank, maar je kunt het bloeden erna wel stoppen. De ongeldigmaking snel opvangen laat je het recht intrekken en, voor alles wat je nog levert, stoppen met uitgeven aan een klant die is terugbetaald en daarna teruggeboekt.

Je blijft betalen om een terugbetaalde klant te bedienen

De aankoopprijs is weg op het moment dat een ongeldigmaking verschijnt. Wat je nog wel in de hand hebt, is de kost van blijven leveren. Elk uur dat een terugbetaald recht actief blijft, blijf je betalen voor de dingen die de klant niet langer financiert: rekenkracht, model-API-aanroepen, opslag en elke uitbetaling aan makers of partners die aan zijn gebruik gekoppeld is. Een intrekkingssysteem dat door deze API wordt aangedreven, is hoe je die meter uitzet. Sla het over, en je financiert het product voor mensen die de store al schadeloos heeft gesteld.

Friendly fraud is een patroon dat het waard is om te volgen

Een voidedReason van 5 of 6 is geen eenmalig geval. Fraud en friendly fraud clusteren per account, per apparaat, en soms per promotie. De API geeft je de voidedSource en voidedReason bij elke ongeldigmaking, wat genoeg is om misbruik per account te volgen in plaats van elke terugboeking als een op zichzelf staande kost te behandelen. Een klant die twee keer een chargeback doet, vertelt je iets wat de eerste terugbetaling niet deed.

Het aansluiten op de RefundHalt-manier

Het model is klein zodra je alle stukjes vasthebt. Luister in real time naar VoidedPurchaseNotification zodat er niets een hele dag wacht. Roep de Voided Purchases API aan als bron van waarheid, gesleuteld op orderId zodat abonnementsverlengingen nooit verward raken. Lees voidedSource en voidedReason zodat een chargeback anders wordt afgehandeld dan een spijt-terugbetaling. Poll volgens een schema dat strak genoeg is dat het venster van 30 dagen nooit bijt, en betaal terug met de revoke-optie aan wanneer het je bedoeling is toegang af te snijden.

Dit is het deel dat RefundHalt voor je uitvoert. Het verwerkt de real-time meldingen, verzoent elke ongeldigmaking met de API, trekt precies de bestelling in in plaats van het hele product, en scheidt een bankchargeback van een gewone terugbetaling zodat de dure worden gemarkeerd, niet begraven. Je krijgt toegang binnen seconden ingetrokken en een registratie van wie wat en waarom ongeldig maakte, zonder zelf een Pub/Sub-pijplijn en een pollingtaak op te zetten.

Veelgestelde vragen

Waarom verschijnen mijn terugbetaalde bestellingen niet in de Voided Purchases API?
Omdat alleen bestellingen met revoke worden geretourneerd. Terugbetalingen van gebruikers, annuleringen, chargebacks en door Google geïnitieerde terugbetalingen krijgen altijd revoke en verschijnen altijd. Een door de ontwikkelaar geïnitieerde terugbetaling verschijnt alleen als je ook de revoke-optie hebt gekozen. Als je een bestelling hebt terugbetaald zonder die te revoken, is de bestelling afgewikkeld maar onzichtbaar voor deze API, dus betaal terug met revoke aan wanneer je van plan bent toegang in te trekken.
Hoe ver terug gaat de Voided Purchases API?
Dertig dagen. De parameter startTime is standaard de huidige tijd min 30 dagen en kan niet ouder worden ingesteld, dus het endpoint is een voortschuivend venster van één maand in plaats van een archief. Een ongeldig gemaakte bestelling die ouder wordt dan 30 dagen is uit de API verdwenen zonder manier om die op te halen, en daarom poll je volgens een schema en onderbouw je het met real-time meldingen.
Moet ik real-time developer notifications of de Voided Purchases API gebruiken om toegang in te trekken?
Gebruik beide. De VoidedPurchaseNotification komt binnen seconden binnen en vertelt je te kijken, maar Google's eigen richtlijn is om het als een signaal te behandelen, niet als een bron van waarheid. Roep de Voided Purchases API aan om de huidige staat te bevestigen, en trek dan in. De melding haalt de vertraging weg, en de API geeft je de gezaghebbende voidedSource en voidedReason om op te handelen.
Hoe onderscheid ik een chargeback van een gewone terugbetaling in de API?
Lees het veld voidedReason. Een waarde van 7 is een chargeback, wat betekent dat de bank van de klant de betaling heeft teruggedraaid, en 6 is friendly fraud. Een waarde van 1 is een spijt-terugbetaling. Dit is van belang omdat Google vanaf 3 augustus 2026 de aankoopprijs van de chargeback en de bankvergoeding doorschuift naar de ontwikkelaar, dus een voidedReason van 7 kost je meer dan een gewone terugbetaling.
Dekt de Voided Purchases API abonnementen?
Ja. Zet de parameter type op 1 om zowel ongeldig gemaakte in-app-aankopen als ongeldig gemaakte abonnementsaankopen te krijgen. De standaard, type 0, retourneert alleen in-app-productaankopen. Voor abonnementen identificeer je de precieze ongeldig gemaakte periode op orderId, omdat één purchaseToken elke verlenging dekt en er voor elke verlengingstransactie een nieuwe orderId wordt gegenereerd.

Bronnen en verder lezen

RefundHalt

De terugbetalingsautopiloot voor de App Store en Google Play

Lees verder

Het volgende terugbetalingsverzoek is al onderweg.

Stel RefundHalt in binnen de tijd die het kost om nog een supportmail te lezen over een terugbetaling die je niet kon betwisten.