apple/app-store-server-library-swift

The Swift server library for the App Store Server API and App Store Server Notifications.

297

stars

203

commits

Swift

primary language

Sep 4, 2026

updated

README

Apple App Store Server Swift Library

The Swift server library for the App Store Server API, App Store Server Notifications, the Retention Messaging API, and Advanced Commerce API. Also available in Java, Python, and Node.js.

Table of Contents

  1. Installation
  2. Documentation
  3. Usage
  4. Support

Installation

Requirements

  • Swift 6

Swift Package Manager

Add the following dependency

.package(url: "https://github.com/apple/app-store-server-library-swift.git", .upToNextMinor(from: "6.0.0")),

Documentation

Documentation

WWDC Video

Obtaining an In-App Purchase key from App Store Connect

To use the App Store Server API or create promotional offer signatures, a signing key downloaded from App Store Connect is required. To obtain this key, you must have the Admin role. Go to Users and Access > Integrations > In-App Purchase. Here you can create and manage keys, as well as find your issuer ID. When using a key, you'll need the key ID and issuer ID as well.

Obtaining Apple Root Certificates

Download and store the root certificates found in the Apple Root Certificates section of the Apple PKI site. Provide these certificates as an array to a SignedDataVerifier to allow verifying the signed data comes from Apple.

Usage

API Usage

import AppStoreServerLibrary

let issuerId = "99b16628-15e4-4668-972b-eeff55eeff55"
let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let client = try! AppStoreServerAPIClient(signingKey: encodedKey, keyId: keyId, issuerId: issuerId, bundleId: bundleId, environment: environment)

let response = await client.requestTestNotification()
switch response {
case .success(let response):
    print(response.testNotificationToken)
case .failure(let failure):
    print(failure.statusCode)
    print(failure.rawApiError)
    print(failure.apiError)
    print(failure.errorMessage)
    print(failure.causedBy)
    print(failure.retryAfter)
}

Verification Usage

import AppStoreServerLibrary

let bundleId = "com.example"
let appleRootCAs = loadRootCAs() // Specific implementation may vary
let appAppleId: Int64? = nil // appAppleId must be provided for the Production environment
let enableOnlineChecks = true
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let verifier = try! SignedDataVerifier(rootCertificates: appleRootCAs, bundleId: bundleId, appAppleId: appAppleId, environment: environment, enableOnlineChecks: enableOnlineChecks)

let notificationPayload = "ey..."
let notificationResult = await verifier.verifyAndDecodeNotification(signedPayload: notificationPayload)
switch notificationResult {
case .valid(let decodedNotification):
    ...
case .invalid(let error):
    ...
}

Receipt Usage

import AppStoreServerLibrary

let issuerId = "99b16628-15e4-4668-972b-eeff55eeff55"
let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let client = try! AppStoreServerAPIClient(signingKey: encodedKey, keyId: keyId, issuerId: issuerId, bundleId: bundleId, environment: environment)

let appReceipt = "MI..."
let transactionIdOptional = ReceiptUtility.extractTransactionId(appReceipt: appReceipt)
if let transactionId = transactionIdOptional {
    var transactionHistoryRequest = TransactionHistoryRequest()
    transactionHistoryRequest.sort = TransactionHistoryRequest.Order.ascending
    transactionHistoryRequest.revoked = false
    transactionHistoryRequest.productTypes = [TransactionHistoryRequest.ProductType.autoRenewable]

    var response: HistoryResponse?
    var transactions: [String] = []
    repeat {
        let revisionToken = response?.revision
        let apiResponse = await client.getTransactionHistory(anyTransactionId: transactionId, revision: revisionToken, transactionHistoryRequest: transactionHistoryRequest, version: .v2)
        switch apiResponse {
        case .success(let successfulResponse):
            response = successfulResponse
        case .failure:
            // Handle failure; fatalError used for example purposes only
            fatalError("Failed to fetch transaction history")
        }
        if let signedTransactions = response?.signedTransactions {
            transactions.append(contentsOf: signedTransactions)
        }
    } while (response?.hasMore ?? false)
    print(transactions)
}

Promotional Offer Signature Creation

import AppStoreServerLibrary

let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")

let productId = "<product_id>"
let subscriptionOfferId = "<subscription_offer_id>"
let appAccountToken = "<app_account_token>"

// try! used for example purposes only
let signatureCreator = try! PromotionalOfferSignatureCreator(privateKey: encodedKey, keyId: keyId, bundleId: bundleId)

let nonce = UUID()
let timestamp = Int64(Date().timeIntervalSince1970) * 1000
let signature = try! signatureCreator.createSignature(productIdentifier: productId, subscriptionOfferID: subscriptionOfferId, appAccountToken: appAccountToken, nonce: nonce, timestamp: timestamp)
print(signature)

Support

Only the latest major version of the library will receive updates, including security updates. Therefore, it is recommended to update to new major versions.

Contributors

dependabot[bot]

10 commits

0xTim

9 commits

shimastripe

7 commits

apple/app-store-server-library-swift

The Swift server library for the App Store Server API and App Store Server Notifications.

297

stars

203

commits

Swift

primary language

Sep 4, 2026

updated

README

Apple App Store Server Swift Library

The Swift server library for the App Store Server API, App Store Server Notifications, the Retention Messaging API, and Advanced Commerce API. Also available in Java, Python, and Node.js.

Table of Contents

  1. Installation
  2. Documentation
  3. Usage
  4. Support

Installation

Requirements

  • Swift 6

Swift Package Manager

Add the following dependency

.package(url: "https://github.com/apple/app-store-server-library-swift.git", .upToNextMinor(from: "6.0.0")),

Documentation

Documentation

WWDC Video

Obtaining an In-App Purchase key from App Store Connect

To use the App Store Server API or create promotional offer signatures, a signing key downloaded from App Store Connect is required. To obtain this key, you must have the Admin role. Go to Users and Access > Integrations > In-App Purchase. Here you can create and manage keys, as well as find your issuer ID. When using a key, you'll need the key ID and issuer ID as well.

Obtaining Apple Root Certificates

Download and store the root certificates found in the Apple Root Certificates section of the Apple PKI site. Provide these certificates as an array to a SignedDataVerifier to allow verifying the signed data comes from Apple.

Usage

API Usage

import AppStoreServerLibrary

let issuerId = "99b16628-15e4-4668-972b-eeff55eeff55"
let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let client = try! AppStoreServerAPIClient(signingKey: encodedKey, keyId: keyId, issuerId: issuerId, bundleId: bundleId, environment: environment)

let response = await client.requestTestNotification()
switch response {
case .success(let response):
    print(response.testNotificationToken)
case .failure(let failure):
    print(failure.statusCode)
    print(failure.rawApiError)
    print(failure.apiError)
    print(failure.errorMessage)
    print(failure.causedBy)
    print(failure.retryAfter)
}

Verification Usage

import AppStoreServerLibrary

let bundleId = "com.example"
let appleRootCAs = loadRootCAs() // Specific implementation may vary
let appAppleId: Int64? = nil // appAppleId must be provided for the Production environment
let enableOnlineChecks = true
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let verifier = try! SignedDataVerifier(rootCertificates: appleRootCAs, bundleId: bundleId, appAppleId: appAppleId, environment: environment, enableOnlineChecks: enableOnlineChecks)

let notificationPayload = "ey..."
let notificationResult = await verifier.verifyAndDecodeNotification(signedPayload: notificationPayload)
switch notificationResult {
case .valid(let decodedNotification):
    ...
case .invalid(let error):
    ...
}

Receipt Usage

import AppStoreServerLibrary

let issuerId = "99b16628-15e4-4668-972b-eeff55eeff55"
let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")
let environment = AppStoreEnvironment.sandbox

// try! used for example purposes only
let client = try! AppStoreServerAPIClient(signingKey: encodedKey, keyId: keyId, issuerId: issuerId, bundleId: bundleId, environment: environment)

let appReceipt = "MI..."
let transactionIdOptional = ReceiptUtility.extractTransactionId(appReceipt: appReceipt)
if let transactionId = transactionIdOptional {
    var transactionHistoryRequest = TransactionHistoryRequest()
    transactionHistoryRequest.sort = TransactionHistoryRequest.Order.ascending
    transactionHistoryRequest.revoked = false
    transactionHistoryRequest.productTypes = [TransactionHistoryRequest.ProductType.autoRenewable]

    var response: HistoryResponse?
    var transactions: [String] = []
    repeat {
        let revisionToken = response?.revision
        let apiResponse = await client.getTransactionHistory(anyTransactionId: transactionId, revision: revisionToken, transactionHistoryRequest: transactionHistoryRequest, version: .v2)
        switch apiResponse {
        case .success(let successfulResponse):
            response = successfulResponse
        case .failure:
            // Handle failure; fatalError used for example purposes only
            fatalError("Failed to fetch transaction history")
        }
        if let signedTransactions = response?.signedTransactions {
            transactions.append(contentsOf: signedTransactions)
        }
    } while (response?.hasMore ?? false)
    print(transactions)
}

Promotional Offer Signature Creation

import AppStoreServerLibrary

let keyId = "ABCDEFGHIJ"
let bundleId = "com.example"
let encodedKey = try! String(contentsOfFile: "/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8")

let productId = "<product_id>"
let subscriptionOfferId = "<subscription_offer_id>"
let appAccountToken = "<app_account_token>"

// try! used for example purposes only
let signatureCreator = try! PromotionalOfferSignatureCreator(privateKey: encodedKey, keyId: keyId, bundleId: bundleId)

let nonce = UUID()
let timestamp = Int64(Date().timeIntervalSince1970) * 1000
let signature = try! signatureCreator.createSignature(productIdentifier: productId, subscriptionOfferID: subscriptionOfferId, appAccountToken: appAccountToken, nonce: nonce, timestamp: timestamp)
print(signature)

Support

Only the latest major version of the library will receive updates, including security updates. Therefore, it is recommended to update to new major versions.

Contributors

dependabot[bot]

10 commits

0xTim

9 commits

shimastripe

7 commits

Languages

Swift

100.0%