Swift (iOS & macOS)
orca-apple is a thin Swift wrapper around StoreKit 2 that talks to your Orca dashboard. It works on iOS, macOS, tvOS, watchOS, and visionOS (iOS 15+ / macOS 12+). You don’t touch StoreKit directly — you call Orca, and it handles fetching products, starting the purchase sheet, and checking what the customer already owns.
Install it
Section titled “Install it”Add the package in Xcode (File > Add Package Dependencies) or drop this in your Package.swift:
.package(url: "https://github.com/maxint-app/orca-apple.git", branch: "main")The flow, end to end
Section titled “The flow, end to end”Here’s the shape of a real app: you configure Orca once at launch, identify the user once you know who they are, show them what they can buy, let them buy it, and then check what they own whenever you need to gate a feature.
1. Configure it at app launch
Section titled “1. Configure it at app launch”Do this once, early — your App init or AppDelegate is the usual spot. This wires up the network client and starts listening for StoreKit transaction updates in the background.
import Orca
Orca.configure(configuration: OrcaConfiguration( publicKey: "your_public_key", environment: .sandbox // switch to .production for release builds))Everything else in this guide throws OrcaError.notConfigured if you skip this step.
2. Identify the customer
Section titled “2. Identify the customer”As soon as you know who’s using the app (after login, or immediately if you don’t have accounts), tell Orca who they are. This is the email Orca uses to look up entitlements and record purchases against — it doesn’t need to match an Apple ID.
try await Orca.identify(customerEmail: user.email)You can call this again later if the user switches accounts; it just replaces the stored identity.
3. Show the paywall
Section titled “3. Show the paywall”Pull the list of products the customer can buy. Orca fetches your entitlements, matches them against the corresponding App Store products, and hands you back ready-to-display pricing.
let products = try await Orca.queryProducts()
for product in products { print("\(product.name) — \(product.formattedPrice)")}products is [StoreProduct], a Swift enum with three shapes depending on what you’re selling:
switch product {case .subscription(let data): // data.subscriptionPeriodDays tells you if it's monthly/yearly breakcase .consumable(let data): // things like credits or coins, can be bought repeatedly breakcase .nonConsumable(let data): // one-time unlocks, like "remove ads" break}Every variant carries id, name, price, formattedPrice, currencyCode, and the underlying entitlement it unlocks — that’s what you’ll pass to purchase.
4. Let them buy it
Section titled “4. Let them buy it”Pick the product the user tapped and pass its entitlement to purchase. This triggers the native App Store purchase sheet.
if let selected = products.first(where: { $0.id == "pro_monthly" }) { try await Orca.purchase(entitlement: selected.entitlement)}If it’s a non-consumable the customer already owns, purchase throws OrcaError.alreadyOwned instead of letting them buy it twice — you don’t need to check that yourself.
5. Gate features behind what they own
Section titled “5. Gate features behind what they own”Anywhere in your app where you need to check access — unlocking a screen, showing a “Pro” badge, deciding whether to show ads — ask Orca what’s currently active for the identified customer.
let active = try await Orca.activeEntitlements()
let isPro = active.contains { $0.entitlement_id == "pro_tier" }If you’d rather work with product info (price, name) instead of raw entitlement IDs, activeProduct() gives you the same active set already mapped to StoreProduct:
let activeProducts = try await Orca.activeProduct()Both of these are cheap to call often — Orca caches the result and only refetches after a purchase or when you call listEntitlements() fresh.
6. Sign out
Section titled “6. Sign out”When the user logs out of your app, clear Orca’s state too so the next person who opens the app doesn’t see the previous customer’s entitlements:
Orca.logout()A complete mini example
Section titled “A complete mini example”Putting it together — a simple paywall screen that lists products and buys the selected one:
struct PaywallView: View { @State private var products: [StoreProduct] = []
var body: some View { List(products, id: \.entitlement.id) { product in Button("\(product.name) — \(product.formattedPrice)") { Task { try? await Orca.purchase(entitlement: product.entitlement) } } } .task { products = (try? await Orca.queryProducts()) ?? [] } }}What’s in listEntitlements()
Section titled “What’s in listEntitlements()”queryProducts() and activeProduct() both call this under the hood, but you can use it directly if you just want the raw catalog Orca has configured for your app — useful for building your own pricing table, or comparing plans before an upgrade:
let entitlements = try await Orca.listEntitlements()Errors you’ll actually see
Section titled “Errors you’ll actually see”Orca throws a plain OrcaError you can pattern-match on:
.notConfigured— you called something beforeOrca.configure.customerNotIdentified— you checked entitlements before callingidentify.productNotFound— the entitlement’s App Store product ID doesn’t exist (usually a dashboard config issue).alreadyOwned— customer tried to buy a non-consumable they already have.apiError— something went wrong talking to Orca’s backend
Server-side work
Section titled “Server-side work”orca-apple only does client-side purchasing — it can’t cancel subscriptions, list all your customers, or verify webhooks. For that, use a backend SDK from your own server:
- TypeScript server SDK if your backend is Node
- Go server SDK if your backend is Go