How to add in-app purchases to your app.
Native IAP via RevenueCat.
Here is the short version of how to add in-app purchases to your app. If you sell anything digital, Apple and Google require their own billing, so Stripe is off the table. This guide covers the rule, how the pieces fit together through RevenueCat, and what Newly sets up versus what you do yourself.
The flow
Adding a subscription, step by step.
Start to finish, this is how to add in-app purchases to your app in Newly. You pick the monthly price, and Newly sets up the RevenueCat side and writes the app code around it. Creating the matching store products in App Store Connect and Google Play Console stays with you.
- 1
Ask the AI for a subscription or paywall
You describe what you want, the same as anything else in Newly. "Add a subscription paywall." "Gate the export feature behind a monthly plan." "Put pro features behind a paywall after onboarding." The AI reads that as a monetization request and starts the in-app purchase flow rather than hand-rolling a payment screen. Words like entitlement and offering come from RevenueCat. You do not need to know them yet.
- 2
Connect your RevenueCat account over OAuth
Newly asks you to connect a RevenueCat account through OAuth. That is a couple of clicks, with no API keys to paste by hand. Do not have an account? You make a free one and authorize it on the spot. The authorization is the important bit: it lets Newly read and write your RevenueCat project for you, which is what makes the next step run on its own.
- 3
Pick a monthly price
You set a monthly price for the subscription. This is the one pricing decision you make in Newly, and it keeps things deliberately narrow: monthly subscriptions, a single price, one entitlement. You are not designing a pricing matrix on day one. You are picking the number your users pay each month for premium access, and you can revisit it later.
- 4
Newly sets up the RevenueCat side for you
With the price set, Newly does the RevenueCat dashboard work. It creates the entitlement (always named "pro"), the product, the offering, and the package that binds them. The matching store products are the part you handle yourself: you create the same subscription in App Store Connect and Google Play Console and connect store access to RevenueCat, since those entries live under your own developer accounts. Newly fills in the RevenueCat side so the pieces line up once your store products exist.
- 5
Newly generates the app code and installs dependencies
Then the code shows up in your project: a SubscriptionContext, a /paywall screen, a useSubscription() hook, and the onboarding hook-up so the paywall appears at the right moment. The react-native-purchases dependency installs itself, and your RevenueCat API keys are written into app.json. The next section breaks down each of these files. For now, the point is that you review it like any other diff.
App payments, at a glance.
The entitlement Newly creates and your code checks to unlock
Wraps Apple and Google billing behind one SDK and one check
The one rule
For digital goods, Stripe is not allowed.
Read this before you write a line of code. Anything digital you sell inside your app, whether that is a subscription, a premium feature, or unlockable content, has to go through Apple In-App Purchase on the App Store and Google Play Billing on Android. Stripe is not permitted for those purchases. Neither is an external link that bounces users out to a web checkout. Reviewers look for exactly this, and the workaround you are picturing does not survive the queue.
So why does Newly reach for RevenueCat? Because RevenueCat does not compete with Apple and Google. It sits on top of their native billing and gives you one SDK and one entitlement model across both platforms. You write against a clean modern API, and the actual money still moves through the rails Apple and Google demand. That is the whole trick: the convenience of a payments API, none of the rule-breaking.
None of this means Stripe is bad. Physical goods, real-world services, and a platform’s own billing all run on it cleanly. Newly itself charges your subscription through Stripe, since paying for the Newly platform is not an in-app digital purchase. The line is simple. The second you are selling digital value to your app’s users, the native rails are the only legal option.
In your code
The code Newly writes, and you own.
When you add a subscription, Newly writes a set of React Native and Expo files into your repo. Here is what each one does.
SubscriptionContext
A React context that initializes the RevenueCat SDK on launch and exposes purchase state to every screen: whether the user is subscribed, which entitlement is active, and whether a purchase is mid-flight.
/paywall screen
A real screen users land on when they tap a locked feature. It shows the monthly price you picked, the purchase button, and the required Restore Purchases option, all wired to RevenueCat.
useSubscription() hook
The gate. Call useSubscription() anywhere and it returns whether the "pro" entitlement is active. Your premium features sit behind one readable check, and the receipt logic stays in one place.
Onboarding integration
The paywall is wired into the onboarding flow so new users meet the offer at a sensible moment. You are not left guessing where to surface it.
Auto-switching API keys in app.json
Your RevenueCat keys live in app.json with a test key for development builds and production keys for release builds. Newly switches between them automatically so you never ship a dev key by accident.
react-native-purchases installed
The native dependency that talks to Apple and Google is added and configured for you. You skip the manual pod install and the usual question of whether the SDK actually linked.
What this involves by hand.
Done manually, this is a fair amount of work: wiring StoreKit on iOS and Play Billing on Android, validating receipts, modelling entitlements, handling restores, and keeping test and production keys apart. Get the entitlement logic subtly wrong and paying users can lose access while non-payers get in free. Newly generates this code for you, and because it is ordinary code in your repo, changing it later is a normal edit.
IAP vs Stripe
What’s allowed vs what gets you rejected.
A common mistake is to treat an app like a website and add a card form to it. For digital goods, the left column is what the stores require and the right column is what gets an app rejected. This is the core distinction in how to add in-app purchases to your app without failing review.
Native IAP via RevenueCat (Newly)
- Apple In-App Purchase and Google Play Billing, the only options Apple and Google allow for digital goods
- Wrapped by RevenueCat, so iOS and Android purchases share one SDK and one entitlement check
- Restore Purchases included, which Apple Guideline 3.1.1 requires
- Cross-device sync when your app has user auth
- Sandbox testing via a Sandbox Apple ID and a Google Play license tester
Stripe for in-app digital goods
- Stripe (or any external processor) for digital goods inside an app
- External payment links pointing users out to a web checkout
- A "web-only" upgrade page to dodge the store cut for digital features
- Charging for premium app features through a card form you built
- Assuming the App Store and Play Store rules are the same as the web
One quick test settles most cases: if the thing being bought is consumed inside the app, it runs through Apple In-App Purchase or Google Play Billing. If it leaves the app, a shipped product or a booked service, Stripe is fine. When in doubt, assume the store cut applies.
Testing & going live
Testing in the sandbox, and the paperwork to do first.
Testing costs you nothing. On iOS you create a Sandbox Apple ID in App Store Connect and sign into it on a real device. On Android you add yourself as a license tester in the Google Play Console. Both let you run the full purchase and restore flow without a charge. Newly auto-switches API keys behind this: dev builds use your RevenueCat test key and production builds use the production keys, so a dev key never ships by accident.
The gotcha that catches almost everyone is paperwork, not code. Before production purchases work, you have to accept Apple’s Paid Applications Agreement and fill in your tax and banking details in App Store Connect. Skip that and purchases fail silently. There is no error to chase, the transaction simply never completes. Do it early. Apple can also take 24 to 48 hours to propagate a brand-new app, so a fresh listing may not take payments the minute you hit submit.
So here is the order of operations for how to add in-app purchases to your app and actually ship them. Build the paywall in Newly. Test the buy and the restore with a sandbox tester. Confirm your useSubscription() gate opens the right features. Finish the Apple agreement and banking. Then cut the production build. Plan around a single monthly plan, since that is what Newly ships today.
FAQ
How to add in-app purchases to your app, answered plainly.
You ask the AI in plain language, something like "add a subscription paywall." Newly then prompts you to connect your RevenueCat account over OAuth, asks you to pick a monthly price, and sets up the RevenueCat side: the entitlement (always named "pro"), the product, the offering, and the package. Then it generates the app code: a SubscriptionContext that wraps the RevenueCat SDK, a /paywall screen, and a useSubscription() hook that gates your premium features on whether the "pro" entitlement is active. Dependencies like react-native-purchases install automatically, and the API keys land in app.json. You still create the matching subscription products in App Store Connect and Google Play Console and connect store access to RevenueCat, since only you can do that under your developer accounts. The result is that the RevenueCat objects and the code are written for you, and you own real React Native and Expo code.
Add a paywall with Newly.
Ask Newly for a paywall and pick your price. It sets up the RevenueCat side and writes the app code, then you create the matching store products and connect store access. Newly starts at $25 a month.