iOS 27 lets developers sell auto-renewable subscriptions as multi-seat purchases directly inside their app (group purchases) or via Apple Business/School Manager (volume purchasing). Purchasers can share an invite link with members, who are automatically assigned seats managed by Apple's built-in seat management system.
• Unlocks B2B and team-oriented revenue models without building custom subscription infrastructure — Apple handles seat assignment, invite links, and lifecycle management
• Volume pricing support (up to 5 price bands) lets you offer bulk discounts to incentivize larger group purchases and consolidate enterprise deals
• Volume purchasing via Apple Business and Apple School Manager opens a completely new distribution channel, making apps deployable at organizational scale through existing MDM workflows
Shows how to initiate a multi-seat group purchase using StoreKit 2, passing a seat count so Apple handles invite link generation and seat assignment automatically.
import SwiftUI
import StoreKit
struct TeamSubscriptionView: View {
let product: Product
@State private var seatCount: Int = 5
@State private var purchaseError: String?
@State private var purchaseResult: Product.PurchaseResult?
@State private var isPurchasing = false
var body: some View {
VStack(spacing: 24) {
Text("Subscribe Your Team")
.font(.title2.bold())
Stepper("Seats: \(seatCount)", value: $seatCount, in: 2...100)
.padding(.horizontal)
if let priceString = formattedPrice {
Text("Total: \(priceString) / month")
.foregroundStyle(.secondary)
}
Button {
Task { await purchaseForGroup() }
} label: {
Group {
if isPurchasing {
ProgressView()
} else {
Text("Buy \(seatCount) Seats")
}
}
.frame(maxWidth: .infinity)
.padding()
.background(.blue)
.foregroundStyle(.white)
.clipShape(RoundedRectangle(cornerRadius: 12))
}
.disabled(isPurchasing)
.padding(.horizontal)
if let error = purchaseError {
Text(error).foregroundStyle(.red).font(.caption)
}
}
.padding()
}
var formattedPrice: String? {
let total = product.price * Decimal(seatCount)
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = product.priceFormatStyle.locale
return formatter.string(from: total as NSDecimalNumber)
}
func purchaseForGroup() async {
isPurchasing = true
purchaseError = nil
defer { isPurchasing = false }
do {
// Pass quantity for the group purchase; Apple generates the invite link
let result = try await product.purchase(
options: [.quantity(seatCount)]
)
purchaseResult = result
switch result {
case .success(let verification):
let transaction = try verification.payloadValue
// Apple's included seat management takes over:
// invite link is generated and surfaced to the purchaser.
await transaction.finish()
case .pending:
break
case .userCancelled:
break
@unknown default:
break
}
} catch {
purchaseError = error.localizedDescription
}
}
}
// MARK: - Preview
#Preview {
// Wrap in a StoreKit configuration for Xcode previews
Text("Load a StoreKit product to preview TeamSubscriptionView")
}• Only works with auto-renewable subscriptions using StoreKit 2 — legacy StoreKit 1 subscriptions are not supported • Family Sharing subscriptions are opted-out of group/org selling by default; you must explicitly opt in via App Store Connect • Custom invitation flows require integration with new App Store Server API endpoints; the default included seat management is zero-code but offers less control • Volume pricing bands (up to 5) must be configured in App Store Connect, not in code
Requires StoreKit 2; subscriptions with Family Sharing enabled are opted-out by default and require explicit opt-in; volume purchasing availability is managed per-subscription in App Store Connect
More iOS 27 APIs land every week.
Get notified when new capabilities are published — no noise, just signal.