iOS SDK

Add in-app purchases and paywalls to your iOS app with Swift and StoreKit 2.

The CashSDK iOS SDK wraps StoreKit 2 in a small, async/await-first API. Fetch offerings, run purchases, and read entitlements without touching SKProduct, transactions, or receipt plumbing directly.

Install#

Swift Package Manager

In Xcode, choose File → Add Packages… and enter the repository URL:

text
https://github.com/cashsdk/cashsdk-ios

Or add it to your Package.swift:

swift
dependencies: [
  .package(url: "https://github.com/cashsdk/cashsdk-ios", from: "1.0.0")
]
CocoaPods

Add the pod to your Podfile and run pod install:

ruby
pod 'CashSDK'

Configure#

Initialize CashSDK once, as early as possible — typically in your App init or AppDelegate. Use your publishable key.

swift
import CashSDK

@main
struct MyApp: App {
  init() {
    CashSDK.configure(apiKey: "pk_live_...")
  }

  var body: some Scene {
    WindowGroup { RootView() }
  }
}

Only ship publishable keys (pk_live_… / pk_test_…) in your app. Secret keys (csk_sk_…) belong on your backend.

Fetch offerings#

An offering is the set of packages you show on a paywall. Fetch the current offering and read its packages, such as monthly and annual.

swift
let offering = try await CashSDK.offerings()

let monthly = offering.monthly
let annual  = offering.annual

Purchase#

Pass a package to purchase. CashSDK drives the StoreKit 2 flow, validates the receipt, and returns the customer's updated entitlements.

swift
let result = try await CashSDK.purchase(offering.monthly)

if result.entitlements["pro"]?.isActive == true {
  unlockPro()
}

Check entitlements#

Read entitlements from any purchase or restore result to gate access.

swift
if result.entitlements["pro"]?.isActive == true {
  // Show premium content
} else {
  // Show the paywall
}

Restore purchases#

Give customers a way to recover access on a new device or after a reinstall.

swift
let result = try await CashSDK.restorePurchases()

if result.entitlements["pro"]?.isActive == true {
  unlockPro()
}

Identify the customer#

Link the SDK to your own user ID so entitlements follow the customer across devices and platforms. Call identify after the user signs in.

swift
CashSDK.identify("u_812")

SwiftUI paywall#

A minimal paywall driven by offerings. Present it whenever the pro entitlement is inactive.

swift
import SwiftUI
import CashSDK

struct PaywallView: View {
  @State private var offering: Offering?
  @State private var isPurchasing = false

  var body: some View {
    VStack(spacing: 16) {
      Text("Unlock Pro").font(.title).bold()

      if let offering {
        ForEach(offering.packages) { package in
          Button {
            Task { await buy(package) }
          } label: {
            HStack {
              Text(package.title)
              Spacer()
              Text(package.localizedPrice)
            }
          }
          .disabled(isPurchasing)
        }
      } else {
        ProgressView()
      }

      Button("Restore purchases") {
        Task { try? await CashSDK.restorePurchases() }
      }
      .font(.footnote)
    }
    .padding()
    .task { offering = try? await CashSDK.offerings() }
  }

  func buy(_ package: Package) async {
    isPurchasing = true
    defer { isPurchasing = false }
    guard let result = try? await CashSDK.purchase(package) else { return }
    if result.entitlements["pro"]?.isActive == true {
      // Dismiss and unlock
    }
  }
}

Next steps#