Get help with your SDK implementation.
Recently active
Hello, I have a Flutter Project where we are using Paywalls to display RevenueCat offerings to customers.For Android, on my Google subscription I have multiple offers under a single Base plan as seen below:Is there a way to pick specific offer(s) when using Paywalls?
Use case:I have a product priced at $71.99 per year in the App Store. On my paywall I am using the variable {{ product.price_per_month }} to display the product's price per month. However, the paywall is rendering $6.00 when I want it to display $5.99.I do not want to hardcode $5.99 on the paywall because then the price will be shown in USD even if the user non-USD, which is not good.Desired Solution: Support for conditional logic directly within the template to show text or values only for specific currencies, such as displaying a hardcoded value but only for USD users.
I love the WebBilling feature, but thought it would be even more powerful to be able to embed the products of a offering as part of my webpage.So for example when a user clicks on a package it would navigate directly to the checkout page.This would make the integration more seamless for users checking out my webpage being able to see the different packages and purchase right away; for example from a landing page.It will also give developers more tools to customize how the packages are shown.
Is there an issue with displaying Paywalls specifically with an offering and or in the sandbox environment with Xcode builds?If I use this is shows the paywall instantly PaywallView()however if I use an offering its blank (as if offering is nil). If I swipe app up to open the app switcher on iOS the paywall is actually loaded and is showing when app re-enters foreground. So wondering if this is a known Xcode sandbox debug issue..fullScreenCover(isPresented: $hasToShowPayWall) {if let offering = offering { PaywallView(offering: offering, displayCloseButton: true) } else{ Text("offerings is somehow nil") }}offerings a awaited and fetched before triggering the fullScreenCover. so offering passed in cannot be nil yet it claims it is @State private var offering: Offering? = nilif let offering = await availableOfferingWithIdentifier("default") { await MainActor.run { offering = offering withAnimation { hasToShowP
Hello,I’m providing a free trial on my weekly plan and I want to check if a user is eligible for the trial. The goal is to display a text (e.g., “3 Day Free Trial”) based on eligibility.How can I check if the user has already availed the free trial or not?I tried this code, but it’s not working: val freeTrialText = if (pkg.storeProduct.subscriptionOptions?.defaultOffer?.freePhase != null) "3 Day Free Trial" else "" println("3 day trial text: $freeTrialText")This always returns empty.On iOS, the payment popup correctly shows the 3-day free trial, but in the app it doesn’t reflect.Any ideas on what I might be missing?
I am on the latest version of iOS SDK, and set delegate for observing for active entitlements and then updating the observable object. It makes it self-contained and effective for a SwiftUI app.My problem is that its method is called when initializing the SDK, but not when the purchase is done, also not when restored purchases.I have set it up the same way in my other apps, and they are on older versions of SDK, where it worked. I hope this is fixed quickly, don’t want odd workarounds in the code.
Before showing paywall I want to check if any purchase already made from a google play or apple account. My app will not support account transfer so if the user already purcahse for any account and user logged in with different account we don’t want to purchase with the same google play or apple account. We want to show a message like “Please change your google play or apple account as another user already using that.”. To show this message I need to know from any account a purchase has been made or not. I can do that by Google Billing client but I want to know more generic way using revenuecat.
Hello,I’m trying to add a hard paywall in a Capacitor project.All is working as intended on Android, the paywall is displayed full screen, while on iOS it’s displayed as a sheet.I don’t see any way to choose whether to use sheet or full screen.I tried adding a close button and removing it but it’s the same.Any ideas ?Thanks
Hey everyone,I’m integrating the Meta SDK with RevenueCat and I have a question about how to handle FBAnonymousID.Right now, I grab the FBAnonymousID from the Meta SDK and then pass it manually into the RevenueCat SDK in my code. From what I understand, this value is generated per device.In my login flow, I set the appUserId in RevenueCat based on a value from my backend.Here’s the part I’m not sure about: When a user logs in, I update the appUserId in RevenueCat. The FBAnonymousID, however, stays the same (since it’s tied to the device). My question is: is it okay that different RevenueCat users on the same device share the same FBAnonymousID? Or should I be re-generating a new one during the login process to avoid mixing analytics?Has anyone else run into this or figured out the best practice?
Hello everyone,I am currently working on paywall and am having some difficulty displaying the paywall correctly. Currently, I display the paywall as follows:ContentView() .presentPaywallIfNeeded( requiredEntitlementIdentifier: Constants.ENTITLEMENT_ID, purchaseCompleted: { customerInfo in [...] }, restoreCompleted: { customerInfo in [...] } )However, it is displayed as a sheet dialog and can be easily closed. A paywall that can be easily closed is not a wall—it's just a door that can be kicked in :)Now I can use the alternative: PaywallView. However, I now have to implement the logic myself to determine whether PaywallView should be displayed or not. Right?Is there an SDK function that allows me to decide whether to display it or not, as with the sheet dialog? The documentation has no info about it.I want the user to be unable to close the paywall. He has to pay or close the app, but the paywall must be impossible to over
## Description Getting "Invalid API Key" error when initializing RevenueCat Flutter SDK despite using valid API keys. **Error:**```RevenueCat Platform Exception: There was a credentials issue. Check the underlying error for more details. Invalid API Key. (Code: 11)``` **Code:**```dartawait Purchases.configure(PurchasesConfiguration(apiKey)); // Test the connectionfinal customerInfo = await Purchases.getCustomerInfo();```
Hiwhere can I find the documentation for PaywallView.currently I’m using it like this:PaywallView() .onRequestedDismissal { state = .paymentRequiredInfo } .onPurchaseCompleted { CustomerInfo in state = .ready } .onPurchaseFailure({ NSError in state = .error(StaticErrorMessage("Payment error")) })After Purchase is completed, callback method onPurchaseCompleted is not called. If I try to purchase again I’m getting “already purchased” dialog info.So my question are why onPurchaseCompleted is not called and where is the documentation for PaywallView.Regards
I want to fetch state from API in addition to webhook handling, for improved resilience.My subscriptions are credits based, when there’s initial/renewal event, I assign a number of credits to the user.Not sure how to proceed with the transfer webhook event:The user installs the app on device A: they get id 1. The user subscribes. My backend has id 1 → 10 credits.The user installs the app on device B: they get id 2.Let’s say that the backend for some reason doesn’t receive or process the transfer webhook, so it’s not aware that id 1 → id 2Now device B, with its id 2, triggers a refresh from RevenueCat api: I get that id 2 has a subscription.Since I don’t have the old id, all I can do here is to create a new record for id 2 with 10 credits, as if it was a new user. Which is incorrect, because it’s effectively duplicating the credits for the user, who can now use 10 credits on device A and 10 credits on device B.How can I associate the subscription data to the old id? Also, is the whole r
Hello RC Support:The issue described below is in the latest IOS SDK only. The android SDK does not have this issue. The crux of the issue is that presented_offering_id IS NOT matching the product_id and resulting incorrect understanding of which product the user actually purchased.I’ll explain this with an example.We have a few product_id = Plus , Gold, Platinum. The corresponding presented_offering_id also matches this: i.e. presented_offering_id = Plus , Gold, Platinum.As an example, In IOS when a user purchases a Gold offering on the paywall, we see the following INCORRECT response in the webhook events that we receive. Actual plan purchased by the user: GoldProduct_Id received via webhook: goldpresented_offering_id received via webhook: platinum. In Android, it is functioning properly:Actual plan purchased by the user: GoldProduct_Id received via webhook: goldpresented_offering_id received via webhook: gold. I can share event logs and more via email.
I am using the React Native SDK, and I am getting some PAYWALL_RESULT.ERROR back when users are shown the paywall.I have been searching for what this result means, but I haven’t been able to find many details about this specific error.All I can see is this line from the source code: “If an error happened during purchase/restoration.” I would like to know whether this indicates an error on RevenueCat’s side (such as the server sending 500s) or a store/user error (for example, problems processing the payment).Thanks!
Platform: React NativeSDK Version: react-native-purchases 8.11.6, react-native-purchases-ui 8.11.6Issue: Bold font weight not applying on Android V2 Paywalls (works perfectly on iOS) Problem DescriptionI have successfully configured custom fonts ("Nunito Sans") for V2 Paywalls and they work perfectly on iOS, but on Android the bold weight is not being applied - all text appears as regular weight even when elements are configured as bold in the RevenueCat dashboard. What Works ✅- Custom font "Nunito Sans" loads correctly on Android (showing custom font instead of system font)- All font weights work perfectly on iOS- Regular font weight displays correctly on Android What Doesn't Work ❌- Bold font weight on Android (appears as regular weight)- Text configured as bold in dashboard renders as regular on Android only Technical Configuration Environment- React Native: 0.76.9 (bare workflow, NOT Expo)- RevenueCat SDK: react-native-purchases 8.11.6- RevenueCat UI: react-native-purchases-ui 8.11
Dear RevenueCat Community,I am using the RevenueCat SDK in my Flutter application and have implemented App Tracking Transparency (ATT) permission on iOS. When the user grants permission, I call the method Purchases.collectDeviceIdentifiers() to obtain the device's IDFA. This value is correctly set and included in the events sent through the webhooks.In my Flutter app, users can purchase subscriptions using Stripe. For this, a web view is opened for the user to complete the payment. Once the purchase is completed and the user returns to the app, the app submit to this endpoint https://api.revenuecat.com/v1/receipts the subscription ids to upload the purchase to RevenueCat. This is how the user gains access to the app features after the purchase.To receive purchase events centrally in my backend, I have added a webhook in RevenueCat that reports Initial Purchase and Renewal events to my endpoint.I have observed the following: For purchases made within the app (IAP), the IDFA is correctly
Hi RevenueCat team,All of my agreements and tax information are already set up and working. I also have other apps where In-App Purchases are working fine. However, with this new app I’m stuck because of Apple’s requirement:“Your first subscription must be submitted with a new app version. Create your subscription, then select it from the app’s In-App Purchases and Subscriptions section on the version page before submitting the version to App Review.”Because of this, I cannot send my IAP for review, and Apple is rejecting the submission under 2.1 - Performance - App Completeness with the note:We found that your in-app purchase products exhibited one or more bugs which create a poor user experience. Specifically, after selecting both weekly and yearly subscriptions an error message is displayed.Review device details:• Device type: iPhone 13 mini• OS version: iOS 26.0At the same time, I get this warning from RevenueCat:[RevenueCat] ⚠️ RevenueCat SDK is configured correctly, but contains
This code checks to see if a customer should be shown the paywall. let customerInfo = try await Purchases.shared.customerInfo(fetchPolicy: .fetchCurrent) let timeInterval = Date.now.timeIntervalSince(customerInfo.firstSeen) let ninetyDays: TimeInterval = 90 * 24 * 60 * 60 return timeInterval >= ninetyDaysThis check is returning false.On the RevenueCat dashboard for this user first seen was 27 June 2024. They never changed their App User ID. However they only seen the paywall today 17 September 2025. Which is much greater than the 90 days. What could be causing the delay in showing the paywall? I appreciate that the customerInfo could be cached but not for over a year.
I am getting the following crashes on Android using revenueCat KMP SDK. And it has increased recently. What could be the issue?The attached two files are of the PaywallState and Purchase click button codes Exception java.lang.IllegalStateException: at com.revenuecat.purchases.kmp.di.AndroidProviderKt.requireActivity (AndroidProvider.kt:83) at com.revenuecat.purchases.kmp.Purchases.purchase (Purchases.android.kt:275) at com.revenuecat.purchases.kmp.Purchases.purchase$default (Purchases.android.kt:266) at utils.PaywallState.purchaseSelectedPackage (PaywallState.kt:29) at pro.ui.paywall.PaywallScreenKt.PaywallScreen$lambda$41$lambda$40$lambda$39$lambda$26$lambda$25 (PaywallScreen.kt:230) at androidx.compose.foundation.ClickableNode.onPointerEvent-H0pRuoY (Clickable.kt:1018) at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:436) at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:422) at androidx.compose.ui.input.poin
Hi everyone,I have a mobile app that originally relied on $RCAnonymousIDs to manage subscriptions. Now, we’ve introduced mandatory signup, so I’m now working on migrating from anonymous IDs to our own custom user IDs.What’s not clear to me is the best way to handle the transition: How can I merge an existing custom user ID with the old $RCAnonymousID values already in the system? Should this be done via the API, or does the SDK handle it automatically? In some cases, the custom user ID is already listed as an alias of an anonymous ID. How can I “promote” the custom ID so it becomes the original_app_user_id instead of the anonymous one? Has anyone here gone through a similar migration? Any guidance on the best practices would be really helpful.Thanks!
I noticed that we had inflated install numbers on RC vs. App Store. I trust Apple more with the installs, so I went on to find the root cause.We have a Flutter app and I call Purchases.logOut() when a user logs out. This sometimes happens automatically. I now read in the docs that logOut will clear the saved appUserID. This will generate a random user id and save it in the cache.Since RC seems to count appUserIDs as installs, each log-out will count as an additional install. Question: Should I even call Purchases.logout when our users log out? They are still on the same device, with the same Apple ID (most likely). Seems to me that this is wrong and inflates our install numbers.
Hello, I have a flutter app that is working fine on Android but can’t fetch offers from Appstore Connect. I have verified all the details, from product id, bundle id, products are approves, agreements signed, bank account added, etc. I can see where the issue lies in any config setting. What else could be causing this problem? I went through the “Why are offerings or products empty?” checklist. I did see where it stated about a shared secret but that was for storekit 1 which is not what we are using. I have done the certificate for storekit 2. This is only on iOS. Any help is greatly appreciated.
Hello,I plan to use virtual currencies within my app.For me, spending or gaining is straight forward and I will use my backend for such calls.Evaluating the available tokens within the app raises more questions and I tried to understand the official doc here https://www.revenuecat.com/docs/offerings/virtual-currency but I still wonder about some aspects.Exact use case: I need to know within my view models if the user has tokens or not.What should I use: Purchases.shared.cachedVirtualCurrencies or Purchases.shared.virtualCurrencies()?I understand the fact that I need to call the Purchases.shared.invalidateVirtualCurrenciesCache() each time there is a backend transaction, but then what?Is calling Purchases.shared.invalidateVirtualCurrenciesCache() updating the Purchases.shared.cachedVirtualCurrencies? or do I need to fist call Purchases.shared.virtualCurrencies() and then use the cachedVirtualCurrenciesHow about this flow:App launch call Purchases.shared.virtualCurrencies() and store it
Something is wrong with the checkTrialOrIntroductoryPriceEligibility function. I'm not sure if I'm doing it right; to be sure, I wanted to share my problem here first.In my iOS app, I use this snippet to check whether there is an eligible introductory price:if (Platform.OS === 'ios') { // Purchases.checkTrialOrIntroductoryPriceEligibility is only available for iOS const introEligibilityStatuses = await Purchases.checkTrialOrIntroductoryPriceEligibility([ pkg.product.identifier, ]); return ( introEligibilityStatuses[pkg.product.identifier].status === Purchases.INTRO_ELIGIBILITY_STATUS.INTRO_ELIGIBILITY_STATUS_ELIGIBLE ); } In one account, everything works fine—I haven't bought anything with that account yet.But the second account (with expired introductory subscription) returns wrong information:The status returns INTRO_ELIGIBILITY_STATUS_ELIGIBLE (2), which means the introductory price is available, so I show the discount in the app. Ho
Already have an account? Login
No account yet? Create an account
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.