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 configure more 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.
Prerequisites: The RevenueCat SDK must already be installed. See the React Native, iOS, and Android codelabs for installation, then come back here to configure.

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
Public key, not secret key. The dashboard also exposes secret keys for server side use. Never embed a secret key in your app. The SDK expects the public key (the one with the 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:

typescript
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:

typescript
// 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:

swift
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:

kotlin
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()
        )
    }
}
Use the store specific key. On Android with Google Play use the 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:

typescript
// 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');
Do not use a guessable or shared id. Never use an email, a device id, or any value that collides between users as the 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.

typescript
// React Native
import Purchases, { LOG_LEVEL } from 'react-native-purchases';

Purchases.setLogLevel(LOG_LEVEL.DEBUG); // before configure
Purchases.configure({ apiKey });
swift
// iOS (Swift)
Purchases.logLevel = .debug // before configure
Purchases.configure(withAPIKey: "appl_xxx")
kotlin
// Android (Kotlin)
Purchases.logLevel = LogLevel.DEBUG // before configure
Purchases.configure(
    PurchasesConfiguration.Builder(this, "goog_xxx").build()
)
Lower the log level in production. 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.

typescript
// React Native: isConfigured() is async.
const ready: boolean = await Purchases.isConfigured();
if (ready) {
  const customerInfo = await Purchases.getCustomerInfo();
}
swift
// iOS (Swift): isConfigured is a synchronous Bool property.
let ready = Purchases.isConfigured
if ready {
    // Safe to call Purchases.shared methods.
}
kotlin
// Android (Kotlin): isConfigured is a synchronous Boolean property.
val ready = Purchases.isConfigured
if (ready) {
    // Safe to call Purchases.sharedInstance methods.
}
Configure first, then everything else. If you call SDK methods before 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