# 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

# Dynamic Values

Dynamic Values allow you to create rules and control flow statements to conditionally apply variables. You can use it for things like:

* Changing the text of a component based on which product is selected.
* Hide and show a modal from a button click.

To open the dynamic values editor, **click** on either the gear icon in the **component editor**, or simply **click** on any property in the **component editor**. In the dropdown, choose **Dynamic**:

![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/pe-editor-dynamic-values-present.gif)

When the dynamic values editor shows, **click** on **Add Value** to get started.

> **Tip:** Check out our introductory video covering [dynamic values on YouTube](https://youtu.be/bw9ve8d2rek?feature=shared).

### Assigning variables without conditions

**First off, to simply assign a variable *without* a condition, you still use the dynamic values editor.** For example, if you want some text component's color to match something you have in your [theme](/docs/dashboard/dashboard-creating-paywalls/paywall-editor-theme) — just select it and don't insert any rule.

Here, we set the text to the theme's primary color:

![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/pe-editor-dynamic-values-assign-var.gif)

### Setting dynamic values

The dynamic values editor works like most control flow interfaces. You set a condition, and choose what should happen when it's met. You can chain multiple conditions together, too. Or, simply use an if/else format.

Check out this example:

![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/pe-editor-dynamic-value-edit.png)

> **Note:** Notice how you can use [variables](/docs/dashboard/dashboard-creating-paywalls/paywall-editor-variables) within the dynamic values editor,
> too.

It's saying:

1. When the product has an introductory offer (i.e. the condition)
2. Then set the text of the component to "Start \{\{ products.selected.trialPeriodText }} free trial" (i.e. what to do when a condition is met)
3. Otherwise, set it to "Subscribe for \{\{ products.selected.price }} / \{\{ products.selected.period }}."

You can also add rules within a group.

### Rules versus group

When you add a condition, you'll have the choice to either add a rule or a group:

![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/pe-editor-dynamic-values-step-one.png)

Think about them like this:

* Use **rule** when you have one condition you're checking.
  * Ex: If the user has a free trial available, do this.
* Use **group** when you need to aggregate several conditions together to check.
  * Ex: If the user has a free trial available *and* they are in the United States, do this.
* Use **both** of them together to check complex conditions.
  * Ex: If the user has a free trial available *and* they are in the United States, *and* they are on a certain version, do this.

In programming terms, it's a bit like this:

```swift
if user.hasPro && (user.isLegacy && user.isEligibleForProPlus) {
    showUpsellToLegacyUsers()
}
```

The first part of that statement would be a **rule** and the second check that's grouped together would be a **group**.

> **Note:** You can add rules within groups, or more groups within an existing group.

### Free trial detection

A common use-case of dynamic values is to conditionally show or hide components, or change copy, based on whether or not the user is eligible for a free trial. To do this, set up a dynamic value as follows:

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

In short, use `products.hasIntroductoryOffer` to detect whether or not a free trial is available.

> **Note:** If a user has already claimed a free trial for any of the products within the subscription group,
> this value will be `false`.

### Examples

## Tab

This text component's color is to set to the theme's primary color without any condition (ie. it
should always be this color).<br />
![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/pe-editor-dynamic-values-no-condition.png)

## Tab

If the product has an introductory offer, the text component will read "Try for free".<br />
![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/pe-editor-dynamic-values-step-two.png)

## Tab

Here, we set the text to be larger than it normally would be if the user an introductory offer
and they haven't seen a paywall in 3 days.<br />
![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/pe-editor-dynamic-values-group.png)

## Tab

Here, some text is set if the user's app version is greater than `1.1.0` and they are on an
iPhone. If those are true, and they have an introductory offer — the text "Power up your iPhone
like never before" is used.<br />
![](https://claude-centralize-agent-preamble-superwall-docs.staffbar.workers.dev/docs/images/pe-editor-dynamic-values-combo.png)