Get CustomerInfo & Check Entitlements with RevenueCat

Overview

CustomerInfo is the object RevenueCat uses to describe the current state of a customer: their active entitlements, active subscriptions, non-subscription purchases, and related metadata. It is the single source of truth for answering the question your app asks most often: "Does this user have access to premium features right now?"

You read CustomerInfo by calling the fetch method for your platform. The same object exposes an entitlements.active map that you check against your entitlement identifier (for example premium). RevenueCat caches CustomerInfo locally and refreshes it automatically in the background, so most calls are fast and do not hit the network.

Prerequisites: The RevenueCat SDK must already be installed and configured with Purchases.configure(...). See the Configure the SDK guide for setup, including your apiKey and appUserID.

Fetch CustomerInfo

Each SDK exposes an async method that returns the latest CustomerInfo. It returns the cached value when one is available and refreshes in the background.

typescript
// React Native (react-native-purchases)
import Purchases from 'react-native-purchases';

const info = await Purchases.getCustomerInfo();
const isPro = typeof info.entitlements.active['premium'] !== 'undefined';
console.log('Pro active?', isPro);
swift
// iOS (RevenueCat, Swift Concurrency)
import RevenueCat

let info = try await Purchases.shared.customerInfo()
let isPro = info.entitlements.active["premium"]?.isActive == true
print("Pro active? \(isPro)")
kotlin
// Android (purchases-kotlin, coroutines)
import com.revenuecat.purchases.Purchases

val info = Purchases.sharedInstance.awaitCustomerInfo()
val isPro = info.entitlements.active["premium"]?.isActive == true
Log.d("Purchases", "Pro active? $isPro")

On iOS, customerInfo() is a throwing async function, so wrap it in try await. On Android, awaitCustomerInfo() is a suspend function that must be called from a coroutine (for example lifecycleScope.launch or viewModelScope.launch). In React Native, getCustomerInfo() returns a Promise.

Check Active Entitlements

entitlements.active is a map keyed by your entitlement identifier. An entitlement that is present in entitlements.active is active for the customer. This is the recommended way to gate features: look up your entitlement by its identifier and check whether it is present (and active).

typescript
// React Native: presence in the active map means active
const info = await Purchases.getCustomerInfo();
const isPro = typeof info.entitlements.active['premium'] !== 'undefined';

if (isPro) {
  // unlock premium features
} else {
  // show paywall
}
swift
// iOS: check isActive on the entitlement
let info = try await Purchases.shared.customerInfo()
let isPro = info.entitlements.active["premium"]?.isActive == true

if isPro {
  // unlock premium features
} else {
  // show paywall
}
kotlin
// Android: check isActive on the entitlement
val info = Purchases.sharedInstance.awaitCustomerInfo()
val isPro = info.entitlements.active["premium"]?.isActive == true

if (isPro) {
  // unlock premium features
} else {
  // show paywall
}
Use the identifier you configured. Replace premium with the entitlement identifier you created in the RevenueCat dashboard. Reading entitlements.active rather than inspecting raw subscriptions keeps your gate logic simple and correct across stores.

How the Cache Works

CustomerInfo is cached locally by the SDK. When you call the fetch method, RevenueCat returns the cached CustomerInfo when it is available, rather than making a network request on every call. This keeps your UI responsive and avoids unnecessary traffic.

The cache is refreshed automatically in these situations, so you rarely need to manage it yourself:

  • In the background on a regular basis while the app is in use
  • After a purchase, a subscription renewal, or a restore
  • When the app foregrounds, so returning users see up-to-date state

Because of this, the normal pattern is simply to call the fetch method when you need the current state. Let RevenueCat keep the cache fresh in the background and notify you of changes through a listener.

Force a Refresh with invalidateCustomerInfoCache

When you have a strong reason to bypass the cache, call invalidateCustomerInfoCache(). It clears the cached CustomerInfo so that the next fetch goes to the network and returns fresh data. It does not return data itself: you still call the fetch method afterward.

typescript
// React Native: clear the cache, then fetch fresh
await Purchases.invalidateCustomerInfoCache();
const info = await Purchases.getCustomerInfo(); // now from the network
swift
// iOS: clear the cache, then fetch fresh
Purchases.shared.invalidateCustomerInfoCache()
let info = try await Purchases.shared.customerInfo() // now from the network
kotlin
// Android: clear the cache, then fetch fresh
Purchases.sharedInstance.invalidateCustomerInfoCache()
val info = Purchases.sharedInstance.awaitCustomerInfo() // now from the network
Do not over-call it. invalidateCustomerInfoCache() forces an extra network request on the next fetch and is rate-limited. The cache already refreshes automatically after purchases, renewals, restores, and in the background, so most apps never need it. Reach for it only in specific cases, such as immediately after granting an entitlement through a server-side flow that the SDK could not have observed locally.

Listen for Changes

Fetching once tells you the state at that moment. To keep your UI in sync as subscriptions renew, purchases complete, or restores happen, add a CustomerInfo update listener instead of polling. The listener fires whenever RevenueCat detects a change, so you can update your premium state reactively.

Pairs with this guide. See addCustomerInfoUpdateListener in React Native for the full subscribe-and-clean-up pattern, including the useEffect teardown. The general rule: fetch once to seed your initial UI, then let the listener handle ongoing updates.

For deeper background on the object itself, see the official RevenueCat docs on CustomerInfo.

FAQ

How do I get CustomerInfo with RevenueCat?
Call the fetch method for your platform: Purchases.getCustomerInfo() in React Native, Purchases.shared.customerInfo() in iOS Swift, or Purchases.sharedInstance.awaitCustomerInfo() in Android Kotlin. It returns a CustomerInfo object, served from cache when available.

How do I check if an entitlement is active?
Read info.entitlements.active, a map keyed by your entitlement identifier. An entitlement present in active means it is active. In Swift and Kotlin you can also check info.entitlements.active["premium"]?.isActive == true.

How do I force RevenueCat to fetch fresh CustomerInfo?
Call invalidateCustomerInfoCache() to clear the cache, then call the fetch method again. The next fetch goes to the network. invalidateCustomerInfoCache() does not return data on its own.

Does getCustomerInfo() always hit the network?
No. CustomerInfo is cached and refreshed automatically in the background, so the fetch method returns cached data when it is available instead of making a request every time. Only invalidate the cache when you specifically need to bypass it.

Related Guides