SkillAgentSearch skills...

Bagbutik

Generated Swift code for the App Store Connect API based on the official OpenAPI spec.

Install / Use

/learn @MortenGregersen/Bagbutik
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <br /> <img src="https://raw.githubusercontent.com/MortenGregersen/Bagbutik/main/Assets/Bagbutik-logo.png" max-width="90%" alt="Bagbutik" /> </p> <p align="center"> <b>Generated Swift code for the <a href="https://developer.apple.com/documentation/appstoreconnectapi">App Store Connect API</a> based on the official <a href="https://en.wikipedia.org/wiki/OpenAPI_Specification">OpenAPI spec</a>.</b> <br /><br /> <a href="https://swiftpackageindex.com/MortenGregersen/Bagbutik"><img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FMortenGregersen%2FBagbutik%2Fbadge%3Ftype%3Dswift-versions" alt="Swift versions" /></a> <a href="https://swiftpackageindex.com/MortenGregersen/Bagbutik"><img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FMortenGregersen%2FBagbutik%2Fbadge%3Ftype%3Dplatforms" alt="Platforms" /></a> <br /> <a href="https://github.com/MortenGregersen/Bagbutik/actions/workflows/ci.yml"><img src="https://github.com/MortenGregersen/Bagbutik/workflows/CI/badge.svg" alt="CI" /></a> <a href="https://bagbutik.dev"><img src="https://raw.githubusercontent.com/MortenGregersen/Bagbutik/gh-pages/badge.svg" alt="Documentation" /></a> <a href="https://codecov.io/gh/MortenGregersen/Bagbutik"><img src="https://codecov.io/gh/MortenGregersen/Bagbutik/branch/main/graph/badge.svg?token=oJZWL49t0G"/></a> <br /> <a href="https://x.com/mortengregersen"><img src="https://img.shields.io/badge/%40mortengregersen-black?logo=x" alt="X (Twitter)" /></a> <a href="https://mastodon.social/@mortengregersen"><img src="https://img.shields.io/badge/%40mortengregersen-6364FF?logo=mastodon&logoColor=white" alt="Mastodon" /></a> </p>

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)

Project structure

The repository is split into a small manually maintained core and a large generated API surface.

  • Bagbutik-Core contains the request service, JWT support, shared response protocols, and the common models used across all API areas.
  • Bagbutik-Models contains generated shared models that are referenced by more than one API area.
  • Bagbutik-AppStore, Bagbutik-TestFlight, Bagbutik-Reporting, and the other product modules contain generated endpoint builders grouped by App Store Connect domain.
  • BagbutikSpecDecoder decodes Apple's OpenAPI document into an intermediate Swift representation.
  • BagbutikDocsCollector downloads and normalizes Apple documentation so generated code gets useful Xcode documentation comments.
  • BagbutikGenerator combines the decoded spec and collected docs to render the Swift source in Sources/.

This split matters when navigating the codebase. If you want to understand runtime behavior, start in Bagbutik-Core. If you want to understand how generated endpoints and models are produced, start with BagbutikSpecDecoder, BagbutikDocsCollector, and BagbutikGenerator.

How to get Bagbutik into a project

Bagbutik is primarily distributed as a source-based Swift package using Swift Package Manager.

For advanced use cases, a prebuilt XCFramework is also provided. Using the XCFramework is optional and does not replace the source-based package.

Using Bagbutik as a source package

The library of generated code consists of multiple libraries, allowing consumers to depend only on the API areas they need.

Add Bagbutik as a dependency in your Package.swift:

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

Then add the required products to your target:

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

If you need access to all APIs, you can depend on the umbrella library:

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

Available modules

Each module corresponds to a specific area of the App Store Connect API:

Remember to replace hyphens with underscores when importing modules. For example, when importing Bagbutik-TestFlight:

import Bagbutik_TestFlight

Endpoint pattern

Generated endpoints follow the same pattern throughout the package:

  1. Import Bagbutik_Core and the product module for the API area you need.
  2. Build a Request by calling a generated static helper such as .listBundleIdsV1(...).
  3. Send the request through BagbutikService.
  4. If the response type supports pagination, use requestNextPage(for:) or requestAllPages(_:).

This keeps each endpoint builder lightweight while centralizing authentication, decoding, and error handling in BagbutikService.

Using the XCFramework

Bagbutik releases also include a prebuilt XCFramework for cases where you prefer a binary dependency, such as:

  • Faster CI builds
  • Tooling or plugin projects
  • Avoiding recompilation of all Bagbutik modules

The XCFramework contains the umbrella Bagbutik module.

Option 1: Use the XCFramework via URL and checksum (recommended)

Add a binary target in your Package.swift:

.binaryTarget(
    name: "Bagbutik",
    url: "https://github.com/MortenGregersen/Bagbutik/releases/download/<VERSION>/Bagbutik.xcframework.zip",
    checksum: "<CHECKSUM>"
)

The exact checksum for each version is listed in the corresponding GitHub Release.

Then add Bagbutik as a dep

View on GitHub
GitHub Stars185
CategoryProduct
Updated1d ago
Forks9

Languages

Swift

Security Score

100/100

Audited on Apr 8, 2026

No findings