# Connect Superwall

> Send Superwall subscription events to Whisperr through a signed webhook, so Whisperr knows the billing state of each user.

Whisperr receives subscription events from Superwall through a webhook. It uses them to know the billing state of each user: in a trial, paid, cancelled with access left, payment failed, expired or refunded. The webhook needs no app code. Your app needs only the shared user ID below.

Connect one billing source per app. If your app uses RevenueCat to make purchases, connect [RevenueCat](/integrations/revenuecat/) instead.

## Use the same user ID in both SDKs

Whisperr links a Superwall customer to a Whisperr user by the `originalAppUserId` in Superwall’s events. It is the user ID that your app passes to Superwall `identify` before the first purchase. Call `identify` with the same user ID that you give to Whisperr `identify()`, at the same places, and call Superwall `reset` where you call Whisperr `reset`.

| Platform                | Identify                                     | Reset                        |
| ----------------------- | -------------------------------------------- | ---------------------------- |
| Swift (`SuperwallKit`)  | `Superwall.shared.identify(userId: user.id)` | `Superwall.shared.reset()`   |
| Android                 | `Superwall.instance.identify(user.id)`       | `Superwall.instance.reset()` |
| Flutter                 | `Superwall.shared.identify(user.id);`        | `Superwall.shared.reset();`  |
| Expo (`expo-superwall`) | `await identify(user.id)` from `useUser()`   | `signOut()` from `useUser()` |

Superwall’s notes on this ID:

- Call `identify` before the user buys. A purchase made before `identify` keeps Superwall’s own alias ID.
- On iOS, the ID reaches App Store events only when it is a UUID. Otherwise Superwall uses its alias ID.
- On Android, set `passIdentifiersToPlayStore` to `true` in the Superwall options. Otherwise Google Play receives a hashed ID.

Superwall alias IDs (`$SuperwallAlias:…`) never match a user. An app with no log-in, or whose user IDs Superwall cannot pass to the store, can set the Superwall user attribute `whisperr_id`, for example `Superwall.shared.setUserAttributes(["whisperr_id": id])`. Use the Whisperr anonymous ID for anonymous users. Of the Whisperr SDKs, only Flutter exposes it today, as `Whisperr.instance.anonymousId`. Whisperr reads no other user attribute.

## Connect

1. In the Whisperr dashboard, open **Integrations → Billing → Superwall**, or go straight to `https://app.whisperr.net/integrations?source=superwall`. Click **Create URL** and copy the webhook URL. A workspace owner or admin must do this step.
2. In Superwall, open **Integrations → Webhooks** and add an endpoint with that URL.
3. In the endpoint, click **Copy Secret**. Paste the signing secret (`whsec_…`) in the Whisperr dashboard. Whisperr refuses every event until the secret is saved, and checks the signature of each event with it.
4. Superwall sends no test event. Make a sandbox purchase: in TestFlight with a sandbox Apple ID, or with a Google Play license test account. The dashboard shows **Sandbox event received**. Superwall is now connected.

If the dashboard says that an event’s signature did not match, paste the signing secret again. If you rotate the secret in Superwall, paste the new one in Whisperr.

Whisperr uses one billing source for each app. To connect Superwall, first disconnect RevenueCat or Adapty if the app has one: open it in **Integrations → Billing** and hold **Hold to disconnect**.

## What Whisperr does with billing events

Superwall events go through the same billing states, billing events and subscription playbooks as RevenueCat events. See [What Whisperr does with billing events](/integrations/revenuecat/#what-whisperr-does-with-billing-events).

- **Sandbox events** show in the dashboard. They do not change a billing state and do not start a playbook.
- **Refunds** (a negative price on a cancellation or an expiration) set the subscription to `refunded`.
- **Prices** are converted to USD with the daily rate of the purchase date.

Whisperr stores a minimized copy of each event: type, store, product, dates, cancel and expiry reasons, and price. It stores no user attribute other than `whisperr_id`. After Whisperr matches an event, it keeps Superwall customer IDs only as keyed hashes.

## History

Whisperr sees Superwall events from the moment you connect. It does not import older history. An event that reaches Whisperr more than 72 hours after it happened, such as a replay, sets the billing state but starts no playbook.

## Check the match

After live events arrive, the dashboard shows the share of Superwall customers in the last 30 days that match a Whisperr user. Your coding agent can read the same numbers with the Whisperr MCP tool `get_superwall_status`.

## Common questions

### My app uses Superwall paywalls with RevenueCat purchases. Which one do I connect?

RevenueCat. Connect the source that makes the purchases. Whisperr uses one billing source per app.

### Does Superwall send a test event to Whisperr?

No. Make a sandbox purchase in TestFlight or with a Google Play test account. The dashboard then shows Sandbox event received.

### Does Whisperr import past Superwall events?

No. Whisperr sees Superwall events from the moment you connect.

Source: https://docs.whisperr.net/integrations/superwall/
