FlwKit
Sdk

Configuration

Configure the FlwKit iOS SDK and display flows in your app.

Basic setup

Call FlwKit.configure() once at app startup. Place it in your @main App init() or AppDelegate.application(_:didFinishLaunchingWithOptions:) — before any view appears.

import SwiftUI
import FlwKit_ios
 
@main
struct MyApp: App {
    init() {
        FlwKit.configure(apiKey: "your-api-key")
    }
 
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

configure() triggers a background prefetch of the active flow immediately. By the time a user reaches FlwKitFlowView, the flow is typically already cached and renders with no loading state.


FlwKit.configure()

public static func configure(
    apiKey: String,
    userId: String? = nil,
    baseURL: String? = nil
)
ParameterTypeRequiredDefaultDescription
apiKeyStringYesYour app's API key from the dashboard.
userIdString?NonilStable identifier for the current user. Used to tie analytics events and A/B test assignments to a specific user. Pass nil to use an anonymous session.
baseURLString?Nohttps://api.flwkit.comOverride the API base URL. Only needed when self-hosting the FlwKit backend.

FlwKitFlowView

Add FlwKitFlowView to any SwiftUI view. The active flow is fetched automatically.

// Minimal
FlwKitFlowView()
 
// With completion handler
FlwKitFlowView { result in
    // navigate away
}
 
// Full control
FlwKitFlowView(
    attributes: ["plan": "pro"],
    onComplete: { result in },
    onExit: { }
)
ParameterTypeRequiredDefaultDescription
attributes[String: Any]No[:]Key-value data passed into the flow. Accessible in conditional transitions via attributes.{key}.
onComplete((FlwKitCompletionResult) -> Void)?NonilCalled when the flow reaches a terminal complete action.
onExit(() -> Void)?NonilCalled when the user exits mid-flow.

FlwKitCompletionResult

PropertyTypeDescription
flowIdStringThe flow key identifier.
variantIdString?A/B test variant ID, or nil if the user was not in a test.
completedAtDateTimestamp of completion.
answers[String: Any]All answers keyed by block key. Choice answers are mapped to option labels, not raw values.

FlwKit.present() — UIKit

Use FlwKit.present() to get the flow view programmatically and embed it in a UIHostingController.

FlwKit.present(
    attributes: [:],
    onComplete: { result in
        DispatchQueue.main.async { self.dismiss(animated: true) }
    },
    completion: { result in
        switch result {
        case .success(let flowView):
            let host = UIHostingController(rootView: flowView)
            host.modalPresentationStyle = .fullScreen
            self.present(host, animated: true)
        case .failure(let error):
            print(error.localizedDescription)
        }
    }
)
ParameterTypeRequiredDefaultDescription
attributes[String: Any]No[:]Same as FlwKitFlowView.attributes.
onComplete(FlwKitCompletionResult) -> VoidNono-opSame as FlwKitFlowView.onComplete.
onExit(() -> Void)?NonilSame as FlwKitFlowView.onExit.
completion(Result<AnyView, Error>) -> VoidYesReceives the flow view or an error.

Error handling

All errors conform to LocalizedError. Check error.localizedDescription for a human-readable message.

When flowNotFound or a network error occurs, the SDK automatically falls back to the most recently cached flow. The error is only surfaced if no cache exists.


Caching

The SDK caches the active flow in UserDefaults after the first successful fetch.

SituationBehavior
Cache exists on launchFlow renders immediately; cache refreshes in the background.
No cache, network availableFlow fetches with a loading indicator.
No cache, network unavailableFlwKitFlowView shows an error state with a retry button.

User progress (current screen and answers) is also persisted and restored automatically if the user closes the app mid-flow.


Permission blocks setup (iOS)

Permission blocks trigger native Apple permission prompts from the host app.
If required app configuration is missing, iOS will not show the prompt.

Required setup by block type

Block typeRequired Info.plist key(s)Additional project setup
notification_permissionNone required by Apple for the prompt callNone
health_permissionNSHealthShareUsageDescriptionEnable HealthKit capability on your app target
tracking_permissionNSUserTrackingUsageDescriptioniOS 14+ only. Prompt appears once per app install
camera_permissionNSCameraUsageDescriptionNone
location_permissionNSLocationWhenInUseUsageDescriptionNone (for when-in-use flow)
microphone_permissionNSMicrophoneUsageDescriptionNone
photo_library_permissionNSPhotoLibraryUsageDescriptionNone

Example Info.plist entries

<key>NSHealthShareUsageDescription</key>
<string>We use Health data to personalize your onboarding experience.</string>
<key>NSUserTrackingUsageDescription</key>
<string>We use anonymous data to improve content relevance.</string>
<key>NSCameraUsageDescription</key>
<string>We use your camera for profile photos and scan flows.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We use your location to personalize recommendations.</string>
<key>NSMicrophoneUsageDescription</key>
<string>We use your microphone for voice input blocks.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We use your photo library so you can select images.</string>

Important behavior

  • Apple shows each permission prompt at most once unless the app is reinstalled.
  • If a user already denied permission, guide them to Settings → Your App to enable it manually.
  • For tracking_permission, iOS returns current status immediately when already decided (no second popup).
  • For health_permission, missing HealthKit capability prevents the system prompt from appearing.

Next steps

On this page