# Connect revenue

> Bring subscription revenue into Union from App Store Server Notifications or RevenueCat, and link each purchase to the person who made it.

Source: https://useunion.dev/docs/revenue · Updated 2026-10-23

Union reads revenue from two webhooks: Apple’s **App Store Server Notifications** and **RevenueCat**. Both describe the same purchases, so only one of them counts at a time.

## Which source counts

| Connected | What counts |
| --- | --- |
| App Store Server Notifications | Apple’s notifications. |
| RevenueCat only | RevenueCat’s webhooks. |
| Both | Apple’s notifications; RevenueCat events are stored but not counted, and the panel says so. |

Apple signs every notification and needs no third party, so it wins when both are connected.

## App Store Server Notifications

In **Settings → App Store Server Notifications**, create the notification URL and paste it into App Store Connect as the Production server URL. Apple accepts only one URL per app, so if your backend already receives notifications, enter its URL as the **forward** target: Union answers Apple first and forwards every notification unchanged, with retries and a log of each attempt.

Apple does not send a USD price, so revenue from notifications is shown per currency as charged.

## RevenueCat

Create a webhook in RevenueCat pointing at the URL from **Settings → RevenueCat**. Optionally add a **v2 secret key** (`sk_…`): Union checks it against RevenueCat before saving it, uses it to import subscriptions from before the webhook existed, and to look up purchasers.

## Link purchases to people

With **StoreKit 2**, pass Union’s install id as the `appAccountToken` on every purchase:

```swift
let result = try await product.purchase(
    options: Union.installUUID.map { [.appAccountToken($0)] } ?? []
)
```

With **RevenueCat**, set the subscriber attribute after `Purchases.configure`, and call `Union.identify(userId:)` with the same id you pass to `Purchases.logIn`:

```swift
if let id = Union.installId {
    Purchases.shared.attribution.setAttributes(["union_install_id": id])
}
```

> **The purchase token is not retroactive**
> Purchases made before `appAccountToken` ships can never be linked to a person. Ship it before the first release that sells anything, even if you connect revenue later.

Revenue totals do not depend on any of this: a purchase Union cannot link still counts, and the Revenue view shows how many subscriptions are unlinked.

## Strict anonymous projects

`Union.installUUID` is `nil` in strict anonymous mode, so purchases are counted but never linked to a person. Do not set `appAccountToken` from Union.
