Configure the RevenueCat SDK: API Key & appUserID
Overview
Configuring the SDK is the first thing you do with RevenueCat. You call
Purchases.configure(...) with your public API key, and from that point on
the SDK can fetch offerings, read CustomerInfo, run paywalls, and process purchases. This
guide covers where and when to configure, how to choose the right API key per store, how
appUserID works, how to set the log level, and how to verify setup with
isConfigured.
Three rules apply on every platform:
- Configure exactly once. Calling
configuremore than once is unnecessary and can cause confusing behavior. - Configure as early as possible at app launch, before any other SDK call.
- Use the public SDK key, never a secret key. Secret keys must never ship in a mobile app.
Get Your Public API Key
API keys live in the RevenueCat dashboard under Project settings > API keys. RevenueCat issues a separate public SDK key per store, and the prefix tells you which store the key belongs to:
| Store | Key prefix | Used for |
|---|---|---|
| Apple App Store | appl_ |
iOS, iPadOS, macOS, tvOS apps |
| Google Play | goog_ |
Android apps on Google Play |
| Amazon Appstore | amzn_ |
Android apps on Amazon |
appl_,
goog_, or amzn_ prefix). Pass the key that matches the store the build targets.
Configure Per Platform
Call configure once, as early as possible at launch. The examples below show the anonymous
form first (no appUserID) and then the identified form.
React Native
Configure in your app entry point (for example App.tsx or index.js) so it runs
before any screen mounts. On React Native a single binary can run on multiple stores, so pick the key per
platform:
import { Platform } from 'react-native';
import Purchases, { LOG_LEVEL } from 'react-native-purchases';
// Pick the public SDK key that matches the current store.
const apiKey = Platform.select({
ios: 'appl_xxx', // Apple App Store
android: 'goog_xxx', // Google Play (use 'amzn_xxx' for Amazon)
}) as string;
export function configurePurchases() {
// Set the log level BEFORE configure (debug during development).
Purchases.setLogLevel(LOG_LEVEL.DEBUG);
// Anonymous user: RevenueCat generates a random id.
Purchases.configure({ apiKey });
}
To configure with a known user id (identified), pass appUserID:
// Identified user: pass your own stable id.
Purchases.configure({ apiKey, appUserID: 'user_123' });
iOS (Swift)
Configure in application(_:didFinishLaunchingWithOptions:) or, with SwiftUI, in your
App initializer:
import RevenueCat
// In application(_:didFinishLaunchingWithOptions:) or App.init()
Purchases.logLevel = .debug // set before configure
// Anonymous user.
Purchases.configure(withAPIKey: "appl_xxx")
// Identified user.
Purchases.configure(withAPIKey: "appl_xxx", appUserID: "user_123")
Android (Kotlin)
Configure in Application.onCreate so it runs before any Activity:
import com.revenuecat.purchases.LogLevel
import com.revenuecat.purchases.Purchases
import com.revenuecat.purchases.PurchasesConfiguration
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
Purchases.logLevel = LogLevel.DEBUG // set before configure
// Anonymous user.
Purchases.configure(
PurchasesConfiguration.Builder(this, "goog_xxx").build()
)
// Identified user.
Purchases.configure(
PurchasesConfiguration.Builder(this, "goog_xxx")
.appUserID("user_123")
.build()
)
}
}
goog_ key,
on Amazon use the amzn_ key, and on iOS use the appl_ key. Passing the wrong
store's key is a common cause of configuration failures.
appUserID: Anonymous vs Identified
The appUserID is how RevenueCat identifies the current user. You have two options at
configure time:
-
Anonymous (omit appUserID). If you do not pass an
appUserID, RevenueCat generates a random anonymous id and persists it on the device. This is the right choice before the user has signed in, or for apps with no accounts. -
Identified (pass appUserID). If you already have a stable id from your own auth system,
pass it as
appUserID. Use the same value everywhere so purchases sync across devices and platforms for that user.
A common pattern is to configure anonymously at launch and identify the user later, after they sign in, by
calling logIn:
// 1) Configure anonymously at launch.
Purchases.configure({ apiKey });
// 2) Later, once you know who the user is, identify them.
const { customerInfo, created } = await Purchases.logIn('user_123');
appUserID. Use the stable, unique id from your backend. See
Identify users: logIn & logOut for the full identity
flow.
Set the Log Level
During development, raise the log level to DEBUG so the SDK prints what it is doing,
including the resolved appUserID, offering fetches, and purchase results. Set the log level
before you call configure so configuration itself is logged.
// React Native
import Purchases, { LOG_LEVEL } from 'react-native-purchases';
Purchases.setLogLevel(LOG_LEVEL.DEBUG); // before configure
Purchases.configure({ apiKey });
// iOS (Swift)
Purchases.logLevel = .debug // before configure
Purchases.configure(withAPIKey: "appl_xxx")
// Android (Kotlin)
Purchases.logLevel = LogLevel.DEBUG // before configure
Purchases.configure(
PurchasesConfiguration.Builder(this, "goog_xxx").build()
)
DEBUG is verbose and intended for
development. For release builds, drop to a quieter level so you do not log noise (or sensitive context)
to the device console.
Check isConfigured
Before calling other SDK methods from a place that might run before setup, you can verify the SDK is
ready with isConfigured. Note the platform difference: on React Native it is an
async method, while on iOS and Android it is a synchronous boolean property.
// React Native: isConfigured() is async.
const ready: boolean = await Purchases.isConfigured();
if (ready) {
const customerInfo = await Purchases.getCustomerInfo();
}
// iOS (Swift): isConfigured is a synchronous Bool property.
let ready = Purchases.isConfigured
if ready {
// Safe to call Purchases.shared methods.
}
// Android (Kotlin): isConfigured is a synchronous Boolean property.
val ready = Purchases.isConfigured
if (ready) {
// Safe to call Purchases.sharedInstance methods.
}
configure
has run, they will fail. The cleanest fix is to configure as early as possible so you rarely need to guard
with isConfigured; use the check only at boundaries that might run very early.
FAQ
What API key do I pass to configure?
The public SDK key from the dashboard, never a secret key. It is store specific: appl_ for
Apple, goog_ for Google Play, amzn_ for Amazon. On React Native, choose the key
that matches Platform.OS so each store build uses its own key.
Do I have to pass an appUserID?
No. Omit it to let RevenueCat generate an anonymous id, then call logIn later once you know
who the user is. Pass appUserID at configure time only if you already have a stable id.
How do I check if the SDK is configured?
Read isConfigured. On React Native it is async, so use
await Purchases.isConfigured(). On iOS and Android it is a synchronous boolean property,
Purchases.isConfigured.
Can I call configure more than once?
You should not. Configure exactly once, as early as possible at launch. To change the identified user
after configuring, use logIn and logOut instead of reconfiguring.
Related Guides
- Identify Users: logIn & logOut (move from anonymous to identified)
- Get CustomerInfo & Refresh the Cache (read entitlements after configuring)
- CustomerInfo Update Listener (React Native) (react to entitlement changes)
- React Native In-App Purchases Tutorial (full end-to-end integration)
- iOS In-App Purchases Tutorial (full Swift integration)
- Android In-App Purchases Tutorial (full Kotlin integration)
- RevenueCat Docs (official reference)