Bagbutik

Generated Swift code for the App Store Connect API based on the official OpenAPI spec.
Swift versions Platforms
CI Documentation
Twitter Mastodon

What is Bagbutik?

Bag·bu·tik (noun) /ˈb̥a̝w-ˌb̥u-tiːk/ - (Danish) A room behind a store

Bagbutik is two things, a command line tool for generating Swift code, and a library with the generated code for the App Store Connect API. The command line tool decodes the official OpenAPI spec for Apple’s App Store Connect API.

While generating the code, the command line tool also downloads the official documentation from Apple’s Documentation site for the App Store Connect API and applies it to the generated code, so you can get documentation right in Xcode.

The command line tool is only needed, when Apple publishes a new version of the spec. A GitHub Action automatically checks for new versions of the spec and creates a pull request with the changes.

How to use Bagbutik

Bagbutik uses JSON Web Tokens (JWT) for authorization. You obtain the required keys from your organization’s App Store Connect account.

See Creating API Keys for App Store Connect API for how to create your keys.

Here is a basic example for fetching all bundle IDs for iOS apps including related profiles sorted by seed ID and the bundle ID itself descending.

import Bagbutik_Core
import Bagbutik_Provisioning

let service = BagbutikService(jwt: try .init(
    keyId: "P9M252746H",
    issuerId: "82067982-6b3b-4a48-be4f-5b10b373c5f2",
    privateKey: """
    -----BEGIN PRIVATE KEY-----
    MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2
    OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r
    1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G
    -----END PRIVATE KEY-----
    """
))
let response = try await service.request(
    .listBundleIdsV1(filters: [.platform([.iOS])],
                     includes: [.profiles],
                     sorts: [.seedIdDescending, .idDescending])
)
print(response)

How to get Bagbutik into a project

Bagbutik supports Swift Package Manager and the internal libraries used to generate the code is also managed by it.

The library of generated code actually consists of multiple libraries, to let the consumer only depend on the endpoints needed. So to get Bagbutik, you need to decide which functionality you need.

In your Package.swift add Bagbutik as a dependency:

dependencies: [
    .package(url: "https://github.com/MortenGregersen/Bagbutik", from: "8.0.0"),

Then in targets add the libraries needed by your target:

targets: [
    .target(
        name: "Awesome",
        dependencies: [
            .product(name: "Bagbutik-AppStore", package: "Bagbutik"),
            .product(name: "Bagbutik-TestFlight", package: "Bagbutik"),

If all libraries are needed, the umbrella library Bagbutik can be used:

targets: [
    .target(
        name: "Awesome",
        dependencies: [
            .product(name: "Bagbutik", package: "Bagbutik"),

Remember to replace the hyphen with an underscore when importing the libraries.

When importing Bagbutik-TestFlight write:

import Bagbutik_TestFlight

Bagbutik-Core

The core library is Bagbutik-Core which contains the BagbutikService, the JWT, protocols and the general generated types like ErrorResponse and PagingInformation.

All other libraries depend on Bagbutik-Core. This is the only library which is documented on Bagbutik.dev, as the other libraries only contain types which are already documented by Apple.

Bagbutik-Models

Because the models from the API are used from many different endpoints, they are all located in Bagbutik-Models. All libraries with endpoints depend on Bagbutik-Models.

Bagbutik-<API-Area>

The endpoints of all the areas of the App Store Connect API are located in different libraries with a describing name.

Right now there are 7 libraries with endpoints:

Manual patches applied to OpenAPI Spec

The OpenAPI Spec provided by Apple do not always align with the data received from the API. Whenever such mismatches are identified, feedback is submitted to Apple and a patch is applied. Whenever an issue is resolved, the patch is removed again.

Currently open feedback and applied patches

FB8977648: The “BundleIdPlatform” schema is missing “UNIVERSAL” and “SERVICES”

  • Submitted: January 21st 2021.
  • Updated: October 14th 2022 - the type “SERVICES” is also missing.

Title: App Store Connect API is missing the “UNIVERSAL” type for the BundleIdPlatform schema

Description

In the OpenAPI spec for the App Store Connect API the “BundleIdPlatform” schema is said to only be “IOS” or “MAC_OS”. This is not right as universal apps (iOS and macOS) has a “UNIVERSAL” platform.

FB12292035: ErrorResponse.Errors has required optional “detail” and no “associatedErrors” in “meta”

  • Submitted: June 9th 2023.

In Apple’s OpenAPI spec the detail property on ErrorResponse.Errors is marked as required. On 12/1/23 some errors (with status code 409) has been observed, with no detail.

In Apple’s OpenAPI spec and documentation the associatedErrors is not mentioned in meta property (last checked 12/1/23). But it is observed when creating a ReviewSubmissionItem with an AppStoreVersion fails.

FB13540097: Almost all of the schemas ending in “WithoutIncludesResponse” has wrong “data” type

  • Submitted: January 14th 2024.
  • Confirmed by Apple: January 31st 2024

Title: App Store Connect API Spec and Docs has wrong schema ref for the “data” property on almost all of the schemas ending in “WithoutIncludesResponse”

Description

Almost all of the schemas ending in “WithoutIncludesResponse” has a wrong schema ref for the “data” property. This is both the case in the OpenAPI Spec and the Docs on developer.apple.com.

As an example, the data property of “BetaTestersWithoutIncludesResponse” refer to the schema “Build”, but when I do a request to the “/v1/betaGroups/{id}/betaTesters” endpoint, all of the items in the “data” of the JSON is of type “BetaTester”. The docs says the same: https://developer.apple.com/documentation/appstoreconnectapi/BetaTestersWithoutIncludesResponse

FB13621277: App Store Connect API Spec is missing “GENERATE_INDIVIDUAL_KEYS” type for the User Role schema

  • Submitted: February 15th 2024.

In the OpenAPI spec for the App Store Connect API the “UserRole” schema is said to not include “GENERATE_INDIVIDUAL_KEYS”. This is not right as “Users” endpoints can have a “GENERATE_INDIVIDUAL_KEYS” type.

Closed feedback (removed patches)

  • FB9963088: The xcodeMetrics schema has no properties or attributes in the OpenAPI spec

    • Submitted: March 21st 2022.
    • Resolved: July 12th 2022 (Spec version 2.0).
  • FB10029609: Required ‘links’ property missing on included BuildBundle

    • Submitted: May 27th 2022.
    • Resolved: At least since May 23rd 2023.
  • FB13071298: App Store Connect API Spec is missing "VISION_OS” type for the Platform schema

    • Submitted: August 28th 2023.
    • Resolved: January 25th 2024 (Spec version 3.2).
  • FB13539766: App Store Connect API Spec is missing “APP_APPLE_VISION_PRO” type for the Screenshot Display Type schema

    • Submitted: January 14th 2024.
    • Resolved: January 25th 2024 (Spec version 3.2).