# 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

# Tips

Practical advice for building effective flows.

Want to watch some of these tips in action? Check out this video:

[Watch on YouTube](https://youtu.be/lkIxyC6tQwo)

### Setting custom user attributes

Setting custom user attributes inside a flow is one of the most useful techniques available. Any tap behavior can set a user attribute, which means buttons, multiple choice selections, and other interactive elements can all tag users with data as they move through the flow.

Once a user attribute is set, you can use it in a few different ways:

* **Within the same flow.** Personalize a later screen with the value (e.g., "Awesome John, welcome to the app!"), route to a different page via branching, or change which products and offers to show.
* **In your app.** Use the [SuperwallDelegate](/docs/sdk/guides/using-superwall-delegate) to send it straight to your analytics provider, create user cohorts, or handle it however you need.

For example, a "Next" button can do more than navigate to the next page. It could, for example, also read from a multiple choice selection, and set its selection to a custom user attribute. By using the tap behavior of "Set Attribute", the value will be set to the user:

![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/flows_ca.jpg)

In addition, your app can handle the attribute using the delegate:

```swift
extension MySuperwallDelegate: SuperwallDelegate {
    func userAttributesDidChange(newAttributes: [String : Any]) {
        // The attribute set in the flow is sent here
    }
}
```

This works for any data you collect in a flow, not just multiple choice. Text input values, quiz responses, demographic selections, and preferences can all be stored as attributes and forwarded to your analytics, CRM, or backend.

### After purchase behavior

By default, when a user makes a purchase, the paywall or flow will close. But in Flows, you might want to continue. For example, you could show a thank-you message or collect feedback.

To set something like this up:

1. Select the purchase action on your button.
2. Look for the **After purchase** section.
3. Add one or more actions:
   * **Close:** Dismisses the flow (the default).
   * **Navigate Page:** Advances to the next page in the flow. This is the most common choice for flows where the purchase happens mid-journey.
   * **Open URL:** Opens a link after purchase.
   * **Custom Action:** Triggers a custom action in your app.
   * **Custom Placement:** Registers a placement after purchase.
   * **Set Attribute:** Sets a user attribute when the purchase completes.
   * **Set State:** Updates a state variable.

![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/flows_tips_post_purchase.jpg)

The **Navigate Page** option is particularly useful in flows. Instead of closing after purchase, the user moves to the next connected page. This opens up use cases like:

* Showing a personalized welcome or thank-you message.
* Collecting feedback about why they subscribed.
* Presenting an upsell for an add-on product.
* Guiding users through initial setup.
* Placing a paywall in the middle of a flow and continuing the journey after conversion.

Purchase actions also include an **On Abandon** section. Use it when users should take a different path if they open the purchase sheet and cancel before completing the transaction. For example, you can close the Flow, navigate to a recovery page, set a state variable, or register a custom placement.

For the full option list and SDK requirements, see [Purchase outcome actions](/docs/dashboard/dashboard-creating-paywalls/paywall-editor-styling-elements#purchase-outcome-actions).

### Simulate permission prompts

Using the permissions tap behavior, you can test Flows without having to run it on device. The canvas view will allow you to mock either response when you interact with a component with the permission behavior:

![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/flows_tips_mock_perms.jpg)

### Use indicators for longer flows

If your flow has more than 3-4 pages, add an Indicator element. Users are more likely to complete a flow when they can see:

* How far they've come.
* How much is left.

Progress visibility reduces abandonment, especially in onboarding flows where users might otherwise wonder "how much longer is this?"

### Keep flows focused

Flows work best when they have a clear, single purpose:

* **Onboarding:** Gathering preferences and introducing the app.
* **Cancellation:** Understanding why users are leaving and offering alternatives.
* **Upsell:** Guiding users to a higher tier or add-on.

If a flow is getting too long or trying to do too many things, consider splitting it into multiple flows. A focused 5-page flow is better than a sprawling 15-page one. When building a new flow, build linear first so all your pages are created and connected in a straight line, then test the basics to make sure navigation works and content looks right, and finally add branching once the foundation is solid. It's much easier to debug a simple flow than a complex one, so get the basics working before adding sophistication.