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.
// Smart routing — picks the right UI based on entitlement sourcestry await ZeroSettle.shared.showManageSubscription(userId: currentUser.id)// Always open the Stripe customer portaltry await ZeroSettle.shared.openCustomerPortal(userId: currentUser.id)
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.
Copy
// Entitlements stay in sync automatically after portal dismisslet entitlements = ZeroSettle.shared.entitlementslet hasAccess = entitlements.contains { $0.isActive }
There are no portal-specific delegate callbacks. Instead, use the entitlement update delegate to react when a user modifies their subscription through the portal:
Copy
class MyDelegate: ZeroSettleDelegate { func zeroSettleEntitlementsDidUpdate(_ entitlements: [Entitlement]) { // Entitlements refreshed after portal interaction updatePremiumUI(entitlements) }}
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.
@State private var showCancelFlow = falseButton("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 }}
let result = await ZeroSettle.shared.presentCancelFlow( productId: "premium_monthly", userId: currentUser.id)// result is CancelFlow.Result: .cancelled, .retained, .paused, or .dismissed
User completed the flow and cancelled their subscription
retained / RETAINED
User accepted the retention offer and kept their subscription
paused / Paused
User chose to pause their subscription instead of cancelling
dismissed / DISMISSED
User 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 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.