Multiseat Subscriptions: What to Build Before Winter

This post has not been translated yet, so you are reading the English original. Read it at the English URL

On September 28, 2026, Apple extended the meaning of one field your server already decodes. The App Store Server API changelog for version 1.22 says: “The quantity field also reports the number of seats for a subscription that a customer buys as a multiseat purchase.”1 A seat on the App Store is a quantity on a transaction, and the rest of the design follows from that sentence.

Apple announced multiseat purchases at WWDC26 on June 8 as two StoreKit 2 configuration options, Volume Purchasing for organizations and Group Purchases for anyone else.2 On September 16 the developer news post set the dates: “Volume Purchasing launches on October 22, 2026, and Group Purchases will launch this winter.”3 The same post turned the feature on for you: “Starting today, multiseat purchases are enabled by default for subscriptions in App Store Connect.”3

I run a subscription app, Reps, where the obvious group buyer is a trainer paying for a roster of clients.4 Apple’s materials never mention trainers. They mention “small businesses, individual departments, or teams,” and a gym is a small business.3 The path for that purchase is Group Purchases, and the documentation Apple has published so far says what your code sees when it lands. The post walks through all of it, from the StoreKit reference to the sandbox-only server endpoints, and names the gaps Apple has not filled.

TL;DR

  • Two purchase paths, one shape. Volume Purchasing (October 22) sells through Apple Business Manager and Apple School Manager with seats assigned by a device management provider. Group Purchases (winter) sells inside your app, where the buyer shares an Apple-generated invitation link and “When they accept, they’ll automatically get a seat assigned.”35 Either way, “the App Store assigns a transaction for each member, and you can give them access.”5
  • A seat holder’s transaction carries inAppOwnershipType of ASSIGNED, “a customer who has access through an organization or group,” and StoreKit exposes the same state on the device as Transaction.OwnershipType.assigned.67 Apple says each member gets a transaction, and Transaction.currentEntitlements emits the latest transaction for each subscribed product, so my reading is that an entitlement loop over that sequence which ignores ownership already grants the seat.523
  • Removal is a revocation. Apple added ASSIGNMENT_REVOKE to revocationType with one instruction: “Revoke the customer’s access to the content the transaction provides.”8 On the device the revoked transaction leaves currentEntitlements and arrives through Transaction.updates, so any cached entitlement has to be cleared there, a gap Reps has today.2324
  • Apple shipped two group endpoints, Get Customer Groups and Get Group Members, and marked both “only available in the sandbox environment.”910 Membership is informational: “To unlock content for a customer, read their transactions; don’t depend on group membership.”9
  • Four server endpoints now reject seat holders outright. Send Consumption Information, its V1 variant, and Set App Account Token return error 4000227, and Extend a Subscription Renewal Date returns 4030028.1112 Check for ASSIGNED before you call them.
  • The seat count has no documented home in the StoreKit purchase request yet. Product.PurchaseOption.quantity(_:) still reads “The quantity applies to consumable Apple In-App Purchases and non-renewing subscriptions,” with a maximum of 10.13 Apple’s session says you “pass that into the StoreKit 2 purchase request” without naming the API.5

Two paths to a seat

Apple splits multiseat into a channel for organizations that already procure software and a channel for everyone else. The WWDC session draws the line by scale: group purchases are “perfect for small teams or social groups to collaborate on apps,” and volume purchasing is “a perfect solution for organizations with larger scale and requirements for management and identity.”5

Two paths to a seat. Group Purchases, which Apple says launches this winter: a subscriber in your app starts a StoreKit 2 purchase for N seats, Apple generates an invitation link, members accept, and each member receives a transaction with inAppOwnershipType ASSIGNED; Get Customer Groups reports the group as groupType CONSUMER with no roles. Volume Purchasing, launching October 22, 2026: an organization buys in Apple Business Manager or Apple School Manager, a device management provider assigns seats, and each member receives a transaction with inAppOwnershipType ASSIGNED; Get Customer Groups reports groupType ORGANIZATION with a role of ADMIN or NONE. Both paths end at Transaction.currentEntitlements in your app.

Volume Purchasing adds no checkout or assignment UI for you to build. “With volume purchasing, Apple Business and Apple School Manager, display your subscriptions and handle the purchase process. All you need to do is make sure your subscription is available to organizations.”5 The organization assigns seats “the same way they assign apps today, through a device management service,” and the seats are “owned and managed by the organization.”5 It launches October 22.3

Group Purchases is the path a trainer takes, and it runs through your own paywall. “For group purchases, you make your own in-app UI to trigger the StoreKit 2 purchase flow.”5 After that, the default is Apple’s included seat management: “With group purchases, an invitation link will be generated for the initial purchaser to share with members.”5 The session’s opening describes the member’s side of the same link: “When they accept, they’ll automatically get a seat assigned.”5 Apple’s newsroom adds the detail that makes the data model work: “Because each subscriber joins from their own account, it’s easy to see and manage who’s in their group.”2 Each member is a distinct Apple Account with a distinct transaction, so nothing about your entitlement logic has to know that a group exists.

The included system is a default, not the only option. The session says the built-in flow covers “generating the invitation link, tracking member acceptance and assignment and Seat life-cycle management for your application, like cancellations,” and then: “if you already implement an invitation and member management system for your app, you can leverage it. Integrating custom invitation flows, will be powered via new App Store Server API endpoints.”5 Apple has published no such endpoint as of October 9; the two group endpoints documented so far read membership rather than create it.1

The one hard requirement is the API generation. “StoreKit 2 is required to offer subscriptions to groups and organizations.”5 An app still on the original StoreKit gets neither path, and App Store Connect already treats those subscriptions differently, which the defaults section covers below.

Dates, in order, with the source for each:

Date Event Source
June 8, 2026 Announced at WWDC26 as two StoreKit 2 configuration options Apple Newsroom2
September 14, 2026 Cutoff for App Store Connect’s opt-out defaults App Store Connect Help14
September 16, 2026 Enabled by default; launch dates published Apple Developer News3
September 28, 2026 App Store Server API 1.22 ships the seat fields and group endpoints API changelog1
October 22, 2026 Volume Purchasing launches, per Apple’s announced schedule Apple Developer News3
“This winter” Group Purchases launches; Apple’s words on September 16, with no date published Apple Developer News3

A seat is a quantity on a transaction

Start from the signed payload, because the server reference is where Apple documented the most. JWSTransactionDecodedPayload has carried a quantity field since the API’s first version, and as of 1.22 its description reads “The number of products or seats the customer purchased.”15 The purchaser’s transaction reports how many seats they bought. The seat holders’ transactions report the ownership that got them in.

That ownership is a new value on an old field. inAppOwnershipType describes “whether the transaction was purchased by the customer, or is available to them through Family Sharing, an organization, or a group,” and its three values are now PURCHASED, FAMILY_SHARED, and ASSIGNED, the last defined as “The transaction belongs to a customer who has access through an organization or group.”6 Apple’s notifications changelog carries the same addition with a scope note: “These values are only available in the sandbox environment.”16

On the device, StoreKit mirrors the value. Transaction.OwnershipType now has three static members: purchased, familyShared, and assigned, the last documented as “The user has access to this transaction through an organization.”7 The Swift abstract says organization where the server abstract says organization or group. I read them as the same value described by two writers, since the server changelog added exactly one ownership value for both purchase paths, but the StoreKit page does not say so itself.17

What the StoreKit reference does not have is a way to send the seat count. The session’s instruction is unambiguous: “After merchandising, you’ll need to get the number of seats requested from your customer and pass that into the StoreKit 2 purchase request.”5 The only quantity-shaped purchase option in the reference today is Product.PurchaseOption.quantity(_:), and its discussion still says “The quantity applies to consumable Apple In-App Purchases and non-renewing subscriptions,” with a parameter note that “The maximum value is 10.”13 Neither sentence covers an auto-renewable subscription, and a ten-seat cap would rule out a gym. The StoreKit framework landing page lists no multiseat topic at all.17 As of October 9, no member of Product.PurchaseOption is documented for seats, so the option is either a revised quantity(_:) or something unpublished, and code written today should not guess.

Here is the purchase Reps makes today, from Reps/Reps/Services/RepsProStore.swift, which is the call that grows a seat count once Apple names the option:4

func purchaseDetailed(
    _ plan: RepsProPlan,
    source: String = "standard"
) async -> RepsProPurchaseOutcome {
    guard let product = products.first(where: { $0.id == plan.id }) else { return .failed }
    purchaseInFlight = plan.id
    defer { purchaseInFlight = nil }
    do {
        let result = try await product.purchase()
        switch result {
        case .success(let verification):
            if case .verified(let transaction) = verification {
                await transaction.finish()
                rememberVerifiedExpiration(transaction.expirationDate)
                Self.rememberVerifiedJWS(verification.jwsRepresentation)
                await refreshEntitlement(verified: transaction)
                return .success
            }
            return .failed
        case .userCancelled:
            return .cancelled
        case .pending:
            return .pending
        @unknown default:
            return .failed
        }
    } catch {
        return .failed
    }
}

The call site is one line, product.purchase(), and every StoreKit 2 purchase call, purchase(options:) and purchase(confirmIn:options:) alike, takes a Set<Product.PurchaseOption>, so my reading of “pass that into the StoreKit 2 purchase request” is one more member of that set.7 The purchase-result handling around it, the pending case for Ask to Buy and the JWS kept for the server, stays as it is; the ride-through’s invalidation does not, for the reason the removal section covers. The work before winter is the screen in front of the call, where a trainer picks a number, and the screen after it, which may or may not get the invitation link to show.

Entitlement is the transaction; membership is the group

Apple wrote the rule into the group endpoint’s documentation and repeated it on the role page: “Group membership is separate from entitlement. To unlock content for a customer, read their transactions; don’t depend on group membership.”9 And: “This value is informational. Determine access to content based on the customer’s transactions.”18

Entitlement versus membership. Left column, the transaction decides access: read it on the device through Transaction.currentEntitlements or on the server from the signed JWS transaction payload; it carries quantity, the seat count on the purchaser's copy; inAppOwnershipType, PURCHASED, FAMILY_SHARED, or ASSIGNED; and revocationType, where ASSIGNMENT_REVOKE means the purchaser removed the seat (the image's label reads "ASSIGNMENT_REVOKE: purchaser removed the seat"). Apple: "To unlock content for a customer, read their transactions; don't depend on group membership." Right column, the group is a roster: read it from Get Customer Groups and Get Group Members, sandbox only as of October 9, 2026; it carries groupId, unique within your app; groupType ORGANIZATION or CONSUMER; and roles ADMIN or NONE, for ORGANIZATION groups only. Apple: "This value is informational. Determine access to content based on the customer's transactions."

The rule is good news for any app whose entitlement check is a loop over Transaction.currentEntitlements. Reps runs one, and here is the part that decides whether the paywall shows:4

for await entitlement in Transaction.currentEntitlements {
    if case .verified(let transaction) = entitlement,
       Self.productIDs.contains(transaction.productID) {
        guard transaction.revocationDate == nil else {
            // Refunded/revoked: the ride-through must die with it.
            UserDefaults.standard.removeObject(forKey: Self.verifiedExpiryDefaultsKey)
            continue
        }
        active = true
        current.append(transaction)
        rememberVerifiedExpiration(transaction.expirationDate)
        Self.rememberVerifiedJWS(entitlement.jwsRepresentation)
    }
}

Nothing in the loop reads ownershipType, so a client whose trainer bought the seat is active the moment their transaction appears, with no code change. Family Sharing has worked the same way since StoreKit 2 shipped, and Apple built assigned as a third value on the same type rather than a new concept.7 The SDK also back-deploys it: in the StoreKit interface that ships with Xcode 27.0, assigned carries an iOS 15.0 availability and a @backDeployed(before: iOS 27.0, ...) attribute, so an app built against the 27 SDK can match on the value while still running on iOS 26.7

Where ownership does get read is the one place I had forgotten about. Reps greets a new subscriber once, and the greeting’s predicate filters on $0.ownershipType == .purchased, so a seat holder would never see it.4 Harmless, and also exactly the kind of branch that hides in a codebase. Before winter, grep for ownershipType and inAppOwnershipType and read every hit, because each one is a place where a seat holder is about to behave differently from a subscriber, and you want to have chosen that.

A seat-aware pass looks like the Reps loop with one more field surfaced, so the interface can say who paid:

enum AccessSource: Sendable {
    case purchased, familyShared, assigned, other
}

func currentAccess(productIDs: Set<String>) async -> (active: Bool, source: AccessSource?) {
    for await result in Transaction.currentEntitlements {
        guard case .verified(let transaction) = result,
              productIDs.contains(transaction.productID),
              transaction.revocationDate == nil else { continue }

        let source: AccessSource
        switch transaction.ownershipType {
        case .purchased:    source = .purchased
        case .familyShared: source = .familyShared
        case .assigned:     source = .assigned   // seat from a group or an organization
        default:            source = .other      // a future value still unlocks
        }
        return (true, source)
    }
    return (false, nil)
}

The default arm is deliberate, and it labels the unknown honestly as .other rather than pretending it was purchased. Transaction.OwnershipType is a struct with static members, not a closed enum, and Apple added a member this cycle. A switch that fails closed on an unknown ownership value would lock out the next kind of customer Apple invents. Access comes from the transaction’s existence and its revocation state; ownership only labels it.

Removal arrives as a revocation

When a trainer drops a client, Apple uses the revocation fields you already handle; nothing new arrives. Apple added ASSIGNMENT_REVOKE to revocationType, defined as “The organization or group purchaser removed the subscription from the customer,” and its discussion gives the instruction: “A revocationType of ASSIGNMENT_REVOKE indicates that the organization or group purchaser removed the subscription from a customer. Revoke the customer’s access to the content the transaction provides.”8 The field sits beside REFUND_FULL, REFUND_PRORATED, and FAMILY_REVOKE, so a server that already revokes on any revocationDate is done.8

On the device, the removal is an absence first. Apple’s currentEntitlements page says “Products that the App Store has refunded or revoked don’t appear in the current entitlements,” so the revocationDate guard in the Reps loop above never fires for a removed seat; the loop finds nothing.23 The transaction that carries the revocationDate arrives through Transaction.updates instead, which is where Apple’s own sample checks the date and removes access.24

That split is where Reps has a gap today, and writing the post is how I found it. The updates handler declines to remember a revoked transaction’s expiry, which is right, and then calls the entitlement pass, which finds nothing in currentEntitlements and falls back to the stored expiry. A removed client, or a refunded subscriber, keeps access until the last verified expiration date.4 The minimum fix is one condition in the updates handler: when the arriving transaction has a revocationDate, clear the cached expiry before the pass runs. Any cached entitlement, a ride-through, a keychain receipt, a server-side token, needs the same rule, because the sequence your paywall reads does not show the revocation itself. Apple’s updates page shows a revocation arriving only in its sample code and says nothing about one that lands while the app is closed, so a cached expiry should also carry a short lifetime of its own rather than running to the subscription’s end; that part is my design, not Apple’s documentation.24

StoreKit does carry the assignment case on the device, on a different type than the one you might grep for first. Transaction.RevocationReason has no assignment member; its members are developerIssue, other, and upgradedToBundle, and its abstract still speaks only of refunds and Family Sharing.19 The newer Transaction.RevocationType, introduced in 26.4 together with the revocationType property, has four static members, and the fourth is assignmentRevocation, “The transaction was revoked by the organization administrator,” with a raw value of ASSIGNMENT_REVOKE.25 The SDK back-deploys that member before 27.0 the same way it does assigned.25 So the access decision branches on revocationDate, and the copy that explains the loss branches on revocationType == .assignmentRevocation. The property page’s own discussion still lists only refunds and Family Sharing as of October 9, so the type is ahead of its prose.25

What Apple has not documented is a notification for the event. The App Store Server Notifications changelog’s September 28 entry adds the two values and extends quantity to seats, and names no notification type for assignment revocation; the notificationType reference describes REVOKE only in Family Sharing terms.1620 A server that wants to learn about a removed seat promptly should plan on reading the transaction’s revocationType when a notification of any kind arrives for that subscription, and on polling where it matters, until Apple says which type fires.

The group endpoints, and what they are not for

Apple shipped two endpoints for groups in API 1.22 and fenced both with the same sentence, “This endpoint is only available in the sandbox environment.”910 The production URLs are documented anyway, so the fence reads as a launch gate rather than a design.

Get Customer Groups takes any transaction identifier that belongs to the customer and returns the groups they are in:9

GET https://api.storekit-sandbox.apple.com/groups/v1/currentGroups/{anyTransactionId}
GET https://api.storekit.apple.com/groups/v1/currentGroups/{anyTransactionId}

Each GroupEntry carries a groupId, “within the scope of your app,” and a groupType with two values. ORGANIZATION means “An organization bought seats through Volume Purchasing and assigned one to the customer.” CONSUMER means “A subscriber bought seats through Group Purchases and invited the customer to join.”21 Organization groups also carry a roles array, one RoleEntry per product, where role is ADMIN, “The customer administers the group for the product,” or NONE, “The customer has a seat in the group but doesn’t administer it.”18 Consumer groups carry no roles: “A group with a groupType of CONSUMER doesn’t report roles.”18 So the trainer who bought a dozen seats through your paywall is not an ADMIN in Apple’s data; the admin concept belongs to the Apple Business Manager path.

Get Group Members takes a groupId and pages through its members, 100 at a time at most, each identified only by appTransactionId, “The unique identifier of the member’s app download transaction.”1022

GET https://api.storekit-sandbox.apple.com/groups/v1/group/{groupId}?limit=50
GET https://api.storekit-sandbox.apple.com/groups/v1/group/{groupId}?limit=50&paginationToken={token}

You can call both today against fixed placeholders. In the sandbox, a customer who belongs to no consumer group gets back a placeholder organization group with groupId 900000000000000000, two example products with roles ADMIN and NONE, and that groupId returns one placeholder member, appTransactionId 700000000000000000, with hasMore false.910 A signed request against the sandbox host:

JWT="$(./sign-app-store-server-jwt.sh)"   # your existing App Store Server API signer
TXN="2000000123456789"                   # any transactionId, originalTransactionId, or appTransactionId for the customer

curl -s -H "Authorization: Bearer $JWT" \
  "https://api.storekit-sandbox.apple.com/groups/v1/currentGroups/$TXN" | jq .

curl -s -H "Authorization: Bearer $JWT" \
  "https://api.storekit-sandbox.apple.com/groups/v1/group/900000000000000000?limit=50" | jq .

Apple scopes the endpoints to one job: “Use this endpoint only if your app offers a group experience where a customer’s group or role changes what you present,” with two examples, “exposing extra controls to a customer with the ADMIN role, or grouping members into that administrator’s shared workspace.”9 For a trainer that job is a roster, and the roster’s keys are appTransactionId values, which your server can join against the app transactions it already receives when a client signs in or syncs. Note what the member list does not carry: no name, no email, no Apple Account identifier. The join to a human is yours to build, and the trainer’s invitation flow is where you build it.

Four endpoints now refuse assigned transactions

Apple added two error codes in 1.22 that encode a design decision: a seat holder is not a billing relationship.1

InvalidAssignedTransactionNotSupportedError, code 4000227, “Invalid request. Assigned transactions aren’t supported by this endpoint,” comes back from Send Consumption Information, Send Consumption Information V1, and Set App Account Token when you pass a transaction “that an organization or group assigns to the customer.”11

AssignedSubscriptionExtensionIneligibleError, code 4030028, “Assigned subscriptions can’t get a renewal date extension,” comes back from Extend a Subscription Renewal Date, with the reason: “An assigned subscription renews on the same schedule as the subscription the organization or group purchaser bought, so the endpoint doesn’t support extending the renewal date for an individual member.”12

Both pages give the same instruction, check for an inAppOwnershipType of ASSIGNED before you call.1112 The consumption refusal matters for refund handling. I read it as Apple treating a refund on a seat as the purchaser’s refund, with no consumption data wanted from the member; the error page gives the rule and not the reason. The app account token refusal matters more, because many servers key customers on appAccountToken. A seat holder’s transaction has no token you can set after the fact, which pushes the key to appTransactionId, the one identifier the group endpoints also use.1011 A server-side guard in Python, written against the decoded payload fields Apple documents:

ASSIGNED = "ASSIGNED"

def may_call_billing_endpoint(decoded_transaction: dict) -> bool:
    """Send Consumption Information, Set App Account Token, and Extend a
    Subscription Renewal Date reject assigned seats with 4000227 / 4030028."""
    return decoded_transaction.get("inAppOwnershipType") != ASSIGNED

def customer_key(decoded_transaction: dict) -> str:
    """One record per customer, keyed on appTransactionId, which every
    transaction carries whether or not a token could be set on it."""
    return f"apptxn:{decoded_transaction['appTransactionId']}"

def link_account_token(records: dict, decoded_transaction: dict) -> None:
    """A purchaser's appAccountToken is an alias, not a second identity:
    attach it to the appTransactionId record, so a seat assigned to the
    same customer later lands on the same record."""
    token = decoded_transaction.get("appAccountToken")
    if token:
        records.setdefault(customer_key(decoded_transaction), {})["app_account_token"] = token

The key is the same for a purchaser and for a seat holder on purpose. A customer who subscribed with a token and later accepts a seat from a trainer is one person, and a key that switches namespace on ownership would give them two records. The endpoint refusal stops you from setting a token on the seat; it does not ask you to change who the customer is. A server that already keys on appAccountToken needs a migration that links each token to its appTransactionId before the first seat arrives.

Reps verifies the subscription JWS on a proxy before it runs managed planning, and that proxy checks signature, expiry, and revocation.4 Those three checks pass a seat holder unchanged. What the proxy cannot do is set an app account token on that customer, so the per-customer record it keeps has to accept an appTransactionId key before the first trainer buys a seat.

App Store Connect flipped the default

The part of the launch that already reached you happened in App Store Connect on September 16, and the help page spells out who is in and who is out:314

Subscription Multiseat default Apple’s sentence
StoreKit 2, Family Sharing off On “Multiseat purchases are turned on by default for all auto-renewable subscriptions.”
Created before September 14, 2026, original StoreKit API Off “Subscriptions created prior to September 14, 2026 that do not use StoreKit 2 or that have Family Sharing turned on are set to opted out by default.”
Created before September 14, 2026, Family Sharing on Off Same sentence
Any subscription in a custom app On, cannot opt out “Subscriptions for custom apps will automatically be available on Apple Business, and Apple School Manager and you may not opt out of multiseat purchases.”

The Help page does not say what a subscription created after the cutoff with Family Sharing on, or without StoreKit 2, defaults to. Its undated sentence, “Subscriptions are set to opted out by default if the app doesn’t use StoreKit 2 or has Family Sharing turned on,” and the WWDC session’s “If your subscription has Family Sharing enabled, you can still sell to groups and organizations, but it is opted-out by default” both read as if the exception applies regardless of date, and the dated sentence narrows it.514 Read the toggle rather than the rule.

Both Reps products predate the cutoff, use StoreKit 2, and have Family Sharing off, so they are opted in without my having touched anything, and so is any subscription shaped like them.414 The control lives in the Purchase Options section of the subscription’s detail page, and changing it takes the Account Holder, Admin, or App Manager role.14

Three consequences of the toggle are easy to miss:

  • Channels are separable, with one lock. You can allow or deny the App Store, Apple Business Manager, and Apple School Manager independently (Apple’s pages shorten the first to “Apple Business”), but “After this subscription has been approved, you may not remove App Store availability.” Removing the two organization channels needs the Account Holder, and “Existing subscribers won’t renew automatically and will be canceled at the end of their next renewal.”14
  • Turning it off is not a kill switch. “If you disallow multiseat purchases, new customers can’t buy multiple seats and this subscription is removed from Apple Business and Apple School Manager, which support multiseat purchases only. Existing customers’ subscriptions continue to renew until the group purchaser cancels, New seats cannot be added, but can be removed by the group purchaser.”14
  • Family Sharing collapses to the buyer. “If you’ve enabled multiseat purchases for a subscription, only the group purchaser’s access will include Family Sharing,” and every other seat is “for individual use only.” Apple adds, “Once you turn on Family Sharing, you won’t be able to turn it off.”14 A seat holder’s family does not ride along.

Pricing is per seat, with optional bands

Apple’s session covers pricing in one screen. “By default, every seat of your subscription is sold at the current price in App Store Connect.”5 A trainer buying 12 seats of a $7.99 plan pays 12 times $7.99 unless you say otherwise.

Saying otherwise means volume pricing: “You can set up to 5 price bands, with full control over the quantities required for each band, and the price,” configured in App Store Connect.5 The session’s example starts a $19.99 seat at full price for seats one through 20, drops to $13.99 for seats 21 through 40, and to $10.99 from seat 41, so a 50-seat purchase lands “about 20% from the base price.”5 Checking the arithmetic: 20 seats at $19.99, 20 at $13.99, and 10 at $10.99 total $789.50, or $15.79 per seat, which is 21 percent under $19.99. The band shape is the same marginal-rate structure as a tax table, and the cheaper seats are the ones at the top of the order, not a discount on the whole purchase.

I found no App Store Connect Help page for the bands on October 9, so the session is the source for the numbers above.5

What a trainer’s purchase would look like in Reps

Genre note: Reps ships a StoreKit 2 subscription today and has not shipped Group Purchases, which has not launched. What follows is the design I am building toward, checked against Apple’s documentation rather than against a running feature.

A trainer opens the Reps Pro paywall, which today offers a monthly plan and a yearly plan with no introductory offer; the first three workouts are free instead.4 A group option sits beside them: pick a seat count, see the per-seat price from the product, and buy. The purchase call is the one above with the seat count attached once Apple names the option. On success, the trainer’s own transaction carries quantity equal to the seat count and inAppOwnershipType of PURCHASED, and Apple generates the invitation link for the trainer to share.515 Apple has not documented whether the app receives that link or only the purchaser does, so the paywall’s success state cannot promise to show it.

The trainer shares the link however they like. Each client who accepts gets a seat, in the session’s words “they’ll automatically get a seat assigned,” signs in with their own Apple Account, and the next Transaction.currentEntitlements pass on their phone yields a verified transaction for the same product with ownershipType of .assigned.57 The paywall never appears for them. The managed-AI proxy receives their JWS, sees ASSIGNED, verifies signature, expiry, and revocation exactly as it does for a subscriber, and keys the client on appTransactionId because it cannot set a token.11

When the trainer drops a client, the client’s transaction gets a revocationDate and a revocationType of ASSIGNMENT_REVOKE.8 It leaves currentEntitlements and arrives through Transaction.updates, so the handler has to clear the ride-through there, which is the gap above, and then the paywall returns with copy that says the seat ended rather than the free workouts, keyed on revocationType == .assignmentRevocation.232425

The roster screen is the part Apple’s included seat management does not build for me; it assigns seats and tracks acceptance, and leaves who-is-who to the app. The group endpoints return appTransactionId values, and the subscription JWS Reps already sends the proxy carries appTransactionId in its payload, so the trainer’s screen is a join between Apple’s member list and my own records. As of October 9 both endpoints are sandbox-only, and the roster depends on Apple making them available in production, which neither page dates.41015

What I am not building: an admin tier keyed on role, because consumer groups report no roles.18 The trainer’s own transaction is easy to spot, quantity greater than one with inAppOwnershipType of PURCHASED, but no documented field on that transaction names a groupId, and Apple says “A customer can belong to more than one group.”915 Tying a purchaser to the roster they bought is app-managed design work on top of Apple’s fields, not something the payload resolves, and the trainer’s controls wait on that link rather than on the bulk-purchase predicate.

FAQ

Does a seat holder need to do anything in my app to get access?

No, beyond being signed in to the Apple Account that accepted the invitation. Apple’s session says “When they accept, they’ll automatically get a seat assigned,” and “the App Store assigns a transaction for each member.”5 Since Transaction.currentEntitlements emits the latest transaction for each subscribed auto-renewable product, that transaction should appear there on the member’s device with ownershipType of .assigned; the two documents imply it, and neither states it in one sentence.723 If your paywall decision is a loop over that sequence, the seat holder passes it.

Can I tell who bought the seat from the seat holder’s transaction?

Not directly. The seat holder’s transaction says ASSIGNED and nothing about the purchaser.6 Get Customer Groups, called with any of the seat holder’s transaction identifiers, returns the groupId they belong to, and Get Group Members lists the customers in that group by appTransactionId.910 Apple does not document whether the purchaser appears in that list. Both endpoints are sandbox-only as of October 9, 2026.

What happens to Family Sharing on a multiseat subscription?

Only the purchaser’s seat can be family-shared. Apple’s help page: “only the group purchaser will be able to share with family members when both multiseat purchases and Family Sharing are turned on. All other seats will be for individual use only.”14 Subscriptions created before September 14 with Family Sharing on were opted out of multiseat when the default went live on September 16, so for those subscriptions, being in both is an explicit choice.314

Which App Store Server API calls break for seat holders?

Four. Send Consumption Information and Send Consumption Information V1 return 4000227, Set App Account Token returns 4000227, and Extend a Subscription Renewal Date returns 4030028.1112 Apple’s advice on both error pages is to check inAppOwnershipType for ASSIGNED before calling.

Should a gym use Volume Purchasing or Group Purchases?

Volume Purchasing only if the gym runs Apple Business Manager and a device management provider, because that is what it requires: organizations “buy your subscriptions through a single Apple In-App Purchase and assign seats using a device management provider.”3 A gym buying for members’ personal phones has no such fleet, so Group Purchases, where “each subscriber joins from their own account,” is its path.2

Key Takeaways

For iOS developers:

  • Clear every cached entitlement from the Transaction.updates handler when a transaction arrives with a revocationDate. The currentEntitlements loop never sees a revoked product, so a ride-through keyed on the last verified expiry outlives a removed seat.2324 Use revocationType == .assignmentRevocation, introduced in 26.4 and back-deployed by the 27 SDK, for the message only.25
  • Grep for ownershipType today and read each hit. Access should come from the transaction’s presence and revocationDate; ownership should only label the customer. Add .assigned to any switch, and give the switch a default that still unlocks.7
  • Leave product.purchase() alone until Apple documents the seat option. The reference still scopes quantity(_:) to consumables and non-renewing subscriptions with a cap of 10, and the session names no API.513 Build the seat picker and the invitation-link surface around the call, not into it.

For server and backend engineers:

  • Gate Send Consumption Information, Set App Account Token, and Extend a Subscription Renewal Date on inAppOwnershipType != "ASSIGNED", and key seat holders on appTransactionId.1112
  • Treat revocationType of ASSIGNMENT_REVOKE as a revocation like any other, and do not wait for a dedicated notification type, because Apple has not documented one.81620
  • Point your group-endpoint integration at the sandbox placeholders now. The 900000000000000000 group and its 700000000000000000 member exist so you can build the roster before winter.910

For whoever owns App Store Connect:

  • Open each subscription’s Purchase Options and read the current state. Everything on StoreKit 2 without Family Sharing is opted in as of September 16, including subscriptions older than the cutoff.314
  • Decide the organization channels before approval, because App Store availability cannot be removed afterward, and removing Apple Business Manager or Apple School Manager cancels those subscribers at their next renewal.14
  • Set volume price bands only if you want them. The default is every seat at list price, and five bands is the cap.5

Apple published the server side of multiseat first and left the purchase call for last, which is the right order for anyone whose entitlement logic already runs on transactions rather than on a membership table. For the other App Store change that reached every submission this cycle, see the social media declaration and what it costs, and for what reviewers are asking in October, What App Review looks for. The full series hub is the Apple Ecosystem Series.

References


  1. Apple, App Store Server API changelog, entry for version 1.22 dated September 28, 2026. Source of “Added the Get Customer Groups and Get Group Members endpoints, and the GetCustomerGroupsResponse and GetGroupMembersResponse data types, to support multiseat purchases, which let organizations and groups buy your subscriptions in bulk. These endpoints are only available in the sandbox environment,” “Added the GroupEntry, GroupMemberEntry, and RoleEntry data types, and the groupId, groupType, role, and limit fields,” “Added the ASSIGNED value to inAppOwnershipType, and the ASSIGNMENT_REVOKE value to revocationType,” “The quantity field also reports the number of seats for a subscription that a customer buys as a multiseat purchase,” and “Added the GroupNotFoundError, InvalidGroupIdError, InvalidLimitError, InvalidAssignedTransactionNotSupportedError, and AssignedSubscriptionExtensionIneligibleError error codes.” Read from Apple’s documentation JSON on October 9, 2026, since the HTML renders through JavaScript. ↩↩↩↩↩

  2. Apple, Apple expands App Store capabilities to help developers grow and reach new users, Apple Newsroom, June 8, 2026 (the page’s datePublished is 2026-06-08 and its title tag reads as linked). Source of “Powered by StoreKit 2, developers will be able to enable subscriptions for groups and organizations within their app” using “two new configuration options,” “Group purchases let a subscriber buy seats as a single purchase and then invite others to access the subscription,” “With Apple-provided invite functionality, it’s seamless for people to invite, accept, and join a subscription,” “Because each subscriber joins from their own account, it’s easy to see and manage who’s in their group,” and “Volume purchasing will be available this fall, with group purchases coming this winter.” Read on October 9, 2026. ↩↩↩↩

  3. Apple, Get your subscriptions ready for iOS 27, Apple Developer News, September 16, 2026. Source of “With Volume Purchasing, organizations that use Apple Business and Apple School Manager can buy your subscriptions through a single Apple In-App Purchase and assign seats using a device management provider,” “With Group Purchases, a subscriber can buy multiple seats in a single Apple In-App Purchase and invite others to join. Apple handles any seat assignment and the invitation flow,” the clause that follows naming “small businesses, individual departments, or teams” as the groups it serves, “Starting today, multiseat purchases are enabled by default for subscriptions in App Store Connect. You have full control over availability and can disable multiseat purchases entirely, or selectively manage availability across the App Store, Apple Business, and Apple School Manager,” “Volume Purchasing launches on October 22, 2026, and Group Purchases will launch this winter,” and “You can start preparing today by making sure your apps use StoreKit 2 to handle your Apple In-App Purchases.” Read on October 9, 2026. ↩↩↩↩↩↩↩↩↩↩↩↩

  4. Author’s production code in Reps, Reps/Reps/Services/RepsProStore.swift, read October 9, 2026. The file’s header documents two auto-renewable products in the “Reps Pro” subscription group, com.941apps.Reps.pro.monthly at $7.99 per month and com.941apps.Reps.pro.yearly at $49.99 per year. The purchaseDetailed(_:source:) and refreshEntitlement(verified:) excerpts in the post are from that file with telemetry, debug-only lines, and one explanatory comment removed; the file’s header comment still describes a seven-day free trial on each product, but Reps commit a95935b of September 3, 2026 removed the introductory offers from both products ("introductoryOffer": null on each in Reps.storekit) in favor of three free workouts, so the header predates the current configuration; the arrival greeting’s predicate includes $0.ownershipType == .purchased; an inline comment inside currentSubscriptionJWS() states that “the server re-verifies signature, expiry, and revocation regardless,” the server being the managed-planning proxy. The Transaction.updates handler in start() finishes each verified transaction, remembers its expiry and JWS only when revocationDate == nil, and then calls refreshEntitlement(verified:), whose fallback reads the stored expiry when the currentEntitlements pass finds nothing; the only code that clears the stored expiry on a revocation is the guard inside the currentEntitlements loop, which Apple’s documentation says a revoked transaction never reaches (note 23). The gap described in the post is therefore in the shipping code as of October 9, 2026. Both products were created before September 14, 2026, use StoreKit 2, and have Family Sharing off. ↩↩↩↩↩↩↩↩↩

  5. Apple, Offer subscriptions to groups and organizations, WWDC26 session 391, transcript. Source of “Customers can make group purchases through your app, just like they make in-app purchases today,” “This is perfect for small teams or social groups to collaborate on apps,” “a perfect solution for organizations with larger scale and requirements for management and identity,” “These new options are available for all auto-renewable subscriptions using StoreKit 2,” “For most new and existing subscriptions using StoreKit 2, the ability to sell to groups and organizations is on by default. If your subscription has Family Sharing enabled, you can still sell to groups and organizations, but it is opted-out by default so you can control how the two options work for you,” “StoreKit 2 is required to offer subscriptions to groups and organizations,” “With volume purchasing, Apple Business and Apple School Manager, display your subscriptions and handle the purchase process. All you need to do is make sure your subscription is available to organizations,” “the same way they assign apps today, through a device management service,” “owned and managed by the organization,” “For group purchases, you make your own in-app UI to trigger the StoreKit 2 purchase flow,” “After merchandising, you’ll need to get the number of seats requested from your customer and pass that into the StoreKit 2 purchase request,” from the session’s opening, “Then, all they need to do is share an invite link with anyone they want to give access to your plan. When they accept, they’ll automatically get a seat assigned,” and from the later seat-management section, “With group purchases, an invitation link will be generated for the initial purchaser to share with members. When assignments are completed from either purchase type, the App Store assigns a transaction for each member, and you can give them access,” “by default, group purchases will use the included seat management system, which covers, generating the invitation link, tracking member acceptance and assignment and Seat life-cycle management for your application, like cancellations,” “All you need to do is start a purchase request and Apple will take it from there,” “if you already implement an invitation and member management system for your app, you can leverage it,” “By default, every seat of your subscription is sold at the current price in App Store Connect,” “You can set up to 5 price bands, with full control over the quantities required for each band, and the price,” the $19.99 example with bands at seats one through 20, 21 through 40, and 41 and above priced $19.99, $13.99, and $10.99, the “about 20% from the base price” summary of a 50-seat purchase, and “Integrating custom invitation flows, will be powered via new App Store Server API endpoints.” The session shows no code and names no StoreKit API for the seat count. Read from the session page on October 9, 2026. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  6. Apple, inAppOwnershipType, App Store Server API. Abstract: “A string that describes whether the transaction was purchased by the customer, or is available to them through Family Sharing, an organization, or a group.” Values: FAMILY_SHARED, “The transaction belongs to a family member who benefits from service”; PURCHASED, “The transaction belongs to the purchaser”; ASSIGNED, “The transaction belongs to a customer who has access through an organization or group.” Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩

  7. Apple, Transaction.OwnershipType, StoreKit. Static members purchased, “The transaction belongs to the purchaser”; familyShared, “The transaction belongs to a family member who benefits from the service”; and assigned, “The user has access to this transaction through an organization.” The page abstract still reads “The types the system uses to describe whether the user purchased the product or it’s available to them through Family Sharing.” Platform availability is given for the struct only, iOS 15.0 and equivalents, with no per-member introduction version. Read from Apple’s documentation JSON on October 9, 2026. The SDK is more specific: in the macOS 27.0 SDK inside Xcode 27.0 (build 27A266a), StoreKit.framework/Versions/A/Modules/StoreKit.swiftmodule/arm64e-apple-macos.swiftinterface declares public static var assigned with @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, visionOS 1.0, *) and @backDeployed(before: iOS 27.0, macOS 27.0, tvOS 27.0, watchOS 27.0, visionOS 27.0), directly below purchased and familyShared, which carry no attribute of their own. The currentAccess sample in the post typechecks with xcrun swiftc -typecheck against both the arm64-apple-macos27.0 and arm64-apple-macos26.0 targets with that toolchain, October 9, 2026. The same interface declares the purchase calls the post names: public func purchase(options: Set<Product.PurchaseOption> = []) async throws -> Product.PurchaseResult at line 2702 and public func purchase(confirmIn window: NSWindow, options: Set<Product.PurchaseOption> = []) async throws -> Product.PurchaseResult at line 2709, module qualifiers removed. ↩↩↩↩↩↩↩↩↩

  8. Apple, revocationType, App Store Server API. Values: REFUND_FULL, REFUND_PRORATED, FAMILY_REVOKE, and ASSIGNMENT_REVOKE, “The organization or group purchaser removed the subscription from the customer.” Discussion: “A revocationType of ASSIGNMENT_REVOKE indicates that the organization or group purchaser removed the subscription from a customer. Revoke the customer’s access to the content the transaction provides. For more information about assignment, see Get Customer Groups.” The type was introduced in 1.19; the ASSIGNMENT_REVOKE value was added in 1.22 per the changelog. Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩↩

  9. Apple, Get Customer Groups, App Store Server API, introduced in 1.22. GET https://api.storekit.apple.com/groups/v1/currentGroups/{anyTransactionId} and the sandbox equivalent at api.storekit-sandbox.apple.com. Source of “This endpoint is only available in the sandbox environment,” “A group consists of customers whose access is purchased and managed centrally by a single account, rather than individually,” “Use this endpoint only if your app offers a group experience where a customer’s group or role changes what you present,” followed by the examples “exposing extra controls to a customer with the ADMIN role, or grouping members into that administrator’s shared workspace,” then “Group membership is separate from entitlement. To unlock content for a customer, read their transactions; don’t depend on group membership,” “A customer can belong to more than one group, and can hold a different role in each,” and the sandbox placeholder response with groupId 900000000000000000, groupType ORGANIZATION, and roles ADMIN and NONE on two example products. Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩↩↩↩↩↩↩

  10. Apple, Get Group Members, App Store Server API, introduced in 1.22. GET https://api.storekit.apple.com/groups/v1/group/{groupId} and the sandbox equivalent, with optional limit (maximum 100) and paginationToken query parameters. Source of “This endpoint is only available in the sandbox environment,” “Each entry identifies the member by their appTransactionId,” “If the hasMore field in the response is true, more members are available: call the endpoint again with the paginationToken from the previous response to get the next set,” “Group membership is separate from any transaction information. To unlock content for a customer, read their transactions; don’t depend on this endpoint,” and the sandbox placeholder response with one member, appTransactionId 700000000000000000, and hasMore false. Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩↩↩↩↩

  11. Apple, InvalidAssignedTransactionNotSupportedError, App Store Server API, introduced in 1.22. Error code 4000227, message “Invalid request. Assigned transactions aren’t supported by this endpoint.” Discussion: “A request returns this error if you call the Send Consumption Information, Send Consumption Information V1, or Set App Account Token endpoint with a transaction identifier for a transaction that an organization or group assigns to the customer. To identify assigned transactions before you call these endpoints, check for an inAppOwnershipType of ASSIGNED.” Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩↩↩↩

  12. Apple, AssignedSubscriptionExtensionIneligibleError, App Store Server API, introduced in 1.22. Error code 4030028, message “Assigned subscriptions can’t get a renewal date extension.” Discussion: “A request returns this error if you call the Extend a Subscription Renewal Date endpoint with an originalTransactionId that belongs to a subscription an organization or group assigns to the customer. An assigned subscription renews on the same schedule as the subscription the organization or group purchaser bought, so the endpoint doesn’t support extending the renewal date for an individual member. To identify assigned transactions before you call the endpoint, check for an inAppOwnershipType of ASSIGNED.” Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩↩

  13. Apple, quantity(_:) on Product.PurchaseOption, StoreKit. Declaration static func quantity(_ quantity: Int) -> Product.PurchaseOption; abstract “Indicates the quantity of items the customer is purchasing”; parameter note “The default value is 1. The maximum value is 10”; discussion “The quantity applies to consumable Apple In-App Purchases and non-renewing subscriptions.” Available from iOS 15.0. The Product.PurchaseOption page lists no member mentioning seats, groups, or multiseat and no iOS 27 addition. Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩

  14. Apple, Manage purchase options for an auto-renewable subscription, App Store Connect Help. Source of “Multiseat purchases will be available for Business and Education organizations, and for App Store customers later this year. Multiseat purchases are turned on by default for all auto-renewable subscriptions. Subscriptions created prior to September 14, 2026 that do not use StoreKit 2 or that have Family Sharing turned on are set to opted out by default,” “This customer, known as the group purchaser, manages the shared subscription and controls who has access,” “In Apple Business and Apple School Manager, only multiseat purchases are supported,” the undated “Default settings for existing subscriptions: Subscriptions are set to opted out by default if the app doesn’t use StoreKit 2 or has Family Sharing turned on. If you want to offer multiseat purchases, you can turn them on at any time in App Store Connect,” “Subscriptions for custom apps will automatically be available on Apple Business, and Apple School Manager and you may not opt out of multiseat purchases,” “Required role: Account Holder, Admin, or App Manager,” “If you disallow multiseat purchases, new customers can’t buy multiple seats and this subscription is removed from Apple Business and Apple School Manager, which support multiseat purchases only. Existing customers’ subscriptions continue to renew until the group purchaser cancels, New seats cannot be added, but can be removed by the group purchaser,” “After this subscription has been approved, you may not remove App Store availability,” “Existing subscribers won’t renew automatically and will be canceled at the end of their next renewal. To remove Apple Business, and/or Apple School Manager from an approved subscription, you must be the Account Holder,” “only the group purchaser will be able to share with family members when both multiseat purchases and Family Sharing are turned on. All other seats will be for individual use only,” “If you’ve enabled multiseat purchases for a subscription, only the group purchaser’s access will include Family Sharing. Once you turn on Family Sharing, you won’t be able to turn it off.” Read on October 9, 2026. ↩↩↩↩↩↩↩↩↩↩↩↩

  15. Apple, JWSTransactionDecodedPayload, App Store Server API. The quantity field’s description: “The number of products or seats the customer purchased.” The inAppOwnershipType field refers to the type documented in note 6, and the payload also lists appTransactionId, the identifier of the app download transaction. Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩

  16. Apple, App Store Server Notifications changelog, entry dated September 28, 2026: “Added the ASSIGNED value to inAppOwnershipType, and the ASSIGNMENT_REVOKE value to revocationType, to support multiseat purchases, which let organizations and groups buy your subscriptions in bulk. These values are only available in the sandbox environment,” and “The quantity field also reports the number of seats for a subscription that a customer buys as a multiseat purchase.” The next entry, dated October 1, 2026, adds the CORE_TECHNOLOGY token type and nothing about seats. Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩

  17. Apple, StoreKit framework landing page. Its topic sections are Apple In-App Purchase, App transaction, Messages, Reviews, Recommendations, Background assets extension, Payment method binding, Ad network attribution, External Purchase, External link account, Deprecated, and the generated Articles and Structures sections; no section or page abstract mentions seats, multiseat, group purchases, organizations, or volume purchasing. Read from Apple’s documentation JSON on October 9, 2026. ↩

  18. Apple, role, App Store Server API, introduced in 1.22. Abstract “A string that identifies a customer’s role for a product within a group.” Values: NONE, “The customer has a seat in the group but doesn’t administer it”; ADMIN, “The customer administers the group for the product.” Discussion: “Roles apply only to a group with a groupType of ORGANIZATION. A group with a groupType of CONSUMER doesn’t report roles,” and “This value is informational. Determine access to content based on the customer’s transactions. Use role if you want to offer an administrator something the other members don’t get, such as naming the team or configuring an experience for the whole group.” Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩

  19. Apple, Transaction.RevocationReason, StoreKit. Abstract “Reasons that describe why the App Store may refund a transaction or revoke it from Family Sharing.” Static members developerIssue, other, and upgradedToBundle, “The transaction was revoked because the customer switched to a subscription bundle.” No member refers to assignment, organizations, or groups. Read from Apple’s documentation JSON on October 9, 2026. ↩

  20. Apple, notificationType, App Store Server Notifications V2. The REVOKE value is described as a notification that an in-app purchase the customer had through Family Sharing is no longer available through sharing, and the page’s 23 values and their subtypes include none that mention seats, assignment, organizations, or multiseat. Read from Apple’s documentation JSON on October 9, 2026. ↩↩

  21. Apple, groupType, App Store Server API, introduced in 1.22. Abstract “A string that describes the kind of multiseat purchase a customer’s access comes from.” Values: ORGANIZATION, “An organization bought seats through Volume Purchasing and assigned one to the customer”; CONSUMER, “A subscriber bought seats through Group Purchases and invited the customer to join.” The groupId type’s abstract is “The unique identifier of a group, within the scope of your app.” Read from Apple’s documentation JSON on October 9, 2026. ↩

  22. Apple, GroupMemberEntry, App Store Server API, introduced in 1.22. Abstract “A customer that belongs to a group.” Its only property is appTransactionId, “The unique identifier of the member’s app download transaction.” Read from Apple’s documentation JSON on October 9, 2026. ↩

  23. Apple, currentEntitlements, StoreKit. Abstract “A sequence of the latest transactions that entitle a customer to Apple In-App Purchases and subscriptions.” The discussion lists what the sequence emits, including, as the page renders its symbol links, “The latest transaction for each auto-renewable subscription that has a Product.SubscriptionInfo.RenewalState state of subscribed or inGracePeriod,” and states: “Products that the App Store has refunded or revoked don’t appear in the current entitlements.” The page does not mention ownership type or multiseat; the claim that a seat holder’s transaction appears in the sequence is the author’s reading of that page together with the session’s “the App Store assigns a transaction for each member.” Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩↩↩

  24. Apple, updates, StoreKit. Abstract “The asynchronous sequence that emits a transaction when the system creates or updates transactions that occur outside the app or on other devices.” Discussion, as the page renders its symbol link: “Use updates to receive new transactions while the app is running. This sequence receives transactions that occur outside of the app, such as Ask to Buy transactions, offer code redemptions, and purchases that customers make in the App Store. It also emits transactions that customers complete in your app on another device.” The page’s sample handler checks revocationDate and carries the comment “Remove access to the product identified by transaction.productID. Transaction.revocationReason provides details about the revoked transaction.” The prose names no revocation case; the sample is the only place the page shows one arriving through the sequence. Read from Apple’s documentation JSON on October 9, 2026. ↩↩↩↩↩

  25. Apple, Transaction.RevocationType, StoreKit, introduced in iOS 26.4, iPadOS 26.4, Mac Catalyst 26.4, macOS 26.4, tvOS 26.4, visionOS 26.4, and watchOS 26.4. Static members: assignmentRevocation, “The transaction was revoked by the organization administrator”; familyRevocation, “The transaction was revoked due to a family sharing revocation”; fullRefund, “The transaction was fully refunded”; proratedRefund, “The transaction was partially refunded based on consumption.” The revocationType property, declared let revocationType: Transaction.RevocationType?, is introduced at 26.4 on the same platforms, and its discussion reads: “This property indicates whether the transaction has a full refund, a prorated refund, or is revoked from Family Sharing. This property is nil for transactions that are not revoked.” In the macOS 27.0 SDK interface cited in note 7, lines 167 through 178 declare the struct @available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *) and assignmentRevocation with the same availability plus @backDeployed(before: iOS 27.0, macOS 27.0, tvOS 27.0, watchOS 27.0, visionOS 27.0), returning Self(rawValue: "ASSIGNMENT_REVOKE"); line 321 declares public let revocationType: Transaction.RevocationType?. Read from Apple’s documentation JSON and the SDK on October 9, 2026. ↩↩↩↩↩

Powiązane artykuły

The App Store's Social Media Checkbox and What It Costs

September's App Store rule makes every submission declare social media capabilities. The under-13 carve-out costs an ent…

30 min czytania

On Demand Resources Is Deprecated: What Background Assets Costs

Apple deprecated ODR in 13 words. The replacement forks three ways, sets an iOS 26 floor, and hands you back the disk ma…

26 min czytania

Honoring the Old Pokémon Games Without Borrowing Them

What made the Game Boy Pokémon games feel alive, measured from their decompilations; the fan-game and Palworld record by…

109 min czytania