Migrating Subscriptions

How to migrate subscriptions from your existing setup

If you already have an existing app that is using subscriptions, it's easy to migrate them over to RevenueCat. You can use the Purchases SDK to replace all of your in-app-purchase code, or you can just use it along side your current stack to track in-app-purchases and benefit from our charting, webhooks, and other integrations.

Determining Your Migration Path

Your migration path will depend on your app’s existing infrastructure and the data that you store. Use the flowchart below to determine which steps need to be taken to complete your migration.


Client Side Migration


This section assumes you've followed our Quickstart section of our Getting Started guide to install and configure our SDK.

The Purchases SDK automatically detects new transactions and sends them to RevenueCat. However, when migrating from an older system, you need to tell Purchases to sync to ensure we are tracking your subscribers correctly.

The way to do this is: if your existing subscription code knows you have a subscription, but RevenueCat does not, then programmatically sync purchases.

See the following pseudo example.

const isSubscribedInOldSystem = oldTracking.isSubscribed()
const isSubscribedInRevenueCat = !purchaserInfo.entitlements.active.isEmpty

// If the old system says we have a subscription, but RevenueCat does not
if (isSubscribedInOldSystem && !isSubscribedInRevenueCat) 
  // Tell Purchases to syncPurchases. 
  // This will sync the user's receipt with RevenueCat.
  Purchases.shared.syncPurchases { (purchaserInfo, error) in }

When a subscriber launches with the first version containing Purchases, it will trigger a sync. Once the sync is complete, it won't be triggered again.


Do not sync or restore on every app launch

It's okay to trigger a sync once per subscriber programmatically the first time they open a version of your app containing RevenueCat. You should not call this programmatically on every app launch for every user. This can increase latency in your app and unintentionally alias users together.


iOS Only: originalApplicationVersion in Sandbox

According to Apple, the originalApplicationVersion is always 1.0 in sandbox and TestFlight, which is unlike production where it reflects the build number of the app. If you're migrating your app and relying on originalApplicationVersion to determine which subscribers should have access in RevenueCat, try mocking different values of originalApplicationVersion to ensure the migration works as expected. You can learn more about originalApplicationVersion in Apple's docs.

Configure Server-Side Receipt Forwarding

To ensure that future in-app purchases from older versions of your app appear in the RevenueCat dashboard, you need to forward receipts of purchases on older app versions from your backend to our servers with the createPurchase API endpoint. Please configure the receipt forwarding before importing your existing data to guarantee that no data is lost during the migration process.

Importing Existing Data

Using the REST API

If you have the correct data saved already for your users, you can import them through the REST API POST /receipts endpoint. This will create the user in RevenueCat and start tracking their subscription status.

More info in the API Reference here.

Bulk imports

For large datasets that aren't practical to import through the REST API, you can send us a .csv file to import manually. Email us with the below information and we'll be in touch. Please note that depending on the size, bulk imports can take time to complete, sometimes up to several days or weeks for the largest data sets. Please keep this in consideration as you are planning your launch.


Bulk imports DO NOT trigger webhooks or integrations

Bulk imports done by RevenueCat will not trigger any webhook or integration events. If this is a requirement, then you'll need to perform an import using the REST API as mentioned above.

To do a receipt import we'll need 3 csv files for iOS, Android and Stripe with the following fields:


  • app_user_id
  • receipt (the raw receipt file)
  • product_id
  • price
  • introductory_price (if not a free trial)
  • currency

You can find a sample iOS reference csv file here.

*If you don't have prices and currency with the transactions we can take a separate file with a mapping of product_id, price, currency as well. If there were any known price changes, those should also be included here. You can find a sample price mapping here.


Product prices are required for iOS imports

Whether you include the products and prices with each receipt in the CSV file or attach a separate file of products and prices, the prices of products is required so that RevenueCat can accurately compute your charts and send events with correct revenue data.


latest_receipt_info not supported for iOS imports

The entire iOS receipt file must be used for imports. The latest_receipt_info is not supported as it's only a subset of the entire receipt.

Google Play:

  • app_user_id
  • product_id
  • token

You can find a reference Google Play import csv file here.

Important: We need to know your API quota with Google and approximately how many remaining requests per day you have so we don't exceed your quota.

*Note that Google Play receipts that expired more than 90 days ago can't be imported, and only the current status can be retrieved from each receipt. This means that historical data won't be presented accurately in charts.


  • app_user_id
  • subscription_token (e.g. sub_xxxxxx)

You can find a reference Stripe import csv file here.

*Note that Stripe subscription tokens contain only the current status can be retrieved from each Stripe subscription token. This means that Stripe charts for historical data won't be accurate.


Allow up to 7-days for bulk imports

Depending on the size of your import and the current queue, please allow up to a week for your import to be processed.

Use RevenueCat Backend Only (Observer Mode)

In some cases, if you have already built a functioning subscription system, it may not be possible or feasible to use the Purchases SDK to make purchases. However, you can still use the SDK to get access to the advanced charting, webhooks, and attribution that RevenueCat can provide.

Check our guide on Observer Mode for details on setting this up.

Next Steps