Skip to main content
Web entitlements enable apps that sell subscriptions via web checkout (e.g., Stripe) to unlock premium features in the native app in real-time. After calling identify(), the SDK listens for entitlement changes automatically — when a user purchases on the web, the app unlocks instantly without a restart.

How It Works

  1. User purchases a subscription on your website (via Stripe or another web payment provider).
  2. Your backend writes the entitlement to AppDNA.
  3. The SDK detects the change in real-time and updates the local cache.
  4. Your app reacts via the callback and unlocks premium features.
Web entitlements are separate from in-app purchase entitlements (StoreKit / Play Billing). They are designed for apps that also sell subscriptions through a web checkout flow.

Check Current Entitlement

After identify(), the current web entitlement is available synchronously from cache:
if let entitlement = AppDNA.webEntitlement, entitlement.isActive {
    // User has an active web subscription
    unlockPremium()
    print("Plan: \(entitlement.planName ?? "unknown"), Status: \(entitlement.status)")
    if let periodEnd = entitlement.currentPeriodEnd {
        print("Renews: \(periodEnd)")
    }
}

Listen for Changes

Register a callback to react in real-time when the entitlement status changes:
AppDNA.onWebEntitlementChanged { entitlement in
    if entitlement?.isActive == true {
        unlockPremium()
    } else {
        lockPremium()
    }
}
This fires immediately when:
  • A new web subscription is purchased
  • A subscription renews
  • A subscription expires or is canceled
  • A subscription enters a grace period

WebEntitlement

PropertyTypeDescription
isActiveBoolWhether the subscription is currently active
planNameString?Name of the subscription plan
priceIdString?Stripe price identifier
statusEntitlementStatusCurrent status enum (see below)
currentPeriodEndDate?End date of the current billing period
intervalString?Billing interval (e.g., "month", "year")
trialEndDate?Trial expiration date, if in a trial

Entitlement Statuses

StatusDescription
activeSubscription is active and paid
trialingUser is in a free trial period
past_duePayment failed, in grace period
canceledSubscription is canceled (access may continue until period ends)

Access

Web entitlements are accessed as a top-level static property on AppDNA:
let webEntitlement = AppDNA.webEntitlement

Auto-Tracked Events

EventTrigger
web_entitlement_activatedWeb subscription becomes active
web_entitlement_expiredWeb subscription expires or is canceled

Full Example

import AppDNASDK

class PremiumManager {
    func setup() {
        // Listen for web entitlement changes
        AppDNA.onWebEntitlementChanged { [weak self] entitlement in
            DispatchQueue.main.async {
                self?.updateAccessState(entitlement: entitlement)
            }
        }
    }

    func checkAccessOnLaunch() {
        // Check in-app purchase entitlements
        Task {
            let hasIAP = await AppDNA.billing.hasActiveSubscription()
            if hasIAP {
                unlockPremium()
                return
            }
        }

        // Check web entitlement
        if let web = AppDNA.webEntitlement, web.isActive {
            unlockPremium()
            return
        }

        // No active subscription from either source
        lockPremium()
    }

    private func updateAccessState(entitlement: WebEntitlement?) {
        if entitlement?.isActive == true {
            unlockPremium()
        } else {
            // Re-check IAP entitlements before locking
            Task {
                let hasIAP = await AppDNA.billing.hasActiveSubscription()
                if !hasIAP {
                    lockPremium()
                }
            }
        }
    }

    private func unlockPremium() {
        // Enable premium features
    }

    private func lockPremium() {
        // Disable premium features
    }
}
Web entitlements require Stripe (or compatible payment provider) integration configured in the Console under Settings > Billing > Web Payments. The real-time listener activates automatically after identify() is called.