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.
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.
// 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);
// 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)")
// 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).
// 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
}
// 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
}
// 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
}
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.
// React Native: clear the cache, then fetch fresh
await Purchases.invalidateCustomerInfoCache();
const info = await Purchases.getCustomerInfo(); // now from the network
// iOS: clear the cache, then fetch fresh
Purchases.shared.invalidateCustomerInfoCache()
let info = try await Purchases.shared.customerInfo() // now from the network
// Android: clear the cache, then fetch fresh
Purchases.sharedInstance.invalidateCustomerInfoCache()
val info = Purchases.sharedInstance.awaitCustomerInfo() // now from the network
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.
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
- CustomerInfo Update Listener (React Native): react to changes live instead of polling
- Check Subscription Status on iOS: read entitlements in Swift
- Configure the RevenueCat SDK: apiKey and appUserID setup
- Restore Purchases on iOS (Swift): re-sync purchases for returning users
- RevenueCat Docs: CustomerInfo: official reference