Skip to content
Nuxie
Esc
navigateopen⌘Jpreview
On this page

Purchases

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

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:

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:

Event When tracked
$purchase_completed A StoreKit purchase completed successfully.
$purchase_failed A purchase attempt failed.
$purchase_synced A verified transaction was synced to the server.
$restore_completed A restore operation completed successfully.
$restore_failed A restore operation failed.
$restore_no_purchases A 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

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

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:

try await NuxieSDK.shared.refreshProfile()

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

Next steps

Last updated on July 23, 2026

Was this page helpful?