# 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

# Retention Campaigns

A/B test Apple retention messages with retention campaigns. Choose which subscribers see which message, split traffic between messages, and compare save rates.

Retention campaigns let you test which [Apple retention messages](/docs/integrations/apple-retention-messaging) keep subscribers from canceling. Each campaign covers a set of products and locales. Inside a campaign, you group subscribers into audiences, give each audience one or more messages, and split traffic between those messages. The **Results** tab shows how many subscribers each message saved.

> **Note:** Retention campaigns are rolling out. If you don't see **Retention campaigns** on the **Retention messaging** page, contact [Superwall Support](https://support.superwall.com).

> **Note:** Retention campaigns are separate from your [Superwall campaigns](/docs/dashboard/dashboard-campaigns/campaigns). They live on the **Retention messaging** page, don't use the Superwall SDK, and only control the message Apple shows in the App Store's cancellation flow.

![The Retention messaging page with Save rate and Total saves cards, the Retention campaigns list and the Message library](https://superwall.com/docs/images/retention-campaigns-overview.jpg)

## How it works

1. A subscriber opens their subscription details in the App Store.
2. Apple calls your Superwall callback URL with the subscription's product, the subscriber's locale and the subscription's original transaction ID.
3. Superwall finds the campaign whose placements include that product and locale.
4. Superwall checks the campaign's live audiences from top to bottom and uses the first one whose filters match. If no audience matches, it uses the campaign's **Fallback** message.
5. Superwall picks one of the audience's messages based on its split and returns it to Apple.
6. When the subscriber taps **Cancel Subscription**, Apple shows that message on the cancellation screen.

Superwall assigns each subscription to a message from its original transaction ID, so the same subscription gets the same message every time. If you change an audience's split, some subscriptions can move to a different message.

## Requirements

* Retention messaging set up for your app, including access from Apple and the callback URL. See [Apple Retention Messaging](/docs/integrations/apple-retention-messaging#apple-callback-url).
* An App Store Connect API key in **Integrations → Revenue tracking**. Superwall uses it to check your products, subscription groups and promotional offers.
* Messages in your [Message library](/docs/integrations/apple-retention-messaging#messages) that you've submitted to Apple. Apple only shows messages it has approved.

## Create a campaign

1. Open **Integrations → Retention messaging** and choose **Production** or **Sandbox**. Campaigns, messages and results are separate for each environment.
2. Under **Retention campaigns**, click **Create campaign**.
3. Enter a **Reference name**.
4. Under **Placements**, choose **Products** and **Locales**. A placement is a product being canceled plus the subscriber's locale. Each selected product uses every selected locale. Locales must be exact Apple locales, such as `en-US`.
5. Choose a **Fallback message**. Apple shows it when no audience matches or all audiences are paused.
6. Create the campaign.

A new campaign has only its **Fallback**. Superwall sends the Fallback message to Apple as the default message for each placement, so Apple can show it even when it can't reach Superwall in time.

### Placement rules

* Each product and locale pair belongs to one campaign per environment. Pairs that another campaign or a legacy configuration already uses show **Used by** and its name.
* Once Apple has a Fallback message for a placement, you can't remove that placement from the campaign. You can still add new ones.
* If Apple doesn't have a placement's Fallback message yet, the campaign shows a warning that placements need attention. Click **Open placements**, then **Sync defaults**.

## Add audiences

Audiences decide which subscribers in a campaign see which messages.

1. Open the campaign. In the sidebar, click **Add audience** next to **Audiences**.
2. On the **Filters** tab, choose the products and locales this audience matches, then click **Save changes**. Audiences can only filter on products and locales within the campaign's placements. Leave a filter empty to match all of the campaign's products or locales.
3. Add messages on the messages tab. See [Add messages and set the split](#add-messages-and-set-the-split).
4. Click **Set live** when the audience is ready. New audiences start paused, and **Set live** is available once the audience has at least one message.

Audiences are evaluated from top to bottom. Drag them to change the order. **Fallback** always runs last and can't be removed, reordered or filtered.

To stop showing an audience's messages, click **Pause**. Paused audiences are skipped, and subscribers they would have matched fall through to the next audience or to **Fallback**.

## Add messages and set the split

![An audience](https://superwall.com/docs/images/retention-campaign-messages.jpg)

1. On the audience's messages tab, click **Add message**.
2. Choose a **Message** from your Message library and enter a **Reference name**.
3. Choose a **Message type**:
   * **Message only**: Apple shows the message.
   * **Alternate product**: Apple shows the message with an option to switch to another product. Choose a product in the same subscription group.
   * **Promotional offer**: Apple shows the message with a promotional offer. Choose a product in the same subscription group and enter the **Offer ID** of a promotional offer configured for that product in App Store Connect.
4. The first message gets 100% of the audience, and messages you add after it start at 0%. Click **Edit split** to set the share of subscribers each message gets. Percentages must be whole numbers that total 100%.

You can add a message once it's been submitted to Apple for every locale the audience covers. Apple only shows messages it has approved, so check that the message's status is **Approved** before you set the audience live. Messages with images can't be used as an **Alternate product** or **Promotional offer**.

You can't edit or delete a message while a campaign uses it. To test new copy, create a new message in the Message library and add it to the audience.

## Read the results

Each audience, and **Fallback**, has a **Results** tab that compares that audience's messages:

* **Messages sent**: responses Superwall sent to Apple with this message. Only the last response per subscription per UTC day counts, so this isn't a count of unique subscribers. Apple doesn't confirm that a message was displayed.
* **Saves**: messages sent where the subscriber didn't cancel within 24 hours.
* **Save rate**: saves divided by messages sent.
* **Pending**: messages sent whose 24-hour window is still open. These count as saves until the window closes.

Results cover the audience's whole lifetime. The **Results** tab doesn't calculate statistical significance.

The **Retention campaigns** list on the **Retention messaging** page shows each campaign's save rate and saves for the selected date range. For more detail, the [Retention Messaging Save Rate](/docs/dashboard/charts/retention-messaging-save-rate) and [Retention Messaging Saves](/docs/dashboard/charts/retention-messaging-saves) charts can be broken down by **Retention Campaign**, **Retention Audience**, **Retention Variant** and **Retention Selection**.

## Limits

* Campaigns can't be deleted. To stop a campaign's audiences, pause them. Subscribers then see the campaign's **Fallback** message.
* Audiences can only filter on products and locales.
* Each product and locale pair can belong to only one campaign or legacy configuration per environment.

## Apps set up before retention campaigns

If your app used **Default messages** and **Real-time configurations** before retention campaigns, Superwall Support can move them into a campaign. Your existing messages keep their Apple identifiers and appear in the Message library.

Once retention campaigns are on for your app, you can't create new default messages or real-time configurations. Their **Create** buttons show **Deprecated**. Existing ones keep working. A campaign can't use a product and locale pair that a default message or real-time configuration already uses, so ask Superwall Support to move them into a campaign.

## Run an A/B test

The **Create campaign** dialog doesn't have A/B test options. You set up a test inside an audience after you create the campaign:

1. [Create a campaign](#create-a-campaign) with your products, locales and a Fallback message.
2. [Add an audience](#add-audiences) and choose its filters.
3. [Add two or more messages](#add-messages-and-set-the-split) to the audience.
4. Click **Edit split** to divide traffic between the messages, for example 50% and 50%.
5. Click **Set live**.
6. Compare the messages on the audience's [Results](#read-the-results) tab.