For the complete documentation index, see llms.txt. Prefer markdown by appending .md to documentation URLs or sending Accept: text/markdown.

Billing

Use RevenueCat or Superwall on device for checkout UX, but grant access only after webhook-verified events on the API.

Mobile billing SDKs run on the device. That is fine for presenting paywalls and starting purchases - it is not enough to unlock paid features by itself.

Client vs server

On deviceOn the API
RevenueCat / Superwall public SDK keys (EXPO_PUBLIC_*)Webhook signing secrets
Paywall UI and purchase sheetsSignature verification
Optimistic UI (“thanks for subscribing”)Customer / entitlement updates in the database

Webhook handlers live with the shared API (often next to web billing routes) and use @workspace/billing-mobile/server:

packages/api - mobile billing webhook
import { webhookHandler, provider } from "@workspace/billing-mobile/server";

export const billingRouter = new Hono().post(`/webhook/${provider}`, (c) =>
  webhookHandler(c.req.raw),
);

Rules when you extend handlers:

  1. Verify the provider signature before mutating data
  2. Use environment-specific secrets (sandbox vs production)
  3. Never grant a plan solely from a client callback or deep link

API deployment required

Production purchases need a deployed API that receives provider webhooks. See Mobile billing webhooks and the web deployment checklist.

Public SDK keys

Client SDK keys for Superwall / RevenueCat are often required in the app. Treat them like EXPO_PUBLIC_ values: anyone can extract them.

Mitigations:

  • Restrict keys in the provider dashboard (bundle id / package name)
  • Prefer server-side entitlement as the source of truth
  • Rotate keys if they leak into a public repo or wrong environment

Entitlements in the UI

Gate screens with the billing summary / entitlements returned by your authenticated API, not only with the native SDK’s local cache.

Local SDK state is useful for snappy UX; the server must still refuse unpaid access on protected routes.

How is this guide?

Last updated on

On this page

Ship your startup everywhere. In minutes.Try TurboStarter