iOS SDK

Purchases

Process in-app purchases with StoreKit 2 and sync to Nuxie

Purchases

Integrate StoreKit 2 purchases with Nuxie. The SDK syncs verified transactions to the server, which updates entitlements and feature access automatically. Purchases can be initiated from your native code or from within flows via the runtime bridge.

Setting up a purchase delegate

The SDK uses a delegate pattern for purchases. Implement NuxiePurchaseDelegate and assign it during configuration:

swift
class MyPurchaseDelegate: NuxiePurchaseDelegate {
    func purchase(_ product: StoreProductProtocol) async -> PurchaseResult {
        // Initiate the StoreKit purchase
        do {
            let result = try await product.purchase()
            return .success
        } catch {
            return .failed(error)
        }
    }
 
    func purchaseOutcome(_ product: StoreProductProtocol) async -> PurchaseOutcome {
        // Optional: return verified transaction data for faster sync
        // Falls back to purchase() if not implemented
        return .notHandled
    }
 
    func restore() async -> RestoreResult {
        // Restore previous purchases
        do {
            try await AppStore.sync()
            return .success
        } catch {
            return .failed(error)
        }
    }
}
 
let config = NuxieConfiguration(apiKey: "your_api_key")
config.purchaseDelegate = MyPurchaseDelegate()
try NuxieSDK.shared.setup(with: config)

Warning: If your flows contain purchase or restore actions and no purchaseDelegate is configured, those actions will fail at runtime.

How purchase sync works

When a user completes a purchase, the SDK syncs the transaction with Nuxie:

  1. StoreKit 2 verifies the transaction and provides a signed JWT.
  2. The SDK sends the JWT to the server.
  3. The server validates the transaction and updates the user's entitlements.
  4. The response includes updated feature access, which the SDK applies immediately to FeatureInfo.
  5. A $purchase_synced event is tracked.

This means your UI can reflect the new entitlements as soon as the sync completes -- no need to wait for a profile refresh.

Transaction observer

On setup, the SDK starts a StoreKit 2 transaction observer that listens for:

  • Unfinished transactions from prior sessions (e.g., purchases made while the app was offline).
  • Transaction updates (new purchases, subscription renewals, revocations).

For each verified transaction, the observer:

  1. Extracts the signed JWT.
  2. Syncs it to the server.
  3. Updates FeatureInfo with the new feature access.
  4. Tracks a $purchase_synced event.
  5. Finishes the StoreKit transaction.

The observer deduplicates transactions by their original transaction ID, so the same transaction is not synced twice.

Purchases from flows

When a flow contains a purchase button, the runtime bridge handles the interaction:

  1. The user taps a purchase button in the flow.
  2. The bridge sends a purchase request to the native SDK with the StoreKit product ID.
  3. The SDK resolves the product details from StoreKit.
  4. Your purchaseDelegate initiates the purchase.
  5. The SDK sends status messages back to the flow (success, cancelled, error).
  6. On success, the transaction is synced and features are updated.

The flow UI updates automatically based on these status messages, showing loading states and confirmation.

Restore from flows

Restore actions work the same way:

  1. The user taps a restore button in the flow.
  2. The bridge sends a restore request to the native SDK.
  3. Your purchaseDelegate.restore() is called.
  4. The result is sent back to the flow (success, error, no purchases found).

Purchase events

The SDK tracks these events during the purchase lifecycle:

EventWhen tracked
$purchase_completedA StoreKit purchase completed successfully.
$purchase_failedA purchase attempt failed.
$purchase_syncedA verified transaction was synced to the server.
$restore_completedA restore operation completed successfully.
$restore_failedA restore operation failed.
$restore_no_purchasesA restore found no previous purchases.

Provider bridges

If you use RevenueCat or Superwall for purchase management, the SDK includes optional bridge libraries that implement NuxiePurchaseDelegate for you.

RevenueCat

swift
import NuxieRevenueCat
 
let config = NuxieConfiguration(apiKey: "your_api_key")
config.purchaseDelegate = NuxieRevenueCatPurchaseDelegate()
try NuxieSDK.shared.setup(with: config)

The RevenueCat bridge routes purchases through Purchases.purchase(product:) and restores through Purchases.restorePurchases().

Superwall

swift
import NuxieSuperwall
 
let config = NuxieConfiguration(apiKey: "your_api_key")
config.purchaseDelegate = NuxieSuperwallPurchaseDelegate()
try NuxieSDK.shared.setup(with: config)

The Superwall bridge routes purchases through Superwall.purchase(...) and restores through Superwall.restorePurchases().

Manual entitlement sync

To sync all current entitlements (for example, after a server-side grant), refresh the profile:

swift
try await NuxieSDK.shared.refreshProfile()

This fetches the latest profile from the server, which includes updated feature access from any source.

Next steps