Skip to main content
This is the shortest path from an installed SDK to a flow on screen: configure at launch, present a placement, then read the FlowResult. It assumes you already have a published flow attached to a placement (the Quickstart walks through building that end to end).
Before you startYou need:
You also need:
  • The SDK installed in your Xcode project.
  • A placement key (for example onboarding) with a published flow attached, targeting iOS.

Steps

1

Configure at launch

Call FlowPilot.configure(_:) once, as early as possible, with your API key and App ID. See Configuration for every option.
import FlowPilotSDK

// In your App struct's init() or AppDelegate.application(_:didFinishLaunchingWithOptions:)
FlowPilot.configure(
    FlowPilotConfiguration(
        apiKey: "fp_live_xxxxxxxxxxxxxxxx",
        appId: "your-app-id"
    )
)
2

Present a placement

Ask the SDK to resolve and present your placement. Reach the SDK through FlowPilot.shared.
Call presentPlacement(_:from:) from a view controller. It is async and throws, so wrap it in a Task and a do/catch.
import UIKit
import FlowPilotSDK

final class HomeViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        Task {
            guard let flowPilot = FlowPilot.shared else { return }
            do {
                let result = try await flowPilot.presentPlacement(
                    "onboarding",
                    from: self
                )
                handle(result)
            } catch {
                print("FlowPilot could not present a flow: \(error)")
            }
        }
    }
}
3

Read the result

Both paths hand you a FlowResult. Switch on its outcome to decide what to do next.
func handle(_ result: FlowResult) {
    switch result.outcome {
    case .completed:
        // The user finished the flow.
        print("Completed")
    case .dismissed:
        // The user closed the flow before finishing.
        print("Dismissed")
    case .error:
        // FlowPilot had nothing to present, or rendering failed.
        print("Error: \(result.error?.message ?? "unknown")")
    }
}
FlowResult also carries finalVariables, screensVisited, durationMs, and experimentAssignments. See Results and outcomes.
That is the full loop: configure, present, read the result. For options, the never-throws host fallback, prefetching, and the SwiftUI surface in depth, see the pages below.

Common mistakes

  • Using a dashboard token instead of an SDK API key. The SDK authenticates with Authorization: Bearer <sdk-key>. Your dashboard login will not work. Create an SDK key in the app settings.
  • App ID mismatch. The appId you configure must own the placement, or the resolve returns no flow.
  • Placement key typo, paused placement, or no flow attached. The key in code must match the placement key exactly, the placement must be active, and a published flow must be attached.
  • Forgetting to publish. A draft flow is never served. Publish a version and attach it to the placement.

Troubleshooting

Nothing appears? Walk this checklist:
  1. Is the API key an SDK key (it starts with fp_) and valid for the environment you configured?
  2. Is the App ID the one that owns the placement?
  3. Is the placement active (not paused) and targeting iOS?
  4. Is a published flow version attached to the placement?
  5. Is the placement key in your code an exact match?
  6. Is the device online? If it may be offline, configure caching or a bundled fallback.
Still stuck? See iOS troubleshooting.