Billing
In-app purchases through RevenueCat - setup, product mapping, and what the app shows.
Store purchases are additive to your web provider: the same account, billed by Apple or Google instead. They ship only with --mobile-purchases revenuecat.
Setup
EXPO_PUBLIC_REVENUECAT_* keys in apps/mobile/.env, then the server variables and the webhook - see Mobile store billing.Product mapping
Each paid price in packages/config/src/pricing.ts carries the store ids and the prices a store sale books, all generated blank.
| Field | What you paste | Where you read it |
|---|---|---|
appleProductId | The product identifier, exactly as App Store Connect shows it | App Store Connect → Subscriptions |
googleProductId | <subscription_id>:<base_plan_id>, the composite RevenueCat sends - not the subscription id alone | Play Console → Subscriptions → Base plans |
storeAmounts | What the stores charge, per currency - a sale books this, not amounts | Your catalogue |
A blank store id hides that plan from the paywall: fill both before you submit, each with a storeAmounts entry in your base currency, since the boot check refuses an id that would book zero revenue.
What the app shows, and from where
| On screen | Comes from | Never from |
|---|---|---|
| A store price | priceString, the store's own localized string | storeAmounts or amounts |
| The plan, its expiry, any trial, the credits | GET /billing/status | the SDK's entitlements |
| The history, in the reader's locale | GET /billing/history | the store |
GET /billing/status answers for the active organization's owner, GET /billing/history for the signed-in user. History, credit packs, upgrade, restore and the external link show only where the viewer funds their own plan.