Apple Monthly Subscription with 12-Month Commitment
How RevenueCat supports Apple annual subscriptions with monthly commitment terms.
Apple’s Monthly Subscriptions with a 12-Month Commitment bill monthly, but requires the customer to stay active for 12 billing periods. Customers can cancel at any time, but the subscription remains active through the end of the commitment term. If the customer reaches the 13th month, the commitment renews automatically for another 12 months.
These products use the same App Store product ID for two billing plan options:
- 1 Year Upfront: a standard annual subscription with one upfront payment.
- Monthly with 12-Month Commitment: monthly billing with a 12-month commitment.
Overview
- The commitment enforces service for 12 billing periods.
- Customers can cancel anytime, but the subscription stays active until the commitment ends.
- If the customer reaches the 13th month, the subscription continues as another 12-month commitment.
- App Store Connect models both billing plans under the same product ID, while RevenueCat represents them as separate products.
Availability
- Available worldwide except for the United States and Singapore.
- Requires building your app with Xcode 26.5+.
- Requires customers to be on iOS 26.4+.
- Requires using the SDK in StoreKit 2 mode.
- Available in the native iOS SDK in versions 5.76.0+, support in the hybrid SDKs is coming soon
Product setup
To create your product in the App Store, open App Store Connect and follow these instructions:
- Create the subscription product with an annual duration.

- Add the 1 Year Upfront billing plan first.


- Add the Monthly with 12-Month Commitment billing plan.
- The monthly billing option is only available in regions where upfront billing is already configured.


- Set prices for each plan.
- The 12-month commitment total must be at least equal to the upfront price and no more than 1.5× the upfront price.

- Optionally attach subscription offers to each billing plan.
- Introductory offers, promotional offers, win-back offers, and offer codes are configured at the billing-plan level.

- Finish the normal subscription product configuration.
How to model this in RevenueCat
In RevenueCat, treat each billing plan as its own product:
- Create the upfront annual product as usual.

- Create a second RevenueCat product for the monthly commitment plan.
- Enable the 12 months commitment option so RevenueCat knows this product represents the monthly commitment plan.

This setup lets RevenueCat track each billing option separately while still mapping them to the same App Store product.
When you create the monthly commitment product in RevenueCat and enable the 12 months commitment option, RevenueCat automatically generates the RevenueCat product ID by appending :monthly to the App Store product ID. That means the monthly commitment product is represented as <apple_product_id>:monthly in RevenueCat.
For API calls, webhooks, SDEs, charts, and other reporting tools, use the colon-form product ID for the monthly commitment product. If you query or filter by product ID, fetch the product using the :monthly suffix so you get the monthly commitment variant rather than the default upfront plan.
Platform product and plan IDs
RevenueCat offerings now expose these products using the same pattern we use for Google:
platform_product_idplatform_plan_id
For monthly commitment products, platform_plan_id is monthly. If the plan ID is null, RevenueCat falls back to the default (upfront) billing option.
API and endpoint behavior
- The
subscribersandentitlementsendpoints expose the same product/plan structure. - Purchases of annual commitment products are processed, mapped to the right RevenueCat products, and unlock the associated entitlements.
- Webhooks, integrations, and public endpoints expose the new product ID format (
<apple_product_id>:monthly) where needed.
SDK
Purchasing a Monthly with 12-Month Commitment product
RevenueCat exposes the monthly commitment plan as a separate product ID using the :monthly suffix. On iOS 26.4 and later you can load it directly. On earlier OS versions, loading this plan may return nil, so you'll need to fallback to purchasing the upfront annual option instead.
Support for 12-month commitment products in RevenueCat Paywalls is coming soon. Until that support is available, load the :monthly product directly in your paywall logic and use targeting to show it only to eligible devices.
To purchase a 12-month commitment product on your custom paywall, pass the 12-month commitment package or product to the purchase() function like you would for any other product:
- Swift
func purchase(packageToPurchase: Package) async {
do {
try await Purchases.shared.purchase(package: packageToPurchase)
} catch {
// TODO: Handle error
}
}
Show monthly commitment details on your paywall
Fetch the :monthly product and read installmentsInfo so you can display the commitment term, total cost, and monthly billing details clearly on your paywall.
- Swift
let upFrontProduct = await Purchases.shared.products(["com.myapp.product"]).first
// upFrontProduct?.installmentsInfo is nil since this is an upFront product
// Returns a product on iOS 26.4+, returns nil on iOS < 26.4,
// where products with billing plans are unavailable.
let productWith12MonthCommitment = await Purchases.shared.products(
["com.myapp.product:monthly"]
).first
// You can also use fetch the InstallmentsInfo from a product in a package
let currentOffering = try await Purchases.shared.offerings().current
if #available(iOS 26.4, *) {
let installmentsInfo = offering?.package(identifier: "12mo_commitment")?.storeProduct.installmentsInfo
}
// The InstallmentsInfo contains all necessary information related to the commitment
// and each individual payment installment.
if #available(iOS 26.4, *) {
guard let installmentsInfo = productWith12MonthCommitment?.installmentsInfo else {
return
}
// Display installment information on your paywall
let commitmentTotalPeriod = installmentsInfo.commitmentTotalPeriod // 1 year
let totalPrice = installmentsInfo.commitmentTotalPrice // 59.98
let totalPriceDisplayString = installmentsInfo.commitmentTotalDisplayPrice // "$59.98"
let numberOfInstallments = installmentsInfo.commitmentInstallmentsCount // 12
let installmentPeriod = installmentsInfo.commitmentInstallmentPeriod // 1 month
let installmentPrice = installmentsInfo.installmentBillingPrice // 4.99
let installmentDisplayPrice = installmentsInfo.installmentBillingDisplayPrice // "$4.99"
}
Apple's docs for 12month commitment products state that developers are required to display both the monthly billing price and the total commitment amount to the customer before they initiate a purchase, so be sure to include those values on your paywall. You can retrieve these values from InstallmentsInfo.installmentBillingDisplayPrice and InstallmentsInfo.commitmentTotalDisplayPrice, respectively.
Use targeting for iOS 26.4+ eligibility
Because the monthly commitment plan is only available on iOS 26.4 and later, use RevenueCat's Targeting feature to surface a different paywall for customers who are eligible to purchase it. This helps avoid showing an option that may be unavailable to older devices.
- Show the
:monthlyproduct only to customers whose devices are iOS 26.4+. - Use a fallback paywall for customers on earlier OS versions or devices that cannot load the monthly commitment product.
Managing monthly with 12-month commitments
Upgrade, downgrade, and crossgrade behavior
Apple controls these transitions within the subscription group for commitment plans:
- Upgrade: immediate. The existing commitment ends when the new higher-tier plan activates.
- Downgrade: deferred until the current 12-month commitment finishes.
- Crossgrade: timing depends on the durations and billing plan types of both plans.
RevenueCat follows Apple's subscription group behavior for these transitions.
When attempting to switch billing plans (upfront to monthly or vice versa) via product.purchase(), customers may encounter "You're already subscribed to this" alerts and plan changes may not process. Contact RevenueCat support if you encounter this in production.