Use Google Play RTDN for fast event handling. Use the Voided Purchases API to check voided orders and reconcile your records. For most paid apps, the safer choice is both.
If you are planning Google Play refund defense for apps, start with that split. One path tells you that something changed. The other lets your server fetch a list of voided purchases and check what it has missed.
The choice is not quite between two notification systems. Google Play RTDN pushes messages through Cloud Pub/Sub. The Voided Purchases API is a pull API: your backend calls it.
Neither, by itself, stops someone from requesting a refund. Their value is in detecting changes, checking orders, and making sure paid access matches the purchase state.
Key takeaways
Use RTDN to react to purchase and subscription events promptly.
Use the voided-purchase list as a second path for checking affected orders.
Do not treat a canceled subscription as proof of a refund.
Make both paths use the same safe access-update logic.
Keep pending chargeback review separate from a completed void.
What is Google Play RTDN?
Google Play Real-Time Developer Notifications, usually called RTDN, sends purchase-related events to a Cloud Pub/Sub topic.
Your backend receives a message and routes it to the right worker. The message type matters. A renewal, a cancellation, and a voided purchase are not the same event.
For refund tracking, pay close attention to voidedPurchaseNotification. It includes:
purchaseToken: links the event to a purchase.
orderId: identifies the affected order.
productType: identifies a subscription or one-time purchase.
refundType: distinguishes a full void from a quantity-based partial refund.
Google’s RTDN reference and event definitions explain these fields and the other notification types.
RTDN is useful when you want to act soon after a change. But a message is not your full purchase database. Match it to stored records and retrieve the relevant purchase state where needed before changing access.
Does a subscription cancellation mean a refund?
No. A customer can stop future renewals while still having paid access for the rest of the current term.
Do not build a rule that removes access whenever SUBSCRIPTION_CANCELED arrives. Check the subscription state and expiry instead. Revocation and expiry need their own handling.
What is the Voided Purchases API?
The Google Play Voided Purchases API returns a list of purchases that were canceled, refunded, or charged back within its supported scope.
It applies to one-time in-app orders and subscriptions. Your server can use the results to check which purchases should no longer grant access.
The list can include the order ID, purchase token, void time, void source, and void reason. For supported quantity-based partial refunds, it can also include the refunded quantity.
Google’s Voided Purchases API guide documents a 30-day lookback. It is not a permanent refund archive. Save processed records in your own system.
This API is especially useful after a worker outage, a routing bug, or a gap in your local records. It also gives you a routine check against the events you processed.
RTDN vs Voided Purchases API: the practical difference
Question | Google Play RTDN | Voided Purchases API |
How does it work? | Google publishes an event to Pub/Sub. | Your server requests a list. |
What is its main role? | Prompt handling of purchase-state changes. | Checking and reconciling voided orders. |
Does it cover events beyond refunds? | Yes, including renewals and other lifecycle events. | It focuses on voided purchases. |
Can it help after a processing gap? | Pub/Sub recovery depends on your setup and retention. | It can list available records within the 30-day window. |
Does it need duplicate protection? | Yes. | Yes, especially when scans overlap or share events with RTDN. |
The key question is not which tool is better in isolation. It is which failure each tool helps you handle.
RTDN gives you a fast path. The API gives you a checking path. Your own database should bring them together.
Which one should your app use?
Use RTDN when speed matters
A paid app should not need to wait for a scheduled scan before it notices a purchase-state change.
Use RTDN when your app needs prompt updates for subscriptions, one-time purchases, and voided orders. Route each event by type rather than applying one refund rule to all messages.
Use the API when completeness matters
Use scheduled API checks to find voided orders your worker did not apply to your records.
For example, your receiver may have accepted a message, but a bug may have stopped the later access update. Fixing delivery alone will not fix that local gap.
Use both for a production refund workflow
For most paid apps, combine them. Have both paths feed one shared handler that checks the order and applies any change safely.
This reduces the risk of one missed event leaving access active. It also reduces the opposite risk: removing access twice for the same refund.
How to detect Google Play refunds step by step
1. Keep a purchase ledger
Store the app package, purchase token, order ID, product, user mapping, and granted quantity. A ledger is simply a clear record of what was bought and what access it granted.
For subscriptions, store renewal order IDs too. The RTDN reference notes that each auto-renewal has a new order ID. A purchase token alone is not enough to identify every affected renewal.
2. Secure and route RTDN messages
Configure Pub/Sub access correctly. For push delivery, verify the authenticated request. For pull delivery, restrict who can read the subscription.
Decode the message, check the package name, and save it before running slow work. Send test events through the full path, not just the receiving endpoint.
3. Run a scheduled voided-purchase scan
Call the list method with suitable credentials and Play Console permissions. Follow all result pages.
Two query settings are easy to miss:
type=1 includes both one-time purchases and subscriptions. The default, 0, includes only one-time purchases.
includeQuantityBasedPartialRefund=true includes supported quantity-based partial refunds. Its default is false.
Google’s voidedpurchases.list method reference covers the request and pagination fields.
Use a modest overlap between scans and deduplicate the results. Choose the scan rate based on your volume, quotas, and how much delay your app can accept. Do not wait until the lookback window is almost over.
4. Apply each change only once
Both paths may report the same void. Build idempotent handling: running the same change again should not change the result.
Do not use the order ID alone to discard every later event. A multi-quantity purchase can have several partial refunds. Track processed adjustments and refunded quantities so a real later refund is not lost.
5. Monitor the gap, not just the message count
Track the last successful scan, unfinished pages, worker errors, and unmatched orders. Measure how long it takes to update access after a confirmed event.
For broader reporting, see our guide to mobile app refund and chargeback tracking tools.
Example: one refund, two detection paths
This is a hypothetical workflow, not a reported customer case.
A player buys a one-time pack that grants 500 coins. The purchase is later fully voided.
RTDN sends a voided-purchase message. Your worker finds the order, checks the recorded grant, and applies your published policy to the coins linked to that purchase.
Later, the scheduled API scan returns the same order. The shared handler sees that the full-void adjustment was already applied. It records the match and makes no second deduction.
Now suppose the worker failed before applying the first change. The scan finds the order and gives your system another path to process it.
That is the point of using both. Not two separate punishments, but two ways to reach one correct result.
If some coins were already spent, do not blindly remove coins from an unrelated paid pack. Use a clear policy, explain the action, and provide a support route.
Pending refund review is a separate workflow
Current Google documentation also lists pendingRefundReviewNotification for a chargeback request that requires developer review.
For that event, Google says to provide a refund suggestion and purchase usage evidence through orders.reviewrefund within 24 hours.
Do not confuse it with voidedPurchaseNotification. One concerns a pending review. The other reports a purchase that has been voided.
The Voided Purchases API is not a replacement for handling a pending review event. Keep that branch separate, and do not assume every refund request produces it.
App Store refunds and revenue leakage: what developers need to know
Revenue leakage is not limited to whether a store returns money. It can also mean your backend keeps granting paid access after the relevant purchase no longer supports it.
For teams on both platforms, the goal is similar: keep money, purchase state, and access records aligned. The store tools and event rules are different, though. Do not copy an Apple workflow into Google Play unchanged.
Our guide to App Store refund revenue management covers the wider revenue-management problem. For this Google Play integration, focus first on missed voids, duplicate deductions, and incorrect subscription access changes.
What Google Play refund fraud prevention can and cannot do
Google Play refund fraud prevention starts with sound records and fair rules. A voided order is not proof that the customer acted dishonestly.
A user may have a valid complaint. A payment may fail. Your app may have delivered the wrong item.
Use these tools to check facts and apply access changes. Review repeated patterns in context. Avoid automatic account bans based on one refund, and let customers challenge mistakes.
Neither RTDN nor the list API guarantees that you can prevent, reject, or reverse a refund.
Conclusion
The RTDN vs Voided Purchases API choice is not an either-or decision for most paid apps.
Use RTDN to react quickly. Use scheduled voided-purchase checks to reconcile records. Send both through one safe handler, and keep pending reviews separate from completed voids.
Start with a small test: send one void through both paths and confirm that access changes only once. Then stop your worker and check that your recovery path catches the gap.
Frequently asked questions
RTDN is better suited to prompt event handling. The API is better suited to scheduled checks of voided orders. Most paid apps benefit from both.
Yes. It includes a voided-purchase notification with order and refund-type details. Handle that event separately from a subscription cancellation.
You can detect available voided records through polling, but detection waits for your next successful scan. You also miss RTDN’s broader lifecycle event stream.
Google documents a 30-day window. Keep your own records for longer-term checks and support needs.
Yes. Enable the supported partial-refund results in list requests. Track refunded quantities and allow for more than one partial refund on an order.



