How to detect subscription is expired

  • 15 July 2022
  • 5 replies

Badge +4


I am trying to convert a paid app into subscription, but I am facing a situation which I need help. I know I can detect the active subscriptions via active entitlements:


and detect if any entitlements are not active then lock the premium version for example. But I am converting a paid app into subscription, so I detect if the user is purchased the app before and unlock it  using customerInfo.originalApplicationVersion. 

That creates a conflict situation, I am unlocking the pro features for previous users and then there is no active subscription for that user in customerInfo, so the in this code:

@Published var customerInfo: CustomerInfo? {

didSet {

if !customerInfo! {


} else {





I lock pro version for a user that hasn’t any subscription, it conflicts for previous user who bought the app. So I am looking for an API to lock the pro features only if the subscription is expired not Active/Not-Active entitlements  in general. I hope I explained correctly.


5 replies


Hi @DinoDeveloper 


If I understand correctly you want to keep access to users who purchased the app while new ones will go through the subscription model.


One way I can think of achieving this is giving lifetime access to users who purchased and check the expiration date that will be returned as null for those. And for others that are using subscriptions you can check that the Expiration Date is not past due before unlocking the pro version. Could this help?

Badge +4

Hi @Roberto Ansuini!

Please take a look at this image:

There are two scenarios:

  • A: The app actives pro features for a paid user after checking the original application version.
  • B: The app checks the active entitlements and unlocks the pro for active subscriptions, while there is no active subscription for a paid user so the app locks the pro version.

SOLUTIONThere should be an expiration detection API ( I know I can access the expiration date in customer info), but I want a simple solution to lock the app only for people who have expired subscriptions. Using non-active entitlements locks the pro version for all users no matter if they purchased the app before.


Hi @DinoDeveloper 


Thank you for your response, I will check with my colleagues to see how this have been solved for other customers with similar usecases.


Meanwhile I believe that the cleanest solution is to create an entitlement with Lifetime Unlock for customers who purchased the app before. That way when you check active entitlements for these customers it will return the non expiring subscription for them, and for the rest you will go with the regular lifecycle of expirations.


Are the customers who purchased previous to using RevenueCat? If so you can use our migration process to bring those purchases to RC

Badge +4

Thank you, so far, I have implemented this using SwiftyStoreKit, to detect expired subscription, if you have any solution in RC, I would love to use it.



Hey @DinoDeveloper 


Here you can find a post about “Converting a Paid App to In-App Subscriptions” that explains what would be the best practices for doing the conversion you are going through. It basically uses a check on the originalApplicationVersion for users who purchased the app. Hope this helps.



func isActive(entitlement: String, result: @escaping ((Bool, Purchases.PurchaserInfo?) -> Void)) {        
2 Purchases.shared.purchaserInfo { (info, error) in
3 if let info = info {
5 /// If a user has access to an entitlement via RevenueCat, return true
6 if info.entitlements[entitlement]?.isActive == true {
7 return result(true, info)
8 } else {
10 /// If a user doesn't have access to an entitlement via RevenueCat, check original downloaded version and compare to registered backwards compatibility versions
11 if let originalVersion = info.originalApplicationVersion {
12 for version in self.registeredVersions {
13 if version.entitlement == entitlement, version.versions.contains(originalVersion) {
14 return result(true, info)
15 }
16 }
17 }
19 /// No registered backwards compatibility versions, or no available originalApplicationVersion to check against
20 return result(false, info)
21 }
23 } else {
25 /// PurchaserInfo not available, so not able to check against originalApplicationVersion
26 return result(false, nil)
27 }
28 }