For AI agents: fetch the complete documentation index at /llms.txt, the full documentation corpus at /llms-full.txt, the agent skill at /skill.md, or this page as Markdown at /docs/mobile/revenuecat.md (or send Accept: text/markdown).
Set up RevenueCat purchases
Create a RevenueCat project, link your App Store and Play products, and wire the SDK keys plus server secrets that verify purchases.
Beginner walkthrough
Why this exists: Apple and Google require digital purchases inside an app to go through their own billing — never Stripe Checkout — and the kit enforces that boundary. RevenueCat sits on top of both stores so one integration covers iOS and Android: it tracks receipts, subscriptions, and restores, and your server asks RevenueCat whether a workspace paid.
Prerequisites: the Apple Developer Program ($99 per year) and Google Play Console ($25 once) accounts from the mobile accounts guide — store products must exist before RevenueCat can link them — plus an EAS development build to actually test, because Expo Go cannot run the native purchase module at all. RevenueCat's free tier covers testing; none of this charges you before products are live.
Quick terms: a RevenueCat project holds your store-linked apps. Products are the store items mirrored inside RevenueCat. An entitlement is the flag RevenueCat grants while a subscription is active — pro by default. An offering bundles products into the paywall the app presents. The public SDK keys go in the mobile env; a secret API key and webhook authorization stay server-side.
What you create: one project, two store-linked apps, products, one entitlement, one offering — about an hour, mostly waiting on store product setup.
Create the RevenueCat account and project
1. Open app.revenuecat.com → sign up and create a project with your product's name.
Expected: an empty project dashboard with tabs for Apps, Products, Entitlements, Offerings, and API keys — the next sections fill them in order.
Create the store products, then link both apps
Store-side products must exist before RevenueCat can reference them. iOS: appstoreconnect.apple.com → My Apps → create the app record with your ios.bundleIdentifier → In-App Purchases or Subscriptions → create the subscription products you plan to sell (they may sit in draft while you test). Android: play.google.com/console → create the app → Monetize → Products → Subscriptions (or in-app products).
Then link both inside RevenueCat: Apps → New app. For iOS pick App Store, enter the bundle id, and supply the App Store Connect credentials the form asks for — it links RevenueCat's own setup docs for each field. For Android pick Play Store, enter the package name, and upload the Play service-account JSON — the linked docs walk creating it in Google Cloud.
Expected: both apps listed under the project, and the store consoles show your products existing — draft state is fine at this stage.
Products, entitlement, offering
1. Products → New: create one RevenueCat product per store product and attach the matching App Store or Play product id — the ids must match the consoles exactly.
2. Entitlements → New: name it to match REVENUECAT_ENTITLEMENT_ID — the kit's default is pro — and attach the products that grant it.
3. Offerings → New: create an offering, add packages pointing at your products, and mark it Current — the app reads offerings.current when rendering the paywall.
Keep REVENUECAT_ENTITLEMENT_KEY at its default ai.reference-task: that is the kit's internal ledger key — the same key the shipped web plans grant — and RevenueCat access is written under it. Rename it only when your product's plan key changes.
Copy the keys and register the webhook
Project → API keys lists the three kinds below. The public per-platform SDK keys (appl_… for iOS, goog_… for Android) go in apps/mobile/.env.local — they identify the app, carry no spend authority, and the EXPO_PUBLIC_ prefix is correct for them.
The secret API key (sk_…, the v1 key) and the webhook authorization are server-only in apps/web/.env.local — never EXPO_PUBLIC_, never committed. The server calls RevenueCat's subscriber API with the secret key to verify each workspace's purchase state.
Webhook: RevenueCat → Integrations → Webhooks → set the URL {APP_URL}/api/billing/webhook/revenuecat and an Authorization header value — any long random string you invent — then put the exact same string into REVENUECAT_WEBHOOK_AUTHORIZATION. The kit compares the header verbatim and rejects anything else, so renewals, cancellations, and refunds reach the server without waiting for the next app launch.
Sandbox purchases are accepted automatically outside production; REVENUECAT_ALLOW_SANDBOX=true in a production env is rejected at startup, so leave it unset once live.
# apps/mobile/.env.local
EXPO_PUBLIC_MOBILE_PURCHASES_PROVIDER=revenuecat
EXPO_PUBLIC_REVENUECAT_IOS_API_KEY=appl_…
EXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY=goog_…
# apps/web/.env.local — server side
MOBILE_PURCHASES_PROVIDER=revenuecat
REVENUECAT_SECRET_API_KEY=sk_…
REVENUECAT_WEBHOOK_AUTHORIZATION=<the exact Authorization value set on the webhook>
REVENUECAT_ENTITLEMENT_ID=pro
REVENUECAT_ENTITLEMENT_KEY=ai.reference-taskVerify with a sandbox purchase
Purchases run only inside a development or production build — Expo Go lacks the native module entirely, so this step assumes eas build --profile development produced a dev client (the EAS guide builds it).
1. Install the dev build on a device or simulator signed into a sandbox account: App Store Connect → Users and Access → Sandbox Testers for iOS; Play Console → license testing for Android.
2. In the app open the paywall and buy with the sandbox account. Expected: the purchase completes in sandbox — no real charge — Restore purchases works, and the workspace's entitlement shows active, recorded server-side under the ai.reference-task key.
Common failures: an empty paywall means the offering is not Current or products are unlinked; a failing device purchase means the store product is still in draft or the wrong sandbox account is signed in; an entitlement that never flips means MOBILE_PURCHASES_PROVIDER/EXPO_PUBLIC_MOBILE_PURCHASES_PROVIDER are off or the webhook Authorization mismatches — RevenueCat's dashboard lists each webhook delivery's status.