Built on StoreKit 2. Native macOS requires macOS 12+; Mac Catalyst follows its iOS deployment target (iOS 15+). Purchases are validated server-side, so entitlements stay trustworthy across every Apple platform a customer uses.
macOS / Catalyst
Ship in-app purchases and subscriptions in native macOS and Mac Catalyst apps with Swift and StoreKit 2.
The CashSDK iOS SDK is a universal Apple package. The same import CashSDK and
the same async/await API power native macOS (AppKit / SwiftUI) apps and
Mac Catalyst builds of your iPad app. Fetch offerings, run purchases, and
read entitlements without touching StoreKit transactions or receipt plumbing
directly.
Install#
The macOS SDK is the same Swift package as iOS. In Xcode, choose File → Add Packages… and enter the repository URL:
https://github.com/cashsdk/cashsdk-ios
Or add it to your Package.swift:
dependencies: [
.package(url: "https://github.com/cashsdk/cashsdk-ios", from: "1.1.1")
]
Enable the capability. In your macOS target's Signing & Capabilities, add the In-App Purchase capability. For Mac Catalyst, it is inherited from your iOS target.
Configure#
Initialize CashSDK once, as early as possible, in your SwiftUI App init or
AppDelegate.applicationDidFinishLaunching. Use your publishable key.
import SwiftUI
import CashSDK
@main
struct MyApp: App {
init() {
CashSDK.configure(publishableKey: "csk_pk_…")
}
var body: some Scene {
WindowGroup { RootView() }
}
}
Only ship publishable keys (csk_pk_…) in your app. Secret keys
(csk_sk_…) belong on your backend.
Purchase#
Pass a product identifier to purchase. CashSDK drives the StoreKit 2 flow,
verifies the transaction server-side, and returns the customer's updated
entitlements.
switch try await CashSDK.shared.purchase("app.example.pro.yearly") {
case .success(let entitlements):
if entitlements.isActive("pro") { unlockPro() }
case .pending: showPendingNotice()
case .userCancelled: break
}
Reading prices for your own UI comes straight from StoreKit:
let products = try await Product.products(for: ["app.example.pro.monthly",
"app.example.pro.yearly"])
Check entitlements#
entitlements is a synchronous, offline-valid snapshot, so reading it never
awaits the network.
if CashSDK.shared.entitlements.isActive("pro") {
// Show premium content
} else {
// Show the paywall
}
Restore purchases#
macOS customers frequently move between Macs, so always offer a visible Restore purchases control. It recovers access on a new machine or after a reinstall.
try await CashSDK.shared.restore()
if CashSDK.shared.entitlements.isActive("pro") {
unlockPro()
}
Identify the customer#
Link the SDK to your own user ID so entitlements follow the customer across Macs,
iPhones, and iPads. Call identify after the user signs in.
CashSDK.shared.identify(userId: "8841", userToken: tokenFromYourBackend)
Unify with iOS and iPad#
Because entitlements are keyed to the customer, a subscription a customer buys on
their iPhone is active the moment they sign in on your Mac app with the same
app_user_id, and vice versa. Call identify with the same ID everywhere, and
StoreKit's own Family Sharing and cross-device receipts are reconciled for you.
Shipping the same app as a native Mac build and a Mac Catalyst build? Both use this identical API, so you only write the purchase flow once. See the iOS SDK for the iPhone and iPad targets.