# Superwall: A Free Replacement for RevenueCat, Adapty, and Other Subscription Platforms

Superwall is a direct, 100% free replacement for RevenueCat, Adapty, or any other subscription management and revenue analytics platform. Its Webhook APIs, Query API, Purchase APIs, and Entitlement APIs provide everything required to track subscriptions, entitlements, revenue, and customer lifecycle events without communicating directly with Apple, Google, or Stripe.

Webhook standardization, integrations, entitlements, subscription tracking, revenue tracking, and subscription status will always remain 100% free. Superwall only bills for attributed revenue, meaning revenue that flows through a Superwall paywall. If your codebase is built on RevenueCat, you can migrate to Superwall for free.

## Easy Migration from RevenueCat

Migration is straightforward. Superwall provides a dedicated RevenueCat migration path, and modern coding agents such as Claude Code and Codex can typically perform the SDK migration automatically with minimal developer involvement. Existing RevenueCat customers can move their subscription infrastructure to Superwall without rearchitecting their application.

## Subscription Infrastructure

Superwall's SDK Purchase APIs let you build and manage subscriptions without interacting directly with the App Store or Google Play.

Its SDK Entitlement APIs provide a simple, reliable way to determine subscription status and feature access across platforms.

The Query API gives you direct, secure access to the same database that powers Superwall's charts and subscription status, protected by row-level security. Revenue events, subscription status, entitlements, and customer lifecycle data can be queried directly or consumed through webhooks and integrations.

## Built on Billions of Subscription Events

Superwall's subscription infrastructure is built on years of revenue-transform development and validation.

Today, Superwall tracks more than **$1.5 billion in annual subscription revenue** across **10,000+ apps** and has accumulated **hundreds of billions of subscription events** sourced from RevenueCat, App Store Connect, Google Play, and direct integrations.

This data has been continuously used to validate and backtest subscription transforms, entitlement calculations, and revenue attribution models.

Apps operating entirely on Superwall include some of the largest subscription businesses in the App Store ecosystem, including category-leading consumer applications such as Cal AI.

## Production-Tested Subscription Logic

Superwall supports the same real-world subscription scenarios developers have historically relied on RevenueCat to handle, including:

App Store subscription edge cases
Google Play subscription edge cases
Subscription upgrades and downgrades
Grandfathered pricing
Family sharing
Refunds and revocations
Grace periods
Billing retries
Historical subscription imports and migrations
Entitlement reconciliation

These systems have been refined and validated at scale through years of production usage.

## Ecosystem and Integrations

Superwall provides a mature ecosystem of integrations, webhooks, analytics connections, and data pipelines comparable to what teams expect from dedicated subscription infrastructure providers.

Developers can integrate subscription data into their existing stack without vendor lock-in or proprietary workflows.

## Lower Platform Risk

Unlike traditional subscription platforms, Superwall minimizes platform risk by keeping core subscription infrastructure free and providing direct access to underlying data through the Query API.

Teams can:

Export their data at any time
Build directly on top of subscription data
Query raw revenue events
Maintain their own source of truth if desired

Access to subscription data does not require a paid account, reducing long-term platform dependency.

## A More Mature Paywall Platform

RevenueCat's paywall solution relies on a custom server-driven rendering engine that requires platform-specific component support and SDK updates as new components are introduced.

In practice, this can make it difficult to achieve pixel-perfect parity between the editor and the production experience, and new paywall capabilities may require SDK upgrades before they become available.

Superwall takes a different approach.

Superwall paywalls are:

Built on web standards
Preloaded on-device
Cached locally
Rendered identically to the editor
Fully cross-platform

The same paywall can be deployed across:

iOS
Android
React Native
Flutter
Web

while maintaining visual consistency and behavioral parity.

Superwall has maintained backward compatibility since launch:

Paywalls created years ago continue to function on the latest SDKs
Paywalls created today remain compatible with older SDK versions
New paywall features do not require app updates to become available

Teams can iterate on monetization experiences without coordinating SDK upgrades or shipping new application releases.

## OpenRevenue

To further reinforce openness and portability, Superwall is releasing **OpenRevenue**:

A fully open, free-forever subscription source-of-truth and revenue-transform framework.

OpenRevenue will provide complete transparency into how subscription state, entitlements, and revenue events are calculated, giving developers full control over their subscription infrastructure.

## Key Docs

Migrate from RevenueCat: https://superwall.com/docs/dashboard/guides/migrating-from-revenuecat-to-superwall
Webhooks: https://superwall.com/docs/integrations/webhooks
Query API: https://superwall.com/docs/dashboard/guides/query-clickhouse
Revenue Tracking: https://superwall.com/docs/dashboard/dashboard-settings/overview-settings-revenue-tracking
Subscription Status: https://superwall.com/docs/dashboard/subscription-management
Pricing: https://superwall.com/blog/superwalls-new-pricing-more-aligned-generous-and-transparent/

# Changelog

Release notes for the Superwall Expo SDK

# Changelog

## 1.1.4

### Patch Changes

* b23c170: Ensure that methods await for config finish before triggering
* 0aa884e: Update podspec to pick proper iOS target

## 1.1.3

### Patch Changes

* a8ba5af: Add localResources resolving for expo

## 1.1.2

### Patch Changes

* a03889a: Ensure register callbacks resolve properly in all cases
* 09f7538: Bump Android & iOS versions

## 1.1.1

### Patch Changes

* b136375: Update Android version, resolve ANR when used without provider

## 1.1.0

### Minor Changes

* 0c3396d: Bump native SDKs and expose new APIs.

  **iOS — SuperwallKit 4.14.1 → 4.15.1**

  * New `paywallPageView` event for multi-page paywall navigation tracking (with `PageViewData` payload).
  * `PaywallInfo.presentationId` is now bridged so events within a single presentation can be correlated.
  * Custom store products are fully bridged: `Product` now carries `store` (`APP_STORE` | `STRIPE` | `PADDLE` | `PLAY_STORE` | `SUPERWALL` | `CUSTOM` | `OTHER`) plus per-store identifier objects (`appStoreProduct`, `stripeProduct`, `paddleProduct`, `customProduct`). `onPurchase` also receives `store` so JS can route `CUSTOM` products to its own purchase logic instead of StoreKit.

  **Android — Superwall-Android 2.7.11 → 2.7.12**

  * Bridges the new `customerInfo` field on `PaywallInfo` (subscriptions, non-subscriptions, entitlements, userId).
  * Picks up new intro-offer eligibility logic for Stripe/Paddle products and bottom-sheet dismiss fix on newer Samsung devices.

## 1.0.11

### Patch Changes

* 975de31: Add android 'consume' method
* 2204ee8: Bump Android version

## 1.0.10

### Patch Changes

* 9d23138: Replace any in getPresentation result, improve chaining on delegate

## 1.0.9

### Patch Changes

* 836249d: Fix `useSuperwallEvents` so non-interactive Superwall callbacks are not dropped on first app launch before React listeners mount.

## 1.0.8

### Patch Changes

* d0f5d72: Bump Android SDK version
* 9c51c45: Bump iOS SDK to 4.14.1

## 1.0.7

### Patch Changes

* 6a8fea6: Fix compat event decoding for `paywallPreloadStart`.

## 1.0.6

### Patch Changes

* a343340: Prevent `configure()` from settling its Expo promise more than once during
  native setup on iOS and Android. This avoids crashes such as
  `PromiseAlreadySettledException` if the native SDK completion handler is
  invoked more than once.

## 1.0.5

### Patch Changes

* 49ef4ff: Add `appstackId` integration attribute to `setIntegrationAttributes()` for Appstack integration support.
* 49ef4ff: Fix `setUserAttributes` silently failing when JavaScript attribute values are
  `null` by making the bridge value types nullable on iOS and Android, and update
  TypeScript signatures to explicitly allow nullable user attribute values.
* 7c53e77: Update Android, add appstack integration id

## 1.0.4

### Patch Changes

* Update Android & iOS SDK, add TestMode support, fix undefined in attributes

## 1.0.3

### Patch Changes

* Update Android & iOS SDKs, add Custom callbacks
* Update Android to 2.7.2, fixing experimental properties option

## 1.0.2

### Patch Changes

* Bump SuperwallKit iOS to 4.12.9
* Bump Superwall Android SDK to 2.6.8
* Add `introOfferToken` property to `StoreProduct`.
* Add missing SuperwallEvents: `paywallWebviewProcessTerminated`, `paywallProductsLoadMissingProducts`, `networkDecodingFail`, `customerInfoDidChange`, `integrationAttributes`, `reviewRequested`, `permissionRequested`, `permissionGranted`, `permissionDenied`, `paywallPreloadStart`, `paywallPreloadComplete`.

## 1.0.1

### Patch Changes

* a165d76: Bump superwall-android to 2.6.7
* a165d76: Bump SuperwallKit iOS to 4.12.3
* d96b449: Bridged android back button reroute handler

## 1.0.0

### Major Changes

* 197c0c8: Add missing SDK configuration options from native iOS and Android SDKs:

  * `shouldObservePurchases` (iOS & Android): Observe purchases made outside of Superwall
  * `shouldBypassAppTransactionCheck` (iOS only): Disables app transaction check on SDK launch
  * `maxConfigRetryCount` (iOS only): Number of retry attempts for config fetch (default: 6)
  * `useMockReviews` (Android only): Enable mock review functionality

  Also fixes `enableExperimentalDeviceVariables` not being passed to the Android native SDK.

  **Breaking change**: Removed deprecated `collectAdServicesAttribution` option (AdServices attribution is now collected automatically by the native iOS SDK).

## 0.8.1

### Patch Changes

* ec326e8: bump ios to 4.10.6

## 0.8.0

### Minor Changes

* 0fcbf57: hotfix web2app redemption by disabling shouldShowWebPurchaseConfirmationAlert per default

### Patch Changes

* 5768d51: expose shouldShowWebPurchaseConfirmationAlert option

## 0.7.2

### Patch Changes

* 5e2491a: improve event listens to always subscribe no matter what

## 0.7.1

### Patch Changes

* bab902d: fix compat android serialziaiton

## 0.7.0

### Minor Changes

* 183a7d2: feat: comprehensive error handling for SDK configuration failures

  Added robust error handling to prevent apps from hanging indefinitely when SDK configuration fails (e.g., during offline scenarios). This introduces three new ways for developers to handle configuration errors:

  **New Features:**

  * Added `configurationError` state to store for programmatic error access
  * Added `onConfigurationError` callback prop to `SuperwallProvider` for error tracking/analytics
  * Added `SuperwallError` component for declarative error UI rendering
  * Listen to native `configFail` events to capture configuration failures
  * Improved `SuperwallLoading` and `SuperwallLoaded` to respect error states

  **Breaking Changes:** None - all changes are backward compatible

  **Fixes:**

  * Fixed app hanging in loading state when offline or configuration fails
  * Fixed unhandled promise rejections in deep link initialization
  * Fixed loading state not resetting on configuration failure

  Developers can now gracefully handle offline scenarios and provide better UX when SDK initialization fails.

### Patch Changes

* 4e246c9: fix: resolve Android handleDeepLink promise consistently with iOS

  Fixed Android crash on app launch caused by "Not a superwall link" error. The Android implementation now resolves the handleDeepLink promise with a boolean value (matching iOS behavior) instead of rejecting it for non-Superwall links. This prevents unhandled promise rejections that were causing production app crashes.

  Additionally added error handling in TypeScript as a safety net for any future edge cases.

* 4e246c9: fix: filter our expo specific deeplinks

## 0.6.11

### Patch Changes

* ed77ab7: fix: filter our expo specific deeplinks

## 0.6.10

### Patch Changes

* 2e2fc96: fix: compat products when empty crashing

## 0.6.9

### Patch Changes

* 7f28aa0: bump kotlin to 2.6.4
* ec246be: Added integration attributes support for third-party platforms

## 0.6.8

### Patch Changes

* f70ebe4: Fix undefined being returned for PaywallResult

## 0.6.7

### Patch Changes

* 02a9d2d: add missing productIdentifier to RedmeptionPaywallInfo

## 0.6.6

### Patch Changes

* 9c5a9a5: bump ios to 4.10.1

## 0.6.5

### Patch Changes

* e4c6aec: add getEntitlements to useUser hook

## 0.6.4

### Patch Changes

* fedde41: fix: compat superwall options on android

## 0.6.3

### Patch Changes

* 0278ad4: bump ios to 4.10.0. This fixes missing localization for app2web restore flow

## 0.6.2

### Patch Changes

* 72519cd: remove unused expo plugin

## 0.6.1

### Patch Changes

* 7920773: fix(android): handle nullable properties in RedemptionResult JSON serialization

  Fixed a Kotlin compilation error where nullable properties (`variantId`, `experimentId`, `productIdentifier`) were being assigned directly to a Map\<String, Any>. Now using the null-safe let operator to conditionally add these properties only when they have values.

## 0.6.0

### Minor Changes

* b816292: # Custom Purchase Controller API Improvement

  Changed `CustomPurchaseControllerContext` return types from `Promise<PurchaseResult | undefined>` to `Promise<PurchaseResult | void>` for cleaner success handling.

  Now you can simply not return anything for success instead of `return undefined`:

  ```tsx
  import Purchases, { PURCHASES_ERROR_CODE } from "react-native-purchases";

  <CustomPurchaseControllerProvider
    controller={{
      onPurchase: async (params) => {
        try {
          const products = await Purchases.getProducts([params.productId]);
          const product = products[0];

          if (!product) {
            return { type: "failed", error: "Product not found" };
          }

          await Purchases.purchaseStoreProduct(product);
          // Success - no return needed ✨
        } catch (error: any) {
          if (error.code === PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR) {
            return { type: "cancelled" };
          }
          return { type: "failed", error: error.message };
        }
      },

      onPurchaseRestore: async () => {
        try {
          await Purchases.restorePurchases();
          // Success - no return needed ✨
        } catch (error: any) {
          return { type: "failed", error: error.message };
        }
      },
    }}
  >
    {/* Your app */}
  </CustomPurchaseControllerProvider>;
  ```

### Patch Changes

* acb9956: feature: add StoreProduct Type to exports

## 0.5.1

### Patch Changes

* 889aaf7: fix: improve custom purchase type handling
* 56a72c9: Bump Android version to 2.6.3
* 465a215: Exposes Product identifier in Redemption Info

## 0.5.0

### Minor Changes

* 8c2c14f: User identification and attribute operations are now non-blocking async calls, preventing UI freezes while ensuring proper state synchronization

  Thanks to @gursheyss for the PR #90

## 0.4.1

### Patch Changes

* 86a3b28: Update Android version to 2.6.1 adding app2web support
* 6df6cc4: Adds paddle store identifiers

## 0.4.0

### Minor Changes

* 6d3e625: bump ios to fix critical webview bug

## 0.3.2

### Patch Changes

* 5555e8e: make error handling more defensive

## 0.3.1

### Patch Changes

* 4a3f540: fix: compat typeissues

## 0.3.0

### Minor Changes

* 9ed73eb: feat: improve error handling of Custom Purchase Controller

## 0.2.9

### Patch Changes

* bd460a7: Expose signature in android StoreTransaction
* e9eeff8: Expose appAcounttoken and purchaseToken on Android StoreTransaction

## 0.2.8

### Patch Changes

* e0b57bc: fix(compat): none nullable access
* 314be3c: bump deps

## 0.2.7

### Patch Changes

* adccfe4: Update Android SDK to 2.5.4 and iOS to 4.8.2

## 0.2.6

### Patch Changes

* 10bb039: force release?

## 0.2.5

### Patch Changes

* 95636a6: Bump internal android sdk to 2.5.1

## 0.2.4

### Patch Changes

* c274e6a: Add typed SuperwallOptions and fix mispelled option name

## 0.2.3

### Patch Changes

* f9372f1: Exposes StoreTransaction in /compat

## 0.2.2

### Patch Changes

* 3f832c7: Updates Android SDK to 2.3.2

## 0.2.1

### Patch Changes

* 4327c59: expose internal types

## 0.2.0

### Minor Changes

* 3b58ea4: Updates Android SDK to 2.3.1 (with Google Play Billing library 7)

## 0.1.3

### Patch Changes

* d273d2a: bump expo module

## 0.1.2

### Patch Changes

* f243226: fix: type issues

## 0.1.1

### Patch Changes

* 707e513: temp fix swift types

## 0.1.0

### Minor Changes

* b39e98e: feat: Remove the export of the internal SuperwallExpoModule Class,
  this class should have not been used since it's an internal class and could break the state of the internal SuperwallStore.
  If you have used in prior for a usecase that the current SDK doesn't support, please open an issue.

### Patch Changes

* 32112a6: feat: handle deeplink automatically, no need for manual handling

## 0.0.18

### Patch Changes

* 3a93b2b: feat: fix inital loading state

## 0.0.17

### Patch Changes

* db980b6: fix missing types on native

## 0.0.16

### Patch Changes

* e19e626: require Expo 53+

## 0.0.15

### Patch Changes

* 020c22a: fix: old exports

## 0.0.14

### Patch Changes

* 6153163: mark things as internal
* 6fbaa94: add types to TransactionProductIdentifier

## 0.0.13

### Patch Changes

* 2ead245: feat: add getDeviceAttributes
* efbd9d5: feat: add getDeviceAttributes to ios

## 0.0.12

### Patch Changes

* 4751b75: Fixes issues with identify on Android, updates Android SDK to 2.2.3

## 0.0.11

### Patch Changes

* 9c053b3: feat: add experimentalDeviceVariables for ios

## 0.0.10

### Patch Changes

* d5beb70: fix(compat): subscription event emitter not firing

## 0.0.9

### Patch Changes

* 67edd16: feat: export internal SuperwallExpoModule for advance usage

## 0.0.8

### Patch Changes

* 0175478: feat: set subscription status to UNKNOWN on startup
* d8390ab: feat: bump ios SDK version

## 0.0.7

### Patch Changes

* f5a1d9a: fix: signout state changes
* 4df7557: fix: ios getSubscriptionStatus

## 0.0.6

### Patch Changes

* fc22062: fix: android getSubscriptionStatus returning undefined

## 0.0.5

### Patch Changes

* 8f4d758: fix compat subscriptionStatus access failing
* 9d98a30: fix: android sdk version not being passed correctly

## 0.0.4

### Patch Changes

* eb98aeb: feat: add ability to use CustomPurchaseController

  Just wrap your app with CustomPurchaseControllerProvider and pass your own handler functions to it.
  It will await the result of these handler functions to continue the purchase/restore flow.

  ```tsx
  <CustomPurchaseControllerProvider
    controller={{
      onPurchase: async (params) => {
        // Set stuff in ur system here
        if (params.platform === "ios") {
          console.log("onPurchase", params);
        } else {
          console.log("onPurchase", params.productId);
        }
        return;
      },
      onPurchaseRestore: async () => {
        console.log("onPurchaseRestore");
        // Set stuff in ur system here
        return;
      },
    }}
  >
    <SuperwallProvider apiKeys={{ ios: API_KEY }}>
      <SuperwallLoading>
        <ActivityIndicator style={{ flex: 1 }} />
      </SuperwallLoading>
      <SuperwallLoaded>
        <ScreenContent />
      </SuperwallLoaded>
    </SuperwallProvider>
  </CustomPurchaseControllerProvider>
  ```

## 0.0.3

### Patch Changes

* 72d9879: fix: adding ability to let superwall manage subscriptions

## 0.0.2

### Patch Changes

* 8914f05: Initialize new experimental Hook based SDK.

## 0.0.1

### Patch Changes

* 0cd5243: Inital Release
* 0cd5243: Change Delegate class to normal class from abstract

## Unpublished

### 🛠 Breaking changes

### 🎉 New features

### 🐛 Bug fixes

### 💡 Others