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
-spmmirror 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_VERSIONisn't accidentally overridden in yourPodfile. Source - SPM + Module Verifier: If you get
module 'RevenueCat' not foundwhen using SPM from within a framework, disableENABLE_MODULE_VERIFIERin Build Settings. Source - Carthage +
podebugger errors: Ifpothrows"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
launchModebreaks purchases: If yourActivityuses anylaunchModeother thanstandardorsingleTop, users verifying purchases in their banking app will return to a new activity instance — and the purchase gets cancelled. Fix it inAndroidManifest.xml: Source
<activity
android:name=".MainActivity"
android:launchMode="singleTop">
AndroidX App Startupconflict: RevenueCat usesandroidx.startup.InitializationProviderunder 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 (likeWorkManagerInitializer), usetools:node="merge"on the provider andtools: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.pempublic 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
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.isIOSto pass the correct key. Source - Type name conflicts: If you use MobX or other state management libraries, you may get type conflicts with
purchases_fluttertypes. 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 :iosisn't set in thePodfile. 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_DISTRIBUTIONin 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 seeCould not resolve all files for configurationbuild errors. Fix by adding to your project-levelbuild.gradle(notapp/build.gradle): Source
buildscript {
dependencies {
classpath("com.android.tools:r8:8.3.37")
}
}
- Expo users: Use the dedicated Expo installation guide — the standard React Native steps don't fully apply to managed Expo workflows.
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:
- Fetch and display offerings — the list of products and packages you've configured in the RevenueCat dashboard. See Displaying Products.
- Make a purchase — the SDK handles the entire native purchase flow. See Making Purchases.
- Check subscription status — query
CustomerInfoto check entitlements and grant access. See Checking Subscription Status. - Test in sandbox — before going to production, validate your integration with sandbox testing. See Sandbox Testing.
Sources
- iOS Installation — RevenueCat Docs
- Android Installation — RevenueCat Docs
- Flutter Installation — RevenueCat Docs
- React Native Installation — RevenueCat Docs
- Configuring the SDK — RevenueCat Docs
- SDK Quickstart — RevenueCat Docs
- API Keys & Authentication — RevenueCat Docs
- Troubleshooting the SDKs — RevenueCat Docs