Google Play subscription add-on refunds can target one item at a time, but your customer can only cancel the whole bundle
Google Play lets a base subscription carry up to 49 add-ons on one purchase token. Here's how subscription add-on refunds work, which API call refunds one item without touching the rest, where Google blocks it, and what each refund path costs you.

Key takeaways
- Google Play's subscription with add-ons feature puts a base subscription and up to 49 add-ons, 50 items in total, on one purchase, and every item must share the same recurring billing period.
- Google Play users can't cancel a single add-on from the Play Subscription Center. They can only cancel the base subscription and its add-ons together, so removing one add-on has to happen inside the developer's app.
- The purchases.subscriptionsv2.revoke method accepts an itemBasedRefund with one productId. If other items stay active, Google revokes and fully refunds only that item and the subscription keeps running.
- Google blocks an item-based refund when the subscription is in a payment declined state, when the item is expired or not owned, and on prepaid subscriptions.
- A proratedRefund on a subscription with add-ons refunds the latest order of every item, prorated by the time left until the next renewal, and revokes access to all items at once.
- Real-time developer notifications for a subscription with add-ons don't carry a subscriptionId, so a backend has to call purchases.subscriptionsv2.get and read each lineItem to see which items are still entitled.
- The only Google Play refund flow that asks the developer for evidence is a chargeback flagged for review through orders.reviewrefund, with a 24-hour window. For orders placed after August 3, 2026, a lost chargeback costs the developer the purchase price less Play's service fee, plus the bank's fees.
Sell a base subscription with three add-ons on Google Play and you can refund any one of those add-ons without cancelling the rest. Your customer can't do the same from their side. Google lets users cancel only the whole bundle, so the precise tools for Google Play subscription add-on refunds sit with you, the developer, and only through the API. Use them well and you refund the line that went wrong. Use the wrong call and you refund, or revoke, everything.
How a subscription with add-ons is built
Google announced multi-product checkout for subscriptions at I/O 2025. One purchase flow sells a base subscription plus optional add-ons, billed together on one schedule. Google's developer guide sets firm limits:
- Only auto-renewing base plans can carry add-ons. Prepaid plans can't.
- Every item must share the same recurring billing period. Monthly add-ons on an annual base aren't allowed.
- A purchase holds at most 50 items, which means one base and up to 49 add-ons.
- The feature isn't available in South Korea.
All of it lives on a single purchase token. When you call purchases.subscriptionsv2.get, the response carries a lineItems list, one entry per item. Each line item has its own productId, expiryTime and latestSuccessfulOrderId. That last field is what makes refunds per item possible: each item has its own latest order.
Proration starts on day one
When a user adds an add-on mid-cycle, Google charges a prorated amount right away so the add-on renews on the same date as the base. Google's own example is a $10 monthly add-on added on August 15 after a 7-day trial, charged $2.90 to cover the rest of August. So a single add-on can have a short, odd-sized first order before its first full one. Keep that in mind when you look up which order a refund will hit.
Your customer can only cancel the whole bundle
Google's consumer help page is blunt about it. Users can cancel the base subscription and add-ons only together, and they can't cancel individual add-ons from Google Play at this time. Pausing isn't available either. If a user turns down a price increase, Google cancels the base subscription and every add-on with it.
That leaves a customer who wants out of one add-on with two options in the Play Store: cancel everything, or ask for their money back. Neither is good for you. Google's guide says your app can offer the removal instead. A removed add-on expires at the end of its current billing period, and the rest of the bundle keeps renewing.
The Google Play subscription add-on refund tools, compared
Google gives you five ways to send money back on a subscription with add-ons. They differ in what they refund and whether access ends.
| Tool | What gets refunded | What happens to access |
|---|---|---|
| Play Console refund on a specific order | An amount you choose on that order | Nothing is revoked |
| orders.refund, revoke not set | The full amount of one order | Nothing is revoked |
| subscriptionsv2.revoke with itemBasedRefund | The full latest charge on one item | Only that item ends, unless it was the last active item |
| subscriptionsv2.revoke with proratedRefund | Each item's latest order, prorated to the time left | Every item ends immediately |
| subscriptionsv2.revoke with fullRefund | The full latest charge on each item | Every item ends immediately |
Google adds one hard warning in its add-ons guide: don't call the deprecated purchases.subscriptions.refund on a subscription with add-ons. And orders.refund can't touch orders older than three years.
How itemBasedRefund behaves
The itemBasedRefund object takes one required field, productId, naming the item to revoke. Google describes two outcomes:
- Other items are still active: only the named item is revoked and fully refunded, and the subscription carries on.
- No other items are active: the item is revoked, fully refunded, and the whole subscription is cancelled.
You can name one item per request. To refund two add-ons, make two calls.
When Google blocks an item-based refund
Google rejects an itemBasedRefund in three cases. The subscription is in any payment declined state, which covers grace period and account hold. The item you named isn't owned or has already expired. Or the purchase is a prepaid subscription, where item turn-down isn't supported at all.
What a refund by order ID does
Google's guide notes that the revoke flag on orders.refund only ends access if the order is the latest one on the subscription. On an older order, the refund succeeds and nothing is revoked. Play Console works the same way: refund the most recent order and the subscription is removed, refund an older one and it stays active. With add-ons, pick the order from the right line item's latestSuccessfulOrderId, or you may refund a different charge than the one you meant.
Who decides the refund, and when you're asked for evidence
Most refunds on a subscription with add-ons are decided without you, just like any other Play subscription. Inside 48 hours of a purchase, a user can ask Google through Report a problem, and Google decides. After that, Google sends them to you. And if you don't acknowledge a new subscription purchase within three days, Google refunds the user automatically and revokes the purchase.
Only one flow asks for your side of the story. When a cardholder files a chargeback and Google flags it for developer review, you get a PendingRefundReviewNotification and have 24 hours to call orders.reviewrefund with a refund preference and usage evidence. Chargebacks themselves are decided by the bank, and the bank's decision is final.
Tracking add-on refunds on your server
Google's RTDN reference lists SUBSCRIPTION_ITEMS_CHANGED for changes to an item in a subscription bundle, and SUBSCRIPTION_REVOKED for a subscription revoked before its expiration time. Google's guide says a revocation through subscriptionsv2.revoke triggers both a SUBSCRIPTION_REVOKED notification and a VoidedPurchaseNotification, and is recorded in the Voided Purchases API.
The catch is the subscriptionId. Google says it isn't provided in RTDNs for subscriptions with add-ons. So don't trust the notification to tell you which item changed. On every notification for a bundle:
- Call purchases.subscriptionsv2.get with the purchaseToken.
- Read every lineItem and its expiryTime. Google says you must refresh expiryTime for all items, not just the one you expect.
- Grant or remove access per productId, not per purchase token.
- Poll the Voided Purchases API as a backstop. It covers the past 30 days.
Grace period and account hold apply to the bundle
Payment trouble hits all items at once. Google picks the shortest grace period among the active items and applies it to the whole renewal. During grace, the user keeps every item. In account hold, access to all items is suspended. If the payment never recovers, the declined items expire and the other items resume for the rest of their billing periods.

What each refund path costs you in money
Add-ons usually map to something you pay for. Extra cloud storage is billed by your storage provider. An AI credits pack is billed in model API calls. An extra seat means more compute, and a creator tier may trigger a payout. Each of those costs is incurred when the user uses the add-on, and a refund returns the price without returning any of them.
Refunding too much
The expensive mistake is reaching for fullRefund or proratedRefund when the complaint is about one add-on. Both revoke every item, so you hand back the base price too and lose a subscriber who wanted to stay. An itemBasedRefund returns only that add-on's latest charge. When it's blocked, an orders.refund on that item's latest order returns the money without ending anything.
Partial refunds and fees
Play Console lets you issue partial refunds on subscription orders, and Google says the refund percentage also applies to your payout and service fee. Refund half an order and half of Google's fee comes back with it. Your own costs for serving that add-on don't.
Chargebacks on a bundle
For orders placed after August 3, 2026, Google moves chargeback costs onto developers. When a chargeback succeeds, you pay the purchase price less Play's service fee, plus the fees the bank charges. A bundle order with several add-ons is a bigger order to lose. Usage logs per add-on, keyed to the obfuscated account ID, are what you'd send in a 24-hour review.
A checklist for add-on refunds
- Ship an in-app way to remove one add-on, since Google Play doesn't offer one.
- Store each lineItem's productId, expiryTime and latestSuccessfulOrderId on every notification.
- Default to itemBasedRefund when one add-on is the problem.
- When the subscription is in grace period or account hold, refund the item's order with orders.refund instead.
- Never call the deprecated purchases.subscriptions.refund on a bundle.
- Log add-on usage per account so a chargeback review can go out inside 24 hours.
- Report refund rates per add-on, not just per subscription, so one weak add-on doesn't hide in the base plan's numbers.
Frequently asked questions
- Can a user cancel just one add-on in a Google Play subscription?
- Not from Google Play. Google's help page says users can only cancel the base subscription and add-ons together. Your app can offer removal of a single add-on, which then expires at the end of its current billing period.
- How do I refund one add-on without cancelling the subscription?
- Call purchases.subscriptionsv2.revoke with an itemBasedRefund naming the add-on's productId. If other items stay active, Google revokes and fully refunds only that item. You can also refund the item's latest order with orders.refund without the revoke flag, which returns the money and leaves access alone.
- Why did my itemBasedRefund call fail?
- Google blocks it when the subscription is in a payment declined state, when the item isn't owned or has expired, and on prepaid subscriptions. Check the line item's expiryTime and the subscription state before calling.
- Does a prorated refund work on a subscription with add-ons?
- Yes, but it revokes everything. Google refunds the latest order of each item, prorated by the time left until the next renewal, and access to all items ends immediately.
- Which RTDN tells me an add-on was refunded?
- Google's guide says revocation triggers SUBSCRIPTION_REVOKED and a VoidedPurchaseNotification, and SUBSCRIPTION_ITEMS_CHANGED covers changes to an item in a bundle. Because the subscriptionId is missing for bundles, call purchases.subscriptionsv2.get and read each lineItem to see what changed.
Sources and further reading
- Google Play Billing: Subscription with add-ons
- Google Play Help: Subscriptions with add-ons
- Google Play Developer API: purchases.subscriptionsv2.revoke
- Google Play Developer API: orders.refund
- Google Play Billing: Manage subscriptions and one-time purchases
- Play Console Help: Issue refunds and cancel orders
- Google Play Billing: Real-time developer notifications reference
- Google Play Billing: Subscription lifecycle
- Google Play Help: Request a refund on Google Play
- Google Play Developer API: orders.reviewrefund
- Play Console Help: Updates to refund protection and chargeback cost responsibility
RefundHalt
The refund autopilot for the App Store and Google Play
Keep reading
Excessive refund requests can cost you more than the refunds, because both app stores treat them as a quality signal
Apple's Guideline 5.6.4 names excessive refund requests as a sign an app isn't meeting quality standards, and Google's Distribution Agreement lets it remove new developers' apps on refund rates. Here's what each store says, what removal costs, and how to stay clear.
Verify App Store server notifications before you act on a refund, because anyone can post to your webhook URL
A refund notification is just an HTTPS request until you check its signature. Here's how to verify App Store server notifications and Google Play RTDN messages, what each store signs, and what a forged or wrongly rejected refund costs you.