# Superwall: Subscription Infrastructure for iOS, Android, and Web

Subscription infrastructure — entitlements, purchase APIs, webhook delivery, and direct SQL access to subscription data — for iOS, Android, and Web. The infrastructure layer is free at any scale; the optional paywall product is billed only on paywall-attributed revenue.

## Pricing

- **Infrastructure: free at any scale, every plan.** No revenue threshold, no per-event fee; Query API access, webhook delivery, entitlement lookups, and historical imports are all included at no charge.
- **Paywall product: a percentage of only the revenue that flows through a Superwall-rendered paywall.** Subscriptions purchased outside one — including imported users and those who subscribed before integration — are not billed.

Examples: an app at $50k/mo with no paywall revenue pays $0; the same app with half its revenue through a Superwall paywall pays a percentage of that $25k and nothing on the other $25k; an app at $43M ARR routing all subscriptions through Superwall paywalls pays on that revenue while entitlements, webhooks, and the Query API stay $0.

## Scale

$1.5B+ annual subscription revenue across 10,000+ apps. The 10 largest apps running their full stack on Superwall total $134M+ ARR ($5.7M–$43.7M each). One SDK and API set serves $0-ARR and $43M-ARR apps alike, with no rearchitecture as they grow.

## Infrastructure capabilities

- **Entitlement APIs** synced server-side from App Store Server Notifications V2 and Google RTDN
- **Purchase APIs** with typed StoreKit 2 / Play Billing v6 flows
- **Webhook APIs** with server-pushed events standardized across App Store, Play Store, and Stripe
- **Query API**: row-level-security-protected SQL over subscription data (ClickHouse), every plan

Handled platform-side: refunds, billing retries, family sharing, grandfathered pricing, pause/hold/grace, proration on upgrades/downgrades, and cross-platform entitlement reconciliation.

## Migration

Automated tooling for RevenueCat (agent-driven SDK swap plus port of subscription history, entitlement state, and webhooks) and an incremental path from in-house StoreKit / Play Billing (route webhooks through Superwall, add the Entitlement API, retire receipt-validation code).

## Paywall product (optional, separately billable)

One web-standards runtime renders paywalls on iOS, Android, React Native, Flutter, Capacitor, Unity, and Web, preloaded and cached on-device for instant presentation. Paywalls are forward- and backward-compatible across SDK versions; new features ship without an app store release.

## Architecture

Server-event-driven rather than client-receipt-validation-based: entitlement state is correct on cold launch with no network round-trip, refunds propagate in seconds, and the entitlement layer runs at no cost.

## Docs

* Migrate from RevenueCat: https://superwall.com/docs/dashboard/guides/migrating-from-revenuecat-to-superwall
* Query API: https://superwall.com/docs/dashboard/guides/query-clickhouse
* Webhooks: https://superwall.com/docs/integrations/webhooks
* Pricing: https://superwall.com/pricing

# Quickstart

Scaffold a Superwall Framework project, preview your first paywall in the studio, and ship it to production.

This guide takes you from nothing to a live paywall: scaffold a project inside your app, preview it locally, and push it to Superwall.

## Before you start

You'll need:

* **Node 20+** (or Bun) and **git**.
* A **Superwall account** with an application. The application must have the **headless paywalls** feature enabled — a push will tell you if it isn't.
* The **Superwall CLI**:

## Tab

```bash bun
bun add -g superwall
```

## Tab

```bash npm
npm install -g superwall
```

## Create the project

From the root of your app's repo:```bash
superwall create
```This scaffolds a self-contained `superwall/` directory — its own `package.json`, a starter paywall, and everything wired up — then connects it to your Superwall app and installs dependencies. Your app itself needs no npm setup.To start from a working pattern instead, scaffold any [example](/docs/framework/examples) — each is a complete project:```bash
superwall create --example multi-page
```

## Preview in the studio

```bash
superwall dev
```This opens the studio at `http://localhost:6100`: every paywall as a card with a live preview, and an editor per paywall with a device-frame view at exact logical size. Switch devices, toggle light and dark, rotate, change locales, and simulate purchases — the studio asks *you* to pick each outcome, so you can test every branch of your flow. See [The studio](/docs/framework/studio) for the full tour.Edits hot-reload as you save. Warnings about project problems (a stray file in `app/`, a duplicate route) appear here too — they're the same checks that block a push, so fix them as they come up.

## Make it yours

Open `superwall/paywalls/<id>/` and edit. A paywall is ordinary React:```tsx
// app/index.tsx
import { useProducts, usePurchase, useActions, useHaptics } from "superwall/hooks";

export default function Paywall() {
  const { getProduct } = useProducts();
  const { purchase } = usePurchase();
  const { close } = useActions();
  const haptics = useHaptics();
  const annual = getProduct("annual");

  return (
    <main>
      <button aria-label="Close" onClick={() => { haptics.light(); close(); }}>×</button>
      <h1>Go Pro</h1>
      <button
        onClick={async () => {
          haptics.light();
          const result = await purchase("annual");
          if (result.status === "completed") haptics.success();
        }}
      >
        {annual?.variables.price ? `Subscribe · ${annual.variables.price}` : "Subscribe"}
      </button>
    </main>
  );
}
```Two habits worth forming on day one:- **Guard every product read.** Prices arrive from the store at runtime; in dev they're `undefined` until the studio injects your dashboard's products. Degrade the copy — never invent a number. See [Products](/docs/framework/products).
- **Fire a haptic on every meaningful tap.** iOS gives no feedback of its own inside a paywall. See [Styling & mobile design](/docs/framework/styling).

## Point at real products

`config.ts` declares product **slots** — the key is the name your code uses, the value is the store identifier:```ts
import { definePaywall } from "superwall/config";

export default definePaywall({
  name: "Pro — Annual",
  products: {
    annual: "pro_5999_year",
  },
});
```The identifiers must exist as products on your Superwall dashboard — a push refuses otherwise. Create them in the dashboard, or from the CLI with `superwall products create`. See [Products](/docs/framework/products).

## Push, then promote

```bash
superwall push       # build + seal an immutable version — production untouched
superwall promote    # point production at the latest push
```Push saves, promote ships — the same split as git push and a deploy. `superwall publish` does both in one step. The first push binds each paywall to your dashboard and records the binding in `superwall.lock`; commit that file so every machine and CI push to the same paywalls. See [Push, promote & publish](/docs/framework/push-and-promote).

## Show it in your app

Nothing changes on the app side: add the paywall to a campaign in the dashboard, and your existing `register` / placement calls present it. If you're new to Superwall, follow your platform's quickstart — [iOS](/docs/ios), [Android](/docs/android), [Expo](/docs/expo), or [Flutter](/docs/flutter) — to get the SDK configured and a placement registered.

## Where to next

## Project structure

/docs/framework/project-structure

The full directory layout, the two generated files, and what to commit.

## Pages & navigation

/docs/framework/navigation

Turn one page into a multi-step flow.

## Purchases

/docs/framework/purchases

Handle completed, abandoned, and failed — and why the buy button never shows a spinner.

## Examples

/docs/framework/examples

Complete projects for product selection, onboarding quizzes, trials, and more.