> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encorekit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using RevenueCat

> Integrate Encore offers seamlessly with RevenueCat paywalls.

## Overview

Present Encore retention offers when users dismiss your RevenueCat paywall without converting.

***

## Presenting Offers

### Option 1: Using PaywallView

If you're using RevenueCat's `PaywallView` component, use the `onRequestDismiss` callback to trigger Encore:

```swift theme={null}
import RevenueCat
import RevenueCatUI
import Encore

PaywallView(
    placement: "your_placement",
    params: [String: Any]?,
    paywallOverrides: PaywallOverrides?,
    onRequestDismiss: { paywallInfo, paywallResult in
        // User dismissed without purchasing - trigger Encore
        Encore.placement().show()
    },
    feature: (() -> Void)?
)
```

***

### Option 2: Using presentPaywallIfNeeded Modifier

If you're using the `.presentPaywallIfNeeded` modifier, use the `onDismiss` callback:

```swift theme={null}
import RevenueCat
import RevenueCatUI
import Encore

YourView()
    .presentPaywallIfNeeded(
        presentationMode: {.fullScreen, .sheet, .default},
        onDismiss: {
            // User dismissed without purchasing - trigger Encore
            Encore.placement().show()
        }
    )
```

<Tip>
  See the SDK Reference for complete API details: [placement()](../sdk-reference/placement) and [onPurchaseRequest()](../sdk-reference/on-purchase-request)
</Tip>

***

## Handle Offer Results

Register RevenueCat as your purchase handler at app launch so Encore delegates purchases automatically.

### Register `onPurchaseRequest`

```swift theme={null}
Encore.shared.onPurchaseRequest { purchaseRequest in
    let products = try await Purchases.shared.products([purchaseRequest.productId])
    guard let product = products.first else { return false }
    let result = try await Purchases.shared.purchase(product: product)
    return !result.userCancelled   // true → Encore dismisses the offer sheet
}
```

### Register `onPassthrough`

Called when the user dismisses the offer or no offers are available. Use this to resume the user's original action.

```swift theme={null}
Encore.shared.onPassthrough { placementId in
    // Resume your original user flow
}
```

***

## Alternative: Automatic StoreKit Purchase

If you don't set `onPurchaseRequest`, Encore purchases via native StoreKit 2 automatically. RevenueCat can auto-detect these transactions when configured in observer mode.

### Setup

1. Configure RevenueCat to observe external purchases:

```swift theme={null}
Purchases.configure(
    with: .builder(withAPIKey: "YOUR_RC_KEY")
        .with(purchasesAreCompletedBy: .myApp, storeKitVersion: .storeKit2)
        .build()
)
```

<Note>
  No `onPurchaseComplete` handler is needed — RevenueCat auto-detects StoreKit transactions in observer mode.
</Note>

***

## Configure Analytics

### Forward subscription events from RevenueCat to Encore

Configure RevenueCat to forward subscription events to Encore. In your RevenueCat dashboard:

1. Go to **Project Settings -> Integrations -> Webhooks**
2. Create a new webhook with URL `https://api.encorekit.com/encore/webhooks/revenuecat/<your-token>` (your token is provisioned by Encore — see the note below)
3. Save

RevenueCat will now POST subscription lifecycle events (renewals, cancellations, refunds) to Encore. This powers offer impact measurement.

<Note>
  Your RevenueCat webhook token (an `rcw_…` value) is issued by Encore and surfaced in your dashboard. Unlike your SDK API keys — which you retrieve yourself — this third-party webhook token is provisioned during onboarding, so share your RevenueCat project details with Encore to receive it.
</Note>

<Tip>
  **Custom server infrastructure?** If you already operate your own ASSN proxy that fans out to multiple destinations, you can forward to Encore from there instead. This is an obsolete fallback — the webhook approach above is preferred for all new integrations.
</Tip>
