SDK Overview

One consistent purchase API for iOS, macOS, Android, the web, Chrome extensions and direct Mac apps, with other platforms on the roadmap.

CashSDK wraps the platform store (StoreKit 2 on Apple, Play Billing on Android) behind a single, consistent API. Every SDK does the same three things: run a purchase, read entitlements, and keep a customer in sync across devices with identify. Transactions are verified server-side, so your client never has to trust the store on its own.

Pick your platform#

Platforms at a glance#

PlatformPackageNative layerStatus
iOSgithub.com/cashsdk/cashsdk-ios (SPM)StoreKit 2Available
macOS / Catalystgithub.com/cashsdk/cashsdk-ios (SPM)StoreKit 2Available
Androidcom.cashsdk:cashsdk-android (Gradle; 1.4.0 from GitHub until Maven Central carries it)Play Billing v9Available
React Nativecashsdk-react-nativeStoreKit 2 + Play BillingRoadmap
FluttercashsdkStoreKit 2 + Play BillingRoadmap
Unitycom.cashsdk.unity (UPM)StoreKit 2 + Play BillingRoadmap
Cordovacashsdk-cordovaStoreKit 2 + Play BillingRoadmap
Capacitorcashsdk-capacitorStoreKit 2 + Play BillingRoadmap
Webcashsdk-web, cashsdk-react, cashsdk-node (npm)Stripe and other web billing providersAvailable
macOS with StripeCashSDKCommerce product of cashsdk-ios (SPM, 2.6.0 or later)URLSession and the system browserAvailable
Chrome extensioncashsdk-web/extension (npm)Manifest V3Available
Stripe onlyServer REST API, optional cashsdk-nodeYour Stripe accountAvailable

See Choose your platform for dashboard and MCP setup, and Go live with Stripe before you sell on the web, in an extension or in a direct Mac app.

The shared API#

The same calls power every integration. Configure once with your publishable key, then work with purchases and entitlements.

swift
import CashSDK

CashSDK.configure(publishableKey: "csk_pk_…")
CashSDK.shared.identify(userId: "8841", userToken: tokenFromYourBackend)

switch try await CashSDK.shared.purchase("pro_monthly") {
case .success(let entitlements):
  if entitlements.isActive("pro") { unlockPro() }
case .pending, .userCancelled:
  break
}

try await CashSDK.shared.restore()
kotlin
import com.cashsdk.CashSDK

CashSDK.configure(context = this, publishableKey = "csk_pk_…")
CashSDK.shared.identify(userId = "8841", userToken = tokenFromYourBackend)

val entitlements = CashSDK.shared.purchase(activity, "pro_monthly")
if (entitlements.isActive("pro")) unlockPro()

CashSDK.shared.restore()
ts
import { createCashSDK } from "cashsdk-web";

// The customer comes from a session your backend issues after its own sign-in.
const cashsdk = createCashSDK({ publishableKey: "csk_pk_…", environment: "production", getSessionToken });

await cashsdk.initialize();
const { entitlements } = await cashsdk.getEntitlements();
if (entitlements.some((e) => e.identifier === "pro" && e.active)) unlockPro();

On the web, purchases come from your payment provider rather than an app store. See Getting paid on the web.

The building blocks#

  • Configure: call once on launch with your csk_pk_… publishable key. Secret keys (csk_sk_…) are backend-only and must never ship in a client app.
  • Purchase: takes a product identifier, runs the native store flow, and verifies the transaction server-side before returning the customer's updated entitlements.
  • Paywalls: register(placement:) resolves and presents the paywall your team configured in the dashboard, so pricing and copy change without a release.
  • Entitlements: the access a customer has right now (pro, premium). Check isActive to gate features.
  • Identify: link the SDK to your own app_user_id so entitlements follow a customer across devices and platforms.

Billing backends#

Store purchases are only half the picture. CashSDK also reconciles revenue from web and merchant-of-record billing providers (Stripe, Paddle, Lemon Squeezy, and more) into the same entitlement and analytics model. See Billing overview to connect one.

Next steps#