Build With RevenueCat

Build a customized mobile subscription business with RevenueCat. We do the heavy lifting of normalizing subscribers from any source and maintain a single source of truth for subscription status, so you can get back to building your app.

RevenueCat is a powerful, secure, reliable, and free to use in-app purchase server with global support. All you need to get started is an API key.

Get Started    REST API Endpoints

Identifying Users

How RevenueCat handles user identity

🚧

To view documentation for the release version of our Identifying Users guide that uses identify() and reset(), head over to v3.1 of the docs: https://docs.revenuecat.com/v3.1/docs/user-ids

RevenueCat provides a source of truth for a subscriber's status across different platforms. To do this, each subscriber has an App User ID that uniquely identifies them within your application.

User identity is one of the most important components of many mobile applications, and it's extra important to make sure the subscription status RevenueCat is tracking gets associated with the correct user.

The Purchases SDK allows you to specify your own user identifiers or use anonymous identifiers generated by RevenueCat. Some apps will use a combination of their own identifiers and RevenueCat anonymous Ids - that's okay!

Anonymous App User IDs

If you don't provide an App User ID when instantiating the Purchases SDK, RevenueCat will generate a new random App User ID for you and cache it on the device. In the event that the user deletes and reinstalls the app, a new random App User ID will be generated.

Purchases.configure(withAPIKey: "my_api_key")
[RCPurchases configureWithAPIKey:@"my_api_key"];
Purchases.configure(this, "my_api_key")
Purchases.configure(this, "my_api_key");
await Purchases.setup("public_sdk_key");
Purchases.setup("public_sdk_key");
Purchases.setup("public_sdk_key");
See Unity installation instructions https://docs.revenuecat.com/docs/unity

πŸ“˜

Anonymous App User Ids are always prefixed with $RCAnonymousID: for SDK versions 3+. This can be useful for working with anonymous users on your server.

Provided App User ID

Setting your own App User ID will allow you to reference users in the RevenueCat dashboard, via the API, as well as in the webhooks and other integrations.

Using an externally managed App User ID also provides a mechanism by which to restore purchases in a few scenarios:

  • When a user deletes and reinstalls your app - using the same App User ID will ensure they still have access to subscriptions previously started without requiring a restore .
  • When the user logs in on multiple devices - you can honor a subscription that was purchased on one device across any other platform.

Provide App User ID on configuration

If you have your own App User IDs at app launch, you can pass those on instantiation to Purchases.

Purchases.configure(withAPIKey: "my_api_key", appUserID: "my_app_user_id")
[RCPurchases configureWithAPIKey:@"my_api_key" appUserID:@"my_app_user_id"];
Purchases.configure(this, "my_api_key", "my_app_user_id")
Purchases.configure(this, "my_api_key", "my_app_user_id");
await Purchases.setup("public_sdk_key", appUserId: "my_app_user_id");
Purchases.setup("public_sdk_key", "my_app_user_id");
Purchases.setup("public_sdk_key", "my_app_user_id");
See Unity installation instructions https://docs.revenuecat.com/docs/unity

Often times, you may not have your own App User IDs until later in the application lifecycle. In these cases, you can pass the App User ID later through the .logIn() method.

Provide App User ID after configuration

If your app doesn't receive its own App User ID until later in its lifecycle, you can set (or change) the App User ID at any time by calling .logIn(). If the logged in identity does not already exist in RevenueCat, it will be created automatically.

// Configure Purchases on app launch
Purchases.configure(withAPIKey: "my_api_key")

//...

// Later log in provided user Id
Purchases.shared.logIn("my_app_user_id") { (purchaserInfo, created, error) in
    // purchaserInfo updated for my_app_user_id
}
// Configure Purchases on app launch
[RCPurchases configureWithAPIKey:@"my_api_key"];

//...

// Later log in provided user Id
[[RCPurchases sharedPurchases] logIn:@"my_app_user_id" completionBlock:^(RCPurchaserInfo *purchaserInfo, Bool *created, NSError *error) {
    // purchaserInfo updated for my_app_user_id
}];
// Configure Purchases on app launch
Purchases.configure(this, "my_api_key")

//...

// Later log in provided user Id
Purchases.sharedInstance.loginWith("my_app_user_id", ::showError) { purchaserInfo, created ->
  // purchaserInfo updated for my_app_user_id
}
// Configure Purchases on app launch
Purchases.configure(this, "my_api_key");

//...

// Later log in provided user Id
Purchases.getSharedInstance().logIn("my_app_user_id", new LogInCallback() {
    @Override
    public void onReceived(@NotNull PurchaserInfo purchaserInfo, boolean created) {
        // purchaserInfo updated for my_app_user_id
    }
  
  @Override
  public void onError(@NotNull PurchasesError error) {

  }
});
// Configure Purchases on app launch
await Purchases.setup("public_sdk_key");

//...

// Later log in provided user Id
LogInResult result = await Purchases.logIn("my_app_user_id");
// Configure Purchases on app launch
Purchases.setup("public_sdk_key");

//...

// Later log in provided user Id
const { purchaserInfo, created } = await Purchases.logIn("my_app_user_id");
// purchaserInfo updated for my_app_user_id
// Configure Purchases on app launch
Purchases.setup("public_sdk_key");

//...

// Later log in provided user Id

Purchases.logIn(
  "my_app_user_id", 
  ({ purchaserInfo, created }) => {
    // purchaserInfo updated for my_app_user_id
  },
  error => {
  }
);
purchases.LogIn("my_app_user_id", (purchaserInfo, created, error) => {
  // purchaserInfo updated for my_app_user_id
});

When going from an Anonymous ID to a Provided ID RevenueCat will decide whether the identities should be merged (aliased) into the same PurchaserInfo object or not depending on the state of the Provided ID and if it already has an anonymous alias.

logIn() behavior

Current App User ID

Provided App User ID already exists?

Provided App User ID has anonymous alias?

Result

Anonymous

No

N/A

Anonymous ID is aliased with Provided ID, PurchaserInfo merged.

Anonymous

Yes

No

Anonymous ID is aliased with Provided ID, PurchaserInfo merged.

Anonymous

Yes

Yes

PurchaserInfo changes to Provided ID, no aliases created.

Non-anonymous

Any

Any

PurchaserInfo changes to Provided ID, no aliases created.

Logging Out

When an identified user logs out you should call the logOut() method - this generates a new Anonymous App User Id for the logged out state.

Logging back in

To log in a new user, the provided App User Id should be set again with .logIn().

Switching accounts

If you need to switch from one provided App User Id to another, it's okay to call the .logIn() method directly - you do not need to call logOut() first.

Sharing Subscriptions Across Platforms

Subscription status is always tied to an App User ID in RevenueCat, not a device. You can share a subscription across platforms (e.g. iOS -> Android) by logging in the same App User ID. This is usually done through your own authentication mechanism.

Note that a user can only manage their subscription on the platform it was purchased from.

Blocked App User IDs

Certain App User Ids are blocked in RevenueCat. This is by design to help developers that may be unintentionally passing non-unique strings as user identifiers. The current block-list is:
no_user, null, none, nil, (null), ``(empty string).

Tips for setting App User IDs

App User IDs Should Not Be Guessable

RevenueCat provides subscription status via the public API, having App User IDs that are easily guessed is not good. It is recommended to use a non-guessable psuedo-random ID.

Don't set emails as App User IDs

For the above reason, and GDPR compliance, we don't recommend using email addresses as App User IDs

Don't set IDFA as App User IDs

Advertising identifiers should not be used as App User IDs since they can be easily rotated and are not unique across users if limit ad tracking is enabled.

Don't hardcode strings as App User IDs

You should never hardcode a string as an App User ID, since every install will be treated as the same user in RevenueCat. This will create problems and could unlock entitlements for users that haven't actually purchased.

Every app user ID must be unique per user. If you don't have your own user IDs for some of your users, you should not pass any value for the App User ID on configuration which will rely on the anonymous IDs created by RevenueCat.

Keep App User IDs shorter than 100 characters

App User IDs should not be longer than 100 characters.

Next Steps

Updated 3 days ago


Identifying Users


How RevenueCat handles user identity

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.