Chapter 4: Subscriptions with RevenueCat
Working with subscriptions directly means navigating the three-tier Google Play hierarchy: Subscription → Base Plan → Offer. You call queryProductDetailsAsync() and get back nested SubscriptionOfferDetails objects you must parse and select from manually.
With RevenueCat, the three-tier hierarchy is still there on the Google Play side, but the SDK presents it through a simpler abstraction: Offerings → Packages → SubscriptionOptions.
How RevenueCat Maps the Hierarchy

In the RevenueCat dashboard, you map Google Play products and base plans to Packages inside Offerings. The mapping looks like this:
A Package has a product property of type StoreProduct. A StoreProduct for a subscription has a subscriptionOptions list, where each SubscriptionOption represents either a base plan or an offer.
Fetching Subscription Products
The PackageType enum gives you named access to standard durations: MONTHLY, ANNUAL, WEEKLY, TWO_MONTH, THREE_MONTH, SIX_MONTH, LIFETIME. Custom package types have PackageType.CUSTOM.
Selecting the Right SubscriptionOption
When you pass a Package to PurchaseParams, the SDK selects the defaultOption automatically. The default option selection logic:
- Filters out options tagged
"rc-ignore-offer"or"rc-customer-center" - Chooses the option with the longest free trial or cheapest first phase
- Falls back to the base plan if no offers qualify
This means users automatically get the best available offer without you writing selection logic.
If you want to present a specific offer to the user, for example, a win-back offer only for returned subscribers, access the SubscriptionOption directly:
Displaying Trial and Introductory Pricing
Each SubscriptionOption has a pricingPhases list. The first phase may be a free trial or discounted intro price:
Free Trial Eligibility
Google Play returns only the offers a user is eligible for in queryProductDetailsAsync(). RevenueCat passes through whatever Google returns in subscriptionOptions without additional eligibility filtering. The SDK's defaultOption selection logic does filter out options tagged "rc-ignore-offer" or "rc-customer-center", but it does not perform trial eligibility checking, that is handled at the Google Play layer before data reaches the SDK.
If a user has already used their free trial for a product, Google simply will not include that trial offer in the returned options. The base plan option will be selected as defaultOption in that case.
Prepaid Plans
Prepaid base plans work the same way as standard base plans from the RevenueCat API perspective. The SubscriptionOption for a prepaid plan will have pricingPhases with RecurrenceMode.NON_RECURRING.
To support pending purchases for prepaid plans, enable the option during SDK configuration:
Checking Active Subscriptions
After a successful purchase:
RevenueCat computes isActive server-side, accounting for grace period, account hold, cancellation with remaining time, and expiry. You do not replicate that logic.