Skip to main content
ZeroSettle provides a customer portal powered by Stripe where your customers can manage their subscriptions and payment methods — both in-app and via email links.

In-App Portal

SwiftUI Modifier

The simplest way to add subscription management is the .zsManageSubscription() modifier:
@State private var showManageSubscription = false

Button("Manage Subscription") {
    showManageSubscription = true
}
.zsManageSubscription(isPresented: $showManageSubscription, userId: currentUser.id)
This automatically routes to the right management UI based on where the user’s subscriptions came from.

Programmatic API

For more control, use the methods directly:
// Smart routing — picks the right UI based on entitlement sources
try await ZeroSettle.shared.showManageSubscription(userId: currentUser.id)

// Always open the Stripe customer portal
try await ZeroSettle.shared.openCustomerPortal(userId: currentUser.id)

Dual-Source Handling

showManageSubscription() inspects the user’s current entitlements and routes accordingly:
Entitlement SourcesManagement UI
Web checkout onlyStripe customer portal
StoreKit only (iOS)Apple’s native subscription management
Play Store only (Android)Google Play subscription management
Both web + native storeStripe customer portal
No entitlementsStripe customer portal
If you always want the Stripe portal regardless of source, call openCustomerPortal(userId:) directly.

Auto-Refresh

Entitlements are automatically refreshed when the management UI is dismissed. Any subscription changes the user makes (cancellation, plan change, re-subscribe) will be reflected in ZeroSettle.shared.entitlements and trigger the zeroSettleEntitlementsDidUpdate(_:) delegate callback.
// Entitlements stay in sync automatically after portal dismiss
let entitlements = ZeroSettle.shared.entitlements
let hasAccess = entitlements.contains { $0.isActive }

Observing Changes

There are no portal-specific delegate callbacks. Instead, use the entitlement update delegate to react when a user modifies their subscription through the portal:
class MyDelegate: ZeroSettleDelegate {
    func zeroSettleEntitlementsDidUpdate(_ entitlements: [Entitlement]) {
        // Entitlements refreshed after portal interaction
        updatePremiumUI(entitlements)
    }
}

Cancel Flow

Present a cancellation questionnaire before a user cancels their subscription. The flow collects feedback, optionally shows a retention offer, and returns the outcome. The questionnaire and retention offer are configured on the ZeroSettle dashboard — no code changes needed to update questions or offers.

SwiftUI Modifier

@State private var showCancelFlow = false

Button("Cancel Subscription") {
    showCancelFlow = true
}
.zsCancelFlow(
    isPresented: $showCancelFlow,
    productId: "premium_monthly",
    userId: currentUser.id
) { result in
    switch result {
    case .cancelled:
        // User completed cancellation
        showConfirmation("Your subscription has been cancelled.")
    case .retained:
        // User accepted the save offer
        showConfirmation("Thanks for staying!")
    case .paused(let resumesAt):
        // User chose to pause instead of cancelling
        showConfirmation("Your subscription is paused.")
    case .dismissed:
        // User dismissed without completing
        break
    }
}

Programmatic API

let result = await ZeroSettle.shared.presentCancelFlow(
    productId: "premium_monthly",
    userId: currentUser.id
)
// result is CancelFlow.Result: .cancelled, .retained, .paused, or .dismissed

Cancel Flow Results

ResultDescription
cancelled / CANCELLEDUser completed the flow and cancelled their subscription
retained / RETAINEDUser accepted the retention offer and kept their subscription
paused / PausedUser chose to pause their subscription instead of cancelling
dismissed / DISMISSEDUser dismissed the flow without completing it
Configure the cancellation questionnaire and retention offers from the ZeroSettle dashboard. You can update questions and offers without an app update.

Pause Option

Pause lets subscribers temporarily stop their subscription instead of cancelling outright. When enabled, the cancel flow can present a pause page where the user picks a pause duration.
  • Dashboard-configured: Enable pause and set available durations from the ZeroSettle dashboard. No code changes required.
  • Answer option trigger: Individual answer options in the questionnaire can set triggersPause to route the user to the pause page instead of the retention offer.
  • Resume date: The paused result includes an optional resumesAt date indicating when the subscription will automatically resume.
  • Entitlement state: While paused, the user’s entitlement reflects status == .paused with a pauseResumesAt date. Access is revoked during the pause period and restored automatically when the subscription resumes.

What Customers Can Do

In the Stripe customer portal, customers can:
  • See upcoming payment information — View details about their next billing cycle
  • Cancel a subscription — End their subscription with immediate effect or at period end
  • Change subscription products — Upgrade or downgrade to different subscription tiers
  • Re-subscribe — Reactivate a cancelled subscription before it expires
  • Update payment methods — Change or add new payment methods
  • View payment history — See a complete list of all past payments
  • Download receipts and invoices — Get PDF receipts and invoices for their records
Customers can also access their portal through links included in emails that ZeroSettle sends automatically:
  • Subscription confirmation emails
  • Renewal receipt emails
  • Billing issue notifications
Each email contains a “Manage Subscription” link that opens the Stripe-powered billing portal.