FlowPilotConfiguration to FlowPilot.configure(_:). After that, you reach the SDK through the FlowPilot.shared singleton.
Before you startYou need:
- A FlowPilot workspace.
- An app inside that workspace.
- An SDK API key for that app.
Configure at launch
Build aFlowPilotConfiguration with at least an apiKey and an appId, then call FlowPilot.configure(_:).
- SwiftUI
- UIKit
FlowPilot.configure(_:) checks that the API key starts with fp_. If it does not, configuration is skipped, an error is logged, and FlowPilot.shared stays nil. Every later present call goes through FlowPilot.shared?, so a skipped configuration means nothing shows (rather than a crash).
Where the credentials come from
apiKeyis an SDK API key for your app. Create one in the dashboard (it is shown only once). It is not your dashboard login. See API keys.appIdis the App ID of the app that owns your placements. See Workspaces and apps.
Configuration options
FlowPilotConfiguration has two required parameters and the rest are optional with sensible defaults.
The App ID that owns your placements. From Workspaces and apps.
Which FlowPilot backend to talk to. One of
.development, .staging, .production, or .custom(url:). Production points at https://api.flowpilot.io/v1. Use .custom(url:) for a self-hosted or test backend.Initial SDK context used for variable resolution and audience targeting (for example
["user.id": "123", "user.is_premium": true]). You can update it later with updateContext(_:). See Variables and context.Whether resolved flows are cached. Caching makes repeat presents fast and powers offline fallback. See Caching.
Custom directory for the flow cache.
nil uses a platform-default location.Hard wall-clock deadline, in seconds, for resolving a placement (including retries and backoff), so a present can never hang on the network. Values are clamped to a minimum of
0.5. When the deadline is hit, the SDK falls back to cache, then a bundled default, then your host fallback.Build-time offline defaults, keyed by placement key. Each value is the base name of a JSON resource in your app bundle (for example
"OnboardingDefault" loads OnboardingDefault.json). See Offline and bundled flows.Offline image and font assets for bundled flows, keyed by placement key, so a bundled default renders with no network at all. See Offline and bundled flows.
Whether images and media are preloaded in screen order when a flow initializes, so users do not see loading states while navigating. See Media preloading.
Placement keys to warm automatically, once, in the background right after
configure(_:). Warming runs at utility priority and never blocks startup: it caches each flow’s JSON and fonts, plus images per prefetchMediaStrategy, so a later present hits the cache. No-op when cachingEnabled is false. Warmed entries only survive their freshness TTL, so this has no visible effect against a 0-TTL backend (.development / .custom). See Prefetching.How aggressively launch prefetch warms images:
.none (JSON + fonts only), .firstScreen (also first-screen and persistent-zone images, the default), or .allScreens (also every screen’s images). Also bounds the screen window when an explicit prefetch(_:warmMedia: true) call opts into media warming. See Prefetching.Maximum in-memory image cache size, in bytes. See Caching.
Maximum on-disk image cache size, in bytes. See Caching.
Optional override for the debug overlay.
nil leaves it off in release builds.How much the SDK logs. One of
.none, .error, .warn, .info, .debug, .verbose.Example
A complete launch configuration with a few context attributes for targeting and variable resolution:Common mistakes
- Configuring more than once. Configure a single time at launch. Calling
configure(_:)again replaces the shared instance and resets in-memory state. - Presenting before configuring. If you present before
configure(_:)runs,FlowPilot.sharedisniland nothing happens. Configure first, in yourAppinit()orapplication(_:didFinishLaunchingWithOptions:). - Hardcoding the API key in committed source. Inject it from build settings or a secrets file instead.
- Wrong environment. A
.stagingor.developmentkey will not resolve against.production, and vice versa. Match the environment to the key. - App ID from the wrong app. The
appIdmust be the app that owns the placement you present, or the resolve returns no flow.
Troubleshooting
- Nothing presents and
FlowPilot.sharedisnil. The API key did not start withfp_, soconfigure(_:)was skipped. Check the logs for “Invalid API key format” and pass a valid SDK key. The SDK exposes this as theinvalidApiKeyerror code. - An “sdk_not_initialized” path is hit. You presented before configuring. Move
configure(_:)earlier in launch. See Error handling. - A resolve returns no flow. Usually the wrong
appId, the wrong environment for the key, or a placement with no published flow. Walk the quickstart troubleshooting checklist.