iOS SDK

Swift Package. iOS 16+. Zero external dependencies. Currently at v0.2.0.

Install

In Xcode → File → Add Package Dependencies…, paste:

text
https://github.com/fil-technology/appmate-ios

Or in Package.swift:

swift
.package(url: "https://github.com/fil-technology/appmate-ios", from: "0.2.0")

Configure

Once at launch:

swift
import AppMate

RetentionFlow.configure(
    .init(
        appSlug: "my-ios-app",
        baseURL: URL(string: "https://cancel.appmate.cloud")!,
        urlScheme: "myapp"
    )
)

Start the cancel flow

swift
RetentionFlow.startCancelFlow(
    userId: currentUser.id,
    attributes: ["plan": "monthly"]
) { link in
    switch link.action {
    case .openPremium(let paywallId):
        navigateToPaywall(variant: paywallId)
    case .openOffer(let offerId):
        OfferRouter.present(offerId)
    case .openSupport(let topic, let message):
        openSupportInbox(topic: topic, prefilled: message)
    case .openFeature(let id): openFeature(id)
    case .returnToApp:        break
    case .manageSubscription:
        Task { await RetentionFlow.presentManageSubscriptions() }
    case .externalURL(let url):
        UIApplication.shared.open(url)
    case .none:               break
    }
}

Coexisting with your existing deep links

AppMate URLs are namespaced as {yourscheme}://retention-flow/action?.... The SDK's parser returns nil for URLs that don't match, so it never claims someone else's URL. Chain it in front of your existing handler:

swift
.onOpenURL { url in
    if let link = RetentionFlow.deepLink(from: url) {
        handleAppMate(link)
        return                     // AppMate URL — done
    }
    handleMyExistingDeepLinks(url) // everything else
}
manage_subscription doesn't even use your scheme — it routes to Apple's StoreKit sheet directly. Your URL handler never sees it.

Manage subscriptions helper

Wraps StoreKit 2's AppStore.showManageSubscriptions(in:) with an App Store URL fallback for Simulator and signed-out devices.

swift
Task { await RetentionFlow.presentManageSubscriptions() }

Soft-fail behaviour

If the AppMate server is unreachable, onAction is invoked with .manageSubscription so you can route the user straight to the App Store — they're never blocked from cancelling.

Action reference

  • .returnToApp — open your home screen.
  • .openPremium(paywallId:) — show your paywall; paywallId may be set to target a variant.
  • .openOffer(id:) — your app maps the id to a StoreKit promo, RevenueCat offering, or custom paywall.
  • .openSupport(topic:message:) — pre-fill your support sheet.
  • .openFeature(id:) — deep-link to a feature, tutorial, or onboarding screen.
  • .manageSubscription — present StoreKit 2 manage-subs.
  • .externalURL(URL) — open in user's browser.
  • .none — future / unknown — handle defensively.

Full source + tests: github.com/fil-technology/appmate-ios.