RevenueCat Setup
Configure RevenueCat products, SDK keys, and webhooks.
RevenueCat setup is dashboard work: create store products, attach them to one RevenueCat entitlement, expose them through an offering, add public SDK keys to Expo, and wire the webhook to Supabase.
The app can configure RevenueCat on iOS and Android, but the shipped Supabase
webhook currently maps App Store events only. Treat iOS as end-to-end today.
Before shipping Google Play purchases, extend providerForStore() and the
billing_provider enum to handle PLAY_STORE.
Store prerequisites
In App Store Connect:
Create the app record
Create an iOS app record for the active bundle identifier. By default the variants are:
development: expo.soarstarter.com.dev
preview: expo.soarstarter.com.preview
production: expo.soarstarter.comOnly store-capable bundle IDs should get real App Store products. Development and preview IDs are useful for internal builds, but they need matching products if you test purchases against them.
Complete paid-app requirements
Finish paid-app agreements, tax, and banking. Products often fail to load until these are complete.
Create products
Create a subscription group with monthly and yearly auto-renewable subscriptions, plus an optional non-consumable lifetime product. Product IDs are yours to choose; the app reads products from the RevenueCat offering and does not require hard-coded IDs.
In Google Play Console:
Create the app and package
Use the Android package from app.config.ts. The default variants are:
development: expo.soarstarter.com.dev
preview: expo.soarstarter.com.preview
production: expo.soarstarter.comMatch the package name and signing key used by the build you test.
Configure monetization
Finish merchant account setup, create subscription products for monthly/yearly plans, and create an in-app product if you want a lifetime purchase equivalent.
Plan the backend extension
The client can use EXPO_PUBLIC_REVENUECAT_ANDROID_KEY, but the current
revenuecat-webhook ignores PLAY_STORE events. Extend and test that mapper
before relying on Android purchases for Supabase entitlement.
RevenueCat project
Add platform apps
In RevenueCat, create a project with an App Store app and, if you plan Android, a Google Play app. Copy the public app-specific SDK keys:
EXPO_PUBLIC_REVENUECAT_IOS_KEY=appl_xxxxxxxxxxxxxxxxx
EXPO_PUBLIC_REVENUECAT_ANDROID_KEY=goog_xxxxxxxxxxxxxxxxxThese are public SDK keys and belong in .env.local or EAS environment values.
Add products
Create RevenueCat products that point at the store product IDs. The Expo app does not read product IDs from env; RevenueCat's product catalog is the source.
Create the entitlement
Create one entitlement with identifier:
proAttach monthly, yearly, and lifetime products to that same entitlement. The
identifier must match PRO_ENTITLEMENT_ID in lib/purchases.tsx.
Create the offering
Create or activate the current offering and add packages:
Package type: Monthly
Package type: Annual
Package type: LifetimeThe paywall reads offerings.current. If no current offering exists, the app
shows the "Couldn't load subscription options" state.
Wire the Supabase webhook
Deploy revenuecat-webhook and set REVENUECAT_WEBHOOK_AUTH from
Supabase Setup. Then in RevenueCat
Project settings → Integrations → Webhooks, add:
| Field | Value |
|---|---|
| URL | https://your-project-ref.supabase.co/functions/v1/revenuecat-webhook |
| Authorization | The same value as REVENUECAT_WEBHOOK_AUTH |
The function has verify_jwt = false because RevenueCat is not a signed-in
Supabase user. It verifies the static Authorization header, then uses the
service role to upsert subscriptions.
Sandbox events are processed the same way as production events and only touch
the row whose user_id matches the RevenueCat app_user_id.
Expected end state
Expo env -> RevenueCat public SDK key for each native platform
RevenueCat app -> iOS app configured; Android app optional until webhook support is extended
Entitlement -> identifier "pro"
Offering -> current offering with Monthly / Annual / Lifetime packages
Supabase -> revenuecat-webhook deployed with REVENUECAT_WEBHOOK_AUTH