# 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

# The Studio

Preview every paywall locally with superwall dev — devices, themes, locales, live variables, and simulated purchases.

`superwall dev` hosts the studio at `http://localhost:6100`: every paywall in your project as a card with a live miniature, and an editor per paywall with a device-frame preview at exact logical size. It's where you check everything you can't check in code.

```bash
superwall dev                # the current project
superwall dev examples/*     # several projects at once
```

`dev` needs no login, regenerates `superwall.d.ts` first (so route and product types are always current), and takes `--port`/`-p` (default 6100, moving to the next free port) and `--host`.

> **Tip:** Project problems — a stray file in `app/`, a duplicate route — print as warnings in dev. They're the same checks that block a push, so fix them as they appear rather than discovering them at ship time.

## What you can check

* **Devices** — iPhone SE through iPad Pro, plus Pixel. Switching devices also changes what the paywall sees as platform, model, and OS version, so platform-conditional code is testable too.
* **Light and dark** — the studio's theme toggle drives the same `dark` class the SDK stamps on device. Check both, always.
* **Locale** — switch languages to proof every catalog. See [Localization](/docs/framework/localization).
* **Rotation** — portrait and landscape, live. See `useDevice().orientation` in the [hooks reference](/docs/framework/hooks).
* **Trial eligibility** — a toggle that flips the store's answer, so both versions of a trial paywall are one click apart. See [Free trials](/docs/framework/trials).
* **Variables** — edit user attributes, device properties, placement params, and per-product variables live in the Variables panel. Values are seeded from your app's real sample data and products, so the preview reflects what production will see. See [Variables & personalization](/docs/framework/variables).

## Simulated outcomes

In dev, everything that would normally resolve from the host — purchases, restores, permission prompts, callbacks — prompts **you** to pick the outcome instead, so both branches of every flow are testable. Decline your own purchase to check the abandoned path; deny your own permission request to check the fallback copy.

Alongside it runs the **event log**: every message the paywall sends — haptics, page views, purchase attempts — as it happens. It's where you confirm that a tap fired its haptic, or that an action reached the host.

## Dev vs device

The same paywall runs against a simulated host in dev and the real SDK on device. What differs:

|                                 | `superwall dev`                                              | Real device                           |
| ------------------------------- | ------------------------------------------------------------ | ------------------------------------- |
| Product variables               | `undefined` until the studio injects your dashboard products | Delivered by the SDK                  |
| `purchase()` / `restore()`      | Simulated — you pick the outcome                             | Real store                            |
| `close()`, `openUrl()`, haptics | Logged in the event log                                      | Acted on by the host                  |
| Permissions / callbacks         | Studio prompts you                                           | OS prompt / your app's code           |
| Numeric variables               | Numbers                                                      | **Strings** — always `Number()` first |
| Presentation (`paywall_open`)   | Immediate                                                    | After preload, when actually shown    |
| Web checkout sheet              | Not mounted — verify on a pushed version                     | Works                                 |

A published paywall never falls back to simulated data — the simulation exists only in previews.

## The Push, Publish, and Promote buttons

The studio has buttons for the same operations as the CLI — good for quick iteration. For actually shipping, prefer the CLI: the buttons skip the diagnostics gate and the dashboard product check, can't resolve renames, and take no `-m` note. See [Push, promote & publish](/docs/framework/push-and-promote).