All articles
Deep dive7 min read

A voided purchase notification lets your Google Play server revoke access the moment a refund lands

Google Play can push your server a voided purchase notification the instant a purchase is refunded, charged back, or voided. It carries a purchaseToken, orderId, productType, and refundType, and it means one thing, revoke access. Here is how to read it and wire it up.

A developer workspace at dusk with a phone showing a reversed payment, illustrating a Google Play voided purchase notification reaching a server

Key takeaways

  • A voided purchase notification is a Real-time Developer Notification that Google Play pushes to your Cloud Pub/Sub topic the moment a purchase is refunded, charged back, or otherwise voided. It is a push signal, not something you have to poll for.
  • The notification carries exactly four fields: `purchaseToken`, `orderId`, `productType`, and `refundType`. That is enough to find the exact purchase in your database and revoke the entitlement tied to it.
  • `productType` is `1` for a voided subscription and `2` for a voided one-time purchase. `refundType` is `1` for a full refund and `2` for a quantity-based partial refund, which applies only to multi-quantity one-time purchases.
  • A voided purchase notification means the customer already has their money back. Google's own guidance is to revoke access to the associated content, because the buyer should no longer hold the entitlement.
  • Voided purchase notifications are off until you turn them on. In Play Console under Monetization setup you pick either subscriptions plus all voided purchases, or that plus one-time product events. Both options include voided purchases.
  • A voided purchase notification is not one of the two refund flows that ask you for evidence. It is an after-the-fact notice. The only flows that take your input are Apple's CONSUMPTION_REQUEST, with a 12-hour window, and Google Play's chargeback review through orders.reviewrefund, with a 24-hour window.
  • From August 3, 2026, Google passes the purchase price plus the bank fee of a chargeback to the developer. A voided purchase notification is often how your server first learns a chargeback void has landed, so wiring it up is what lets you stop serving a customer you are no longer paid for.

A refund on Google Play does not have to be something you discover later in a report. Google Play can push your server a voided purchase notification the instant a purchase is voided, whether the buyer took a self-service refund, a support agent granted one, a bank forced a chargeback, or you refunded the order yourself with the revoke flag on. The message is tiny, it names the exact purchase, and it carries one instruction, give back the entitlement, because the money is already gone.

What a voided purchase notification actually is

A voided purchase notification is one type of Google Play's Real-time Developer Notifications, or RTDN. RTDN is a push channel. Google publishes a message to a Cloud Pub/Sub topic you own, and your backend receives it within moments of the event, rather than finding out on your next scheduled poll. That is the whole point of the voided purchase notification over the older pull path: you learn about the refund as it happens, not hours later.

The pull path still exists and still matters. The Voided Purchases API lets your server ask, on your own schedule, for the list of purchases that were voided in a time range. The two are complementary. The notification tells you the instant one purchase flips; the API lets you reconcile in bulk and backfill anything a missed message would have left behind.

It rides inside a Real-time Developer Notification

The voided purchase notification never arrives on its own. It sits inside a DeveloperNotification wrapper, and that wrapper is delivered as a single base64-encoded string in the Pub/Sub message's data field. Your handler decodes that string to JSON before it can read anything. The wrapper always names the app and the event time, and it contains exactly one notification object out of the five Google defines. They are mutually exclusive, so a message that carries a voidedPurchaseNotification will not also carry a subscription or one-time event.

Wrapper fieldWhat it holds
versionThe notification schema version, for example 1.0
packageNameThe app the event belongs to, for example com.acme.app
eventTimeMillisWhen the event happened, in milliseconds since epoch
One of five notification objectsoneTimeProductNotification, subscriptionNotification, voidedPurchaseNotification, pendingRefundReviewNotification, or testNotification. Only one is present per message

The four fields it carries

Strip away the wrapper and the voided purchase notification itself is four fields. That is deliberately spare. Google's position is that if all you need is to find the right purchase and adjust entitlement, these four are enough, and you do not have to call back into any API to act.

FieldWhat it isHow you use it
purchaseTokenThe token handed to the device when the item was boughtYour primary key. Match it to the purchase record you stored at grant time
orderIdThe order id shown to the buyer, for example GS.0000-0000-0000A human-readable second key for support and reconciliation
productTypeWhether the voided item was a subscription or a one-time purchaseRoute to the right revoke path
refundTypeWhether the void was a full refund or a quantity-based partial refundDecide whether to revoke everything or just the refunded quantity

productType tells you what was voided

productType is a small integer, and it decides which of your revoke paths to take. A subscription void has to unwind ongoing access; a one-time purchase void just removes a single entitlement.

`productType` valueConstantMeaning
1PRODUCT_TYPE_SUBSCRIPTIONA subscription purchase was voided
2PRODUCT_TYPE_ONE_TIMEA one-time purchase was voided

refundType tells you how much came back

refundType separates a clean full reversal from a partial one. The partial case is narrow. It only appears when a multi-quantity one-time purchase had some, but not all, of its quantity refunded.

`refundType` valueConstantMeaning
1REFUND_TYPE_FULL_REFUNDThe purchase was fully voided
2REFUND_TYPE_QUANTITY_BASED_PARTIAL_REFUNDPart of a multi-quantity purchase was voided

Turn it on first, or it never arrives

Voided purchase notifications do not flow by default. You enable RTDN once, in Play Console, and point it at a Pub/Sub topic you control. The switch lives under Monetize, then Monetization setup, in the Real-time developer notifications section at the top of the page. Check Enable real-time notifications, then paste your full topic name in the form projects/{project_id}/topics/{topic_name}, and use Send Test Message to confirm the pipe works before you trust it.

The content toggle is where people miss voided purchases. Both choices include them, so you cannot accidentally opt out of refunds while keeping subscriptions.

  • Get notifications for subscriptions and all voided purchases. You receive subscription events and every voided purchase, but not one-time product purchase events.
  • Get all notifications for subscriptions and one-time products. You receive the above plus one-time product events such as ONE_TIME_PRODUCT_PURCHASED and ONE_TIME_PRODUCT_CANCELED.
A credit card face down beside a paper receipt, standing in for a voided Google Play purchase

What it costs you, in money

A void is a loss that is already booked by the time the notification reaches you. The sale price is gone, and so is whatever you spent serving that customer. If they generated images, ran calls against your models, pulled storage, or triggered a payout to a third party, those costs were paid in real money and do not come back with the refund. The notification cannot recover any of that. What it can do is stop the bleeding from here forward, which is the entire reason to act on it fast.

The bleeding is worst on subscriptions and worst on chargebacks. A subscription you fail to revoke keeps costing you to serve, month after month, for a customer who is no longer paying. And a chargeback is the most expensive kind of void. From August 3, 2026, Google's documentation states that a chargeback passes the purchase price plus the bank's fee to the developer. The voided purchase notification is frequently the first place your own systems hear that a chargeback has completed, so a handler that revokes on the spot is what keeps a lost sale from turning into a lost sale plus weeks of free service.

How to handle a voided purchase notification, step by step

Verify and dedupe the message

  • Confirm the Pub/Sub message came from Google and targets the topic you configured, then decode the base64 data field to get the DeveloperNotification JSON.
  • Use the Pub/Sub messageId to drop duplicates. Google warns that the same notification can be delivered more than once, so treat replay as normal and make your handler idempotent.
  • Acknowledge the message only after you have safely recorded it, so a crash mid-handler does not lose the event.

Look up the purchase

  • Match the purchaseToken against the purchase you stored when you first granted the entitlement. Fall back to orderId for support lookups and manual reconciliation.
  • Read productType to pick the subscription or one-time revoke path, and read refundType to decide between a full revoke and a partial one.

Revoke and record

  • Remove the entitlement. For a full refund, cut off access to the item. For a quantity-based partial refund, reduce the granted quantity by the amount refunded and leave the rest intact.
  • Write down what you did and when, keyed by purchaseToken and orderId. That record is what lets you answer a support ticket later, and what lets the Voided Purchases API reconcile cleanly against your own state.

Where it sits among the other refund signals

A voided purchase notification is a notice, not a negotiation. It tells you an outcome that is already decided. It is worth seeing it next to the signals it is easy to confuse it with, because only some of them ever ask for your side of the story.

SignalDirectionDoes it take your input
Voided purchase notification (RTDN)Google pushes to your serverNo. It reports a void that already happened
Voided Purchases APIYour server pulls from GoogleNo. It is a read-only list of past voids
pendingRefundReviewNotification (RTDN)Google pushes to your serverYes, indirectly. It flags a chargeback that you then contest through orders.reviewrefund within 24 hours
Apple CONSUMPTION_REQUESTApple asks your serverYes. You reply with Send Consumption Information inside 12 hours

The line to hold onto is simple. Across both stores there are exactly two refund flows where the developer gets a say, Apple's CONSUMPTION_REQUEST and Google Play's chargeback review. A voided purchase notification is neither. By the time it reaches you, the decision is behind you and the only thing left in your hands is how fast you revoke.

Frequently asked questions

What does a voided purchase notification mean on Google Play?
It means a purchase was refunded, charged back, or otherwise voided, and the customer has their money back. Google's guidance is to revoke access to the associated content, because the buyer should no longer hold the entitlement. The notification names the exact purchase through its `purchaseToken` and `orderId`.
What fields does a Google Play voided purchase notification contain?
Four: `purchaseToken`, `orderId`, `productType`, and `refundType`. `productType` is `1` for a subscription and `2` for a one-time purchase. `refundType` is `1` for a full refund and `2` for a quantity-based partial refund on a multi-quantity purchase.
How do I enable voided purchase notifications?
In Play Console, open Monetize then Monetization setup, and in the Real-time developer notifications section check Enable real-time notifications, then enter your Cloud Pub/Sub topic name. Both content options, subscriptions plus all voided purchases, and that plus one-time product events, include voided purchases.
What is the difference between the voided purchase notification and the Voided Purchases API?
The notification is a push signal delivered in real time through Cloud Pub/Sub the moment a purchase is voided. The Voided Purchases API is a pull path your server queries on its own schedule to list voids over a time range. Use the notification to react instantly and the API to reconcile and backfill.
Does a voided purchase notification let me contest the refund?
No. It is an after-the-fact notice of a decision that is already made. The only Google Play flow that takes your input is the chargeback review through `orders.reviewrefund`, which you have 24 hours to answer, and on Apple it is the CONSUMPTION_REQUEST with a 12-hour window.

Sources and further reading

RefundHalt

The refund autopilot for the App Store and Google Play

Keep reading

The next refund request is already on its way.

Set up RefundHalt in the time it takes to read another support email about a refund you didn't get to contest.