> ## 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 Multiple Managers

> Combine Encore entitlements with Superwall, RevenueCat, or your own IAP manager

## Overview

Many apps use a paywall/subscription SDK (e.g., Superwall or RevenueCat) alongside Encore retention offers. This guide shows how to combine multiple sources into a single entitlement model for your app.

<Tip>
  Core APIs used here: [isActivePublisher](/publishers/ios/sdk-reference/is-active-publisher), [isActive](/publishers/ios/sdk-reference/is-active), and [EntitlementScope](/publishers/ios/sdk-reference/entitlement-scope).
</Tip>

***

## Purchase Routing

When using multiple subscription managers, you can route purchases inside your `onPurchaseRequest` handler based on product ID or configuration:

```swift theme={null}
Encore.shared.onPurchaseRequest { purchaseRequest in
    if purchaseRequest.productId.hasPrefix("rc_") {
        // Route to RevenueCat
        let products = try await Purchases.shared.products([purchaseRequest.productId])
        guard let product = products.first else { return }
        try await Purchases.shared.purchase(product: product)
    } else {
        // Route to StoreKit directly
        guard let product = try await Product.products(for: [purchaseRequest.productId]).first else { return }
        let result = try await product.purchase()
    }
}
```

<Tip>
  See [onPurchaseRequest()](../sdk-reference/on-purchase-request) for full handler documentation.
</Tip>

***

## Superwall + RevenueCat

A minimal Combine setup that merges Superwall subscription state, RevenueCat entitlements, and Encore grants into one boolean.

```swift theme={null}
import Foundation
import Encore
import Combine
import SuperwallKit
import RevenueCat

class EntitlementManager: NSObject, ObservableObject {
    @Published var hasProAccess: Bool = false
    
    private var cancellables = Set<AnyCancellable>()
    private let revenueCatStatusSubject = CurrentValueSubject<Bool, Never>(false)

    override init() {
        super.init()
        
        // 🔑 Set delegate so we get subscription updates
        Purchases.shared.delegate = self
        
        // Listen for RevenueCat events
        setupRevenueCatListener()

        // Combine IAP subscription status with Encore promotional rewards + Superwall
        Publishers.CombineLatest3(
            revenueCatStatusSubject.eraseToAnyPublisher(),
            Superwall.shared.$subscriptionStatus,
            Encore.shared.isActivePublisher(for: .freeTrial())
        )
        .map { revenuecatActive, superwallActive, encoreActive in
            // User has pro access if:
            // - They have any RevenueCat entitlements
            // - OR they have an active Superwall subscription
            // - OR they have an active Encore reward
            return revenuecatActive || (superwallActive != .inactive) || encoreActive
        }
        .assign(to: \.hasProAccess, on: self)
        .store(in: &cancellables)
    }
    
    private func setupRevenueCatListener() {
        // Fetch initial CustomerInfo
        Purchases.shared.getCustomerInfo { [weak self] customerInfo, error in
            guard let self = self else { return }
            if let customerInfo = customerInfo {
                self.updateRevenueCatStatus(from: customerInfo)
            } else if let error = error {
                print("Error fetching CustomerInfo: \(error)")
            }
        }
    }
    
    private func updateRevenueCatStatus(from customerInfo: CustomerInfo) {
        // Check for active entitlements
        let hasActiveEntitlement = !customerInfo.entitlements.active.isEmpty
        print("RevenueCat entitlements: \(customerInfo.entitlements.active.keys)")
        revenueCatStatusSubject.send(hasActiveEntitlement)
    }
}

// MARK: - PurchasesDelegate
extension EntitlementManager: PurchasesDelegate {
    func purchases(_ purchases: Purchases, receivedUpdated customerInfo: CustomerInfo) {
        print("RevenueCat CustomerInfo updated")
        updateRevenueCatStatus(from: customerInfo)
    }
}
```

<Tip>
  Related docs: [isActivePublisher](/publishers/ios/sdk-reference/is-active-publisher), [EntitlementScope](/publishers/ios/sdk-reference/entitlement-scope), [Using Superwall](/publishers/ios/guides/using-superwall), [Using RevenueCat](/publishers/ios/guides/using-revenuecat).
</Tip>
