Refunds, revocation, and voided purchases
A cancellation stops the next charge. A refund takes back a charge already made. The entitlement has to tell those apart, because one keeps access until the period ends and the other usually does not.
Two Google Play signals
Refunds are issued by Google or from Play Console; Tierux reacts to the notification Play sends afterwards. There are two shapes:
SUBSCRIPTION_REVOKED(subscription type 12). The subscription was revoked before its expiry — Play's signal for a refunded or charged-back subscription.voidedPurchaseNotification. A separate message shape for a purchase that was voided. It carries a product type (SUBSCRIPTIONorONE_TIME) and a refund type (FULL_REFUNDorQUANTITY_BASED_PARTIAL_REFUND).
Both write the same effect: status cancelled, access off immediately, and a refund event on the billing timeline and, if you have configured one, your outbound webhook. Neither waits for expiresAt. That is the difference from a plain cancellation, which writes cancelled but leaves access on — see the table in chapter 1.
// src/services/rtdnProcessor.ts case 12: // SUBSCRIPTION_REVOKED — immediate revoke (refund/chargeback) return { status: 'cancelled', active: false };
Partial refunds and one-time products
A voided purchase revokes access the same way regardless of its product type or refund type. A QUANTITY_BASED_PARTIAL_REFUND is treated like a full refund. The refund type is kept on the record as the raw store status, so you can see which kind it was when investigating.
The voided-purchase path is also how a refunded one-time product loses its entitlement. Play's one-time product notifications (purchased, canceled) do not change entitlements in Tierux; a one-time entitlement is granted at verify time, and a voided-purchase notification revokes it.
If your business rules call for something softer than "access off" on a partial refund — keeping a consumable balance, say — implement it on your side from the refund webhook event and the entitlement you read back.
Guards that still apply
- Superseded tokens. A refund on a token the entitlement no longer points at is ignored. This is what protects a subscriber's upgraded plan when Play voids the prorated remainder of the old one — see chapter 3.
- Duplicates and ordering. The message-id and event-time checks from the notifications chapter apply, so a redelivered refund does not append a second timeline event, and an older event does not overwrite a newer one.
- Unknown purchases. A refund for a token Tierux has no purchase record for is acknowledged without a write.
The win-back flag is not cleared on a Google Play refund
On Google Play, the revoke and voided-purchase effects set status and access but do not touch winbackPending. If a subscriber cancelled — which arms the flag when the product has a cancellation offer — and was then refunded, the entitlement can read active: false with winbackPending: true until a later event clears it (an expiry notification does). The Android SDK's showWinback decides eligibility from winbackPending alone, so check active yourself before calling it from your cancel action. How the flag is armed is covered in the cancellation win-back chapter; win-back is implemented for Google Play and not yet for the App Store.
A dashboard revoke is not a refund
For support cases, a developer can revoke a subscriber's entitlement from the Tierux dashboard. That writes cancelled with access off and adds a cancellation_pending entry to the timeline. It does not refund the subscriber and does not cancel their store subscription — the response says so explicitly, and directs you to Play Console or App Store Connect for the billing side. Use it to stop access; use the store to move money.
On the App Store
Apple's REFUND and REVOKE notifications map to the same effect — cancelled, access off, a refund event — and additionally clear winbackPending. Apple can also reverse a refund: REFUND_REVERSED restores active with access on, with no timeline event of its own. The App Store notification path is implemented with limitations — see the platform support matrix.
Glossary: Refund
Refund versus cancellation, and why the access result depends on the product.
Glossary: Entitlement
The access record a verified reversal changes.
Docs: Webhooks
Receiving the refund event on your own backend.
Feature: RTDN webhooks
Lifecycle events, refunds included, applied without polling.
Guide: Cancellation win-back with RTDN
The save-sheet flag this chapter warns about.
Refunds that revoke access on time
Free tier — unlimited apps, 1 paywall. No credit card, no revenue share.
Start free