Skip to content

Quick start

This page shows a minimal end-to-end integration: construct the client, check for an update, and install it. It assumes you have already added the package and have an app key and app secret from your channel configuration.

Construct the client

AppGantryUpdates is a Swift actor. Create one with an AppGantryConfiguration:

import AppGantrySDK

let updates = AppGantryUpdates(
    configuration: AppGantryConfiguration(
        baseURL: URL(string: "https://api.appgantry.com/sdk/v1")!,
        appKey: "<your-app-key>",
        appSecret: "<your-app-secret>"
    )
)

You typically construct this once and hold onto it (for example on a view model or an app-level object).

Check, prompt, install

// currentVersion / currentBuild default to the host bundle's
// CFBundleShortVersionString and CFBundleVersion.
let info = try await updates.checkForUpdate()

if info.updateAvailable {
    let metadata = try await updates.appMetadata()

    // Show your prompt using metadata.name, info.latestVersionName,
    // and info.releaseNotes. When the user confirms:
    let opened = try await updates.beginInstall(for: info)
    if opened, let releaseId = info.releaseId {
        try await updates.reportInstall(releaseId: releaseId, state: .installing)
    }
}

beginInstall(for:) returns false when the update has no iOS over-the-air manifest; handle that case (for example by falling back to a direct download on non-iOS platforms).

What happened on first use

The first call that talks to the backend (here, checkForUpdate()) enrolls the install: it exchanges your app secret for a scoped, revocable update token and persists it in the Keychain. You do not call enroll() yourself unless you want to. If the token is later rejected, the SDK re-enrolls transparently and retries once. See Tokens and errors.

Mandatory updates

info.isMandatory is true when the release must be installed. Your UI should not let the user dismiss a mandatory update. The built-in UpdatePromptView hides its "Later" button automatically in that case.

Use the built-in prompt

Instead of building your own UI, you can render the shipped SwiftUI view:

let metadata = try await updates.appMetadata()
let icon = try await updates.iconData(for: metadata)
let content = UpdatePromptContent(update: info, metadata: metadata, iconData: icon)

UpdatePromptView(
    content: content,
    onInstall: { Task { try await updates.beginInstall(for: info) } },
    onLater: { /* dismiss */ }
)

See The update prompt for the full detail.

When it doesn't work

The failures that catch people out on a first integration, in the order they show up:

Symptom Cause Fix
SDKError.notConfigured on construction An empty app key or app secret Copy both from the channel's SDK app. See Configuration
The first call throws a 401 The app secret is wrong or has been revoked. The /sdk/v1 surface answers a uniform 401 for every credential problem, so the status alone won't tell you which Re-check the secret; if it was revoked, create a new SDK app. See Every failure is the same 401
info.updateAvailable is false with a newer build uploaded The build wasn't published into this SDK app's channel. Uploading is not releasing Publish the build into that channel as a release
beginInstall(for:) returns false No iOS over-the-air manifest for that release Fall back to a direct download
The install begins and the app icon greys out The device isn't in the provisioning profile the build was signed with Enroll the device, regenerate the profile, re-sign, re-upload
Everything works in the simulator and nothing works on device Network policy, or the device can't reach the API Check HTTPS access to api.appgantry.com from the device

Anything not on that list is almost certainly a typed SDKError you can switch on — see Tokens & errors.

Next