The Problem Every Developer Faces

You've decided to add in-app purchases or subscriptions to your app. You know the business logic you want — free tier, premium tier, annual discount — but the moment you open Apple's StoreKit docs or Google Play Billing's API reference, you're staring at hundreds of pages of platform-specific boilerplate: receipt validation, server-side verification, edge cases around interrupted purchases, sandbox environments, and more. And if you're building for multiple platforms? You're doing it all twice (or four times).

This is exactly the problem RevenueCat solves: a unified SDK that wraps StoreKit, Google Play Billing, and more, so you handle subscriptions once instead of per-platform. But even RevenueCat has platform-specific setup steps, and skipping or misconfiguring those steps is the most common cause of empty product lists, silent purchase failures, and build errors that developers hit early in integration.

This guide covers the exact steps — with the common gotchas called out — for iOS, Android, Flutter, and React Native.


Before You Write Any Code

Create Your RevenueCat Account and Project

Before installing any SDK, you need an account and a configured project at app.revenuecat.com. Every new project comes with a Test Store automatically, so you can start testing immediately without connecting to the App Store or Google Play. Source

Understand Your API Keys

RevenueCat uses two types of API keys, and mixing them up is a security risk and a common mistake: Source

Key Type Prefix Use Case
Public (SDK) key platform-specific Configure the SDK in your app
Secret key sk_ Server-side REST API calls only — never embed in your app

You find your public SDK keys under Project Settings > API keys > App specific keys in the RevenueCat dashboard. Each platform (iOS, Android) gets its own separate public key.

⚠️ Critical for hybrid SDKs (Flutter, React Native): You must use a separate API key for each platform. Pass the iOS key when running on iOS and the Android key when running on Android. Source


iOS Setup

Step 1: Install the SDK

RevenueCat for iOS supports three package managers. Swift Package Manager (SPM) is the recommended approach for most projects. Source

Via Swift Package Manager (Recommended)

In Xcode, go to File → Add Package Dependencies... and enter:

https://github.com/RevenueCat/purchases-ios-spm.git

💡 Speed tip: Use the -spm mirror repository (purchases-ios-spm) instead of the main repo. It resolves significantly faster. Source

Set the Dependency Rule to Up to Next Major, version 5.0.0 < 6.0.0. When prompted, select both RevenueCat and RevenueCatUI packages.

Via CocoaPods

Add to your Podfile:

pod 'RevenueCat'

Then run:

pod install

Via Carthage

Add to your Cartfile:

github "RevenueCat/purchases-ios"

Run with XCFrameworks support (recommended for Carthage >= 0.37):

carthage update --use-xcframeworks

Step 2: Enable the In-App Purchase Capability

This is the #1 missed step on iOS. Without it, your products will silently fail to load.

In Xcode: Project Target → Capabilities → In-App Purchase → toggle it on. Source

Step 3: Import and Initialize the SDK

Import RevenueCat in your AppDelegate or App entry point:

import RevenueCat

Initialize it early in the app lifecycle — application(_:didFinishLaunchingWithOptions:) for UIKit, or your @main App's init() for SwiftUI:

// AppDelegate (UIKit)
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    Purchases.logLevel = .debug // Enable during development
    Purchases.configure(withAPIKey: "your_ios_public_api_key")
    return true
}
// SwiftUI App
@main
struct MyApp: App {
    init() {
        Purchases.logLevel = .debug
        Purchases.configure(withAPIKey: "your_ios_public_api_key")
    }
    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

iOS-Specific Gotchas

  • Objective-C only projects: You may need to add an empty Swift file and a bridging header before the SDK compiles. Source
  • Deployment target: Must be iOS 11.0 or higher. Source
  • Swift version: Must be Swift 5.0 or higher. Check that SWIFT_VERSION isn't accidentally overridden in your Podfile. Source
  • SPM + Module Verifier: If you get module 'RevenueCat' not found when using SPM from within a framework, disable ENABLE_MODULE_VERIFIER in Build Settings. Source
  • Carthage + po debugger errors: If po throws "Couldn't IRGen Expression", add an empty Objective-C file and create a bridging header. Source

Android Setup

Step 1: Add the Gradle Dependency

RevenueCat for Android (Google Play and Amazon Appstore) is published on Maven Central and installed via Gradle. Source

In your app-level build.gradle:

dependencies {
    implementation 'com.revenuecat.purchases:purchases:8.+' // Use the latest version
}

Check the latest release tag to pin an exact version.

Step 2: Import Purchases

In your Kotlin/Java code:

import com.revenuecat.purchases.Purchases
import com.revenuecat.purchases.PurchasesConfiguration

Step 3: Initialize the SDK

Initialize in your Application class's onCreate() method — not in an Activity:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Purchases.logLevel = LogLevel.DEBUG // Enable during development
        Purchases.configure(
            PurchasesConfiguration.Builder(this, "your_android_public_api_key").build()
        )
    }
}

Register your Application class in AndroidManifest.xml:

<application
    android:name=".MyApplication"
    ...>

Android-Specific Gotchas

  • launchMode breaks purchases: If your Activity uses any launchMode other than standard or singleTop, users verifying purchases in their banking app will return to a new activity instance — and the purchase gets cancelled. Fix it in AndroidManifest.xml: Source
<activity
    android:name=".MainActivity"
    android:launchMode="singleTop">
  • AndroidX App Startup conflict: RevenueCat uses androidx.startup.InitializationProvider under the hood. If you've removed this provider entirely from your manifest, the SDK will fail to initialize. If you need to remove other initializers (like WorkManagerInitializer), use tools:node="merge" on the provider and tools:node="remove" on only the specific meta-data entry. Source
  • ProGuard/R8: RevenueCat ships its own ProGuard rules, so no extra configuration is needed. If you still have issues, add -keep class com.revenuecat.purchases.** { *; } manually. Source
  • Amazon Appstore: Requires an additional dependency (purchases-amazon) and a .pem public key file added to your project. Source

Flutter Setup

Step 1: Add the Dependency

Add purchases_flutter to your pubspec.yaml:

dependencies:
  purchases_flutter: ^8.0.0  # Use the latest version

Or run:

flutter pub add purchases_flutter

Source

Step 2: iOS-Specific Flutter Configuration

Flutter does not automatically set the iOS deployment target. You must set it manually in ios/Podfile: Source

platform :ios, '11.0'

Also ensure your Swift version is at least 5.0 in the Podfile:

# Check for existing SWIFT_VERSION — don't let it be overridden below 5.0

Don't forget to enable the In-App Purchase capability in Xcode for your Flutter iOS target. Source

Step 3: Android-Specific Flutter Configuration

Add the BILLING permission to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="com.android.vending.BILLING" />

Set launchMode to standard or singleTop on your main activity:

<activity
    android:name=".MainActivity"
    android:launchMode="singleTop">

If you plan to use RevenueCat Paywalls, your MainActivity must subclass FlutterFragmentActivity instead of FlutterActivity. Source

Step 4: Initialize the SDK

Import and configure in your main.dart:

import 'package:purchases_flutter/purchases_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Purchases.setLogLevel(LogLevel.debug); // Enable during development

  PurchasesConfiguration configuration;
  if (Platform.isAndroid) {
    configuration = PurchasesConfiguration("your_android_public_api_key");
  } else if (Platform.isIOS) {
    configuration = PurchasesConfiguration("your_ios_public_api_key");
  }
  await Purchases.configure(configuration);

  runApp(MyApp());
}

Flutter-Specific Gotchas

  • Separate API keys per platform — always branch on Platform.isAndroid / Platform.isIOS to pass the correct key. Source
  • Type name conflicts: If you use MobX or other state management libraries, you may get type conflicts with purchases_flutter types. Resolve with an import alias: Source
import 'package:purchases_flutter/purchases_flutter.dart' as purchases;
// Use as purchases.CustomerInfo, purchases.Package, etc.
  • iOS deployment target not set: Flutter silently compiles but crashes at runtime if platform :ios isn't set in the Podfile. Always set it explicitly. Source
  • Build failures: Run pub cache clean, upgrade to the latest Flutter SDK, and follow the iOS troubleshooting steps. Source

React Native Setup

Step 1: Install the Package

Using npm:

npm install react-native-purchases

Using yarn:

yarn add react-native-purchases

Modern React Native (0.60+) auto-links the native module, so no manual linking is required. For older React Native versions, run react-native link react-native-purchases after install. Source

Minimum requirements: iOS 13.4+, Android 6.0+ (API 23+), React Native 0.64+. Source

Step 2: iOS — CocoaPods Install

After adding the package, install pods:

cd ios && pod install && cd ..

Enable the In-App Purchase capability in Xcode. Source

Step 3: Android — Billing Permission

Add to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="com.android.vending.BILLING" />

Set your Activity's launchMode to standard or singleTop. Source

Step 4: Initialize the SDK

import Purchases, { LOG_LEVEL } from 'react-native-purchases';
import { Platform } from 'react-native';

const initPurchases = async () => {
  Purchases.setLogLevel(LOG_LEVEL.DEBUG); // Enable during development

  if (Platform.OS === 'android') {
    await Purchases.configure({ apiKey: 'your_android_public_api_key' });
  } else {
    await Purchases.configure({ apiKey: 'your_ios_public_api_key' });
  }
};

// Call early — typically in your root App component's useEffect or initialization

React Native-Specific Gotchas

  • BUILD_LIBRARY_FOR_DISTRIBUTION in Podfile: If you set this flag globally, you must exclude RevenueCat's targets from it — otherwise the iOS archive build will fail. Source
  • R8 dependency conflict (Android): When using react-native-purchases-ui, you may see Could not resolve all files for configuration build errors. Fix by adding to your project-level build.gradle (not app/build.gradle): Source
buildscript {
    dependencies {
        classpath("com.android.tools:r8:8.3.37")
    }
}

Universal Configuration Best Practices

These apply across all platforms:

Always Enable Debug Logs During Development

Debug logs are the fastest way to diagnose purchase issues. Enable them before calling configure(), and disable them for production builds. Source

Configure Only Once

The Purchases SDK is a singleton. Configure it once on app launch (in AppDelegate, Application.onCreate(), or main()). Calling configure() multiple times will cause undefined behavior. Source

Provide a User ID When You Have One

If your app has authentication, pass your user's ID at configuration time — or call Purchases.logIn("user_id") after they authenticate. If you have no auth system, omit the user ID and RevenueCat generates an anonymous $RCAnonymousID automatically. Source

// iOS — with user ID
Purchases.configure(withAPIKey: "your_api_key", appUserID: "your_user_id")

// iOS — anonymous
Purchases.configure(withAPIKey: "your_api_key")

Never Ship with a Test Store API Key

RevenueCat's Test Store uses a separate API key from real platform keys. Using the Test Store key in a production build means your real users can't make real purchases. Use build configuration or environment variables to automatically select the correct key per build type. Source

Users in Mainland China, Russia, and Myanmar

RevenueCat's API may be blocked in these regions. If you have a significant user base there, set the proxyURL to https://api.rc-backup.com/ before calling configure(). Source


Quick Reference: Setup Checklist

Step iOS Android Flutter React Native
Install SDK SPM / CocoaPods / Carthage Gradle flutter pub add npm / yarn
Enable IAP capability (Xcode)
Add BILLING permission
Set iOS deployment target ≥ 11.0
Set launchMode = standard/singleTop
Separate API key per platform
Configure once at app launch
Enable debug logs in dev

What's Next?

Once your SDK is configured, you're ready to:

  1. Fetch and display offerings — the list of products and packages you've configured in the RevenueCat dashboard. See Displaying Products.
  2. Make a purchase — the SDK handles the entire native purchase flow. See Making Purchases.
  3. Check subscription status — query CustomerInfo to check entitlements and grant access. See Checking Subscription Status.
  4. Test in sandbox — before going to production, validate your integration with sandbox testing. See Sandbox Testing.

Sources