This iOS SDK integration pattern gives you full control over the onboarding experience. Instead of passing a single flow to the SDK and waiting for it to finish, you create an onboarding session, split the flow into sections, and run each section with startOnboardingSection. Control returns to your app between sections, so you can show your own screens, make decisions, or call your back end before continuing.
Use this pattern when you need to insert your own UI between capture steps, group modules into logical sections, or branch based on intermediate results. If you prefer to define the flow in Dashboard instead, see Run Flows Configured in Dashboard. If you want full control over the flow in client code, see Configure Flows Locally and Run End to End. For more information about these patterns, see Integration Approaches.
This page covers session creation and section execution only. Ensure you have followed the steps to install and initialize the Incode iOS SDK first.
Set Up This Integration Pattern
Complete the following steps in order.
Create a New Onboarding Session
Before running any section, create a session with setupOnboardingSession. The result is delivered through a completion closure; there is no session listener.
IncdOnboardingManager.shared.setupOnboardingSession(
sessionConfig: IncdOnboardingSessionConfiguration(token: "<SESSION_TOKEN>")
) { result in
// result.token, result.interviewId, result.error
}
OnboardingSessionResult exposes token, interviewId, and error. You can optionally supply a list of OnboardingValidationModule values through IncdOnboardingSessionConfiguration.validationModules to determine which modules count toward the onboarding score. If omitted, the default modules .id, .liveness, and .faceRecognition are used.
Create a Delegate to Receive SDK Results
Conform to IncdOnboardingDelegate to receive results from each module and the overall flow. Only onSuccess() and onError(_:) are required. Every other method has a default empty implementation. Override only the events for the modules your flow includes.
extension MyViewController: IncdOnboardingDelegate {
func onOnboardingSessionCreated(_ result: OnboardingSessionResult) {
// Session created: result.token, result.interviewId
}
func onIdProcessed(_ result: IdProcessResult) {
// ID validation completed
}
func onSelfieScanCompleted(_ result: SelfieScanResult) {
// Selfie scan completed
}
func onFaceMatchCompleted(_ result: FaceMatchResult) {
// Face match completed
}
func onOnboardingSectionCompleted(_ flowTag: String) {
// Section finished — safe place to start the next section
}
func userCancelledSession() {
// User cancelled the flow
}
func onSuccess() {
// Onboarding finished successfully
}
func onError(_ error: IncdFlowError) {
// Onboarding aborted due to an error
}
}
For the shape and fields of each result object, see the corresponding page in Modules.
Run a Section
Build an IncdOnboardingFlowConfiguration for the section, add the modules it should run, and start it with startOnboardingSection. The section is tagged at call time with the sectionTag parameter instead of on the builder.
let section = IncdOnboardingFlowConfiguration()
section.addIntro(checks: [])
section.addPhone()
section.addIdScan(scanStep: .both)
IncdOnboardingManager.shared.startOnboardingSection(
flowConfig: section,
sectionTag: "id",
delegate: self
)
Only one section can run at a time. Starting a second section while one is still running fails with IncdFlowError.sectionAlreadyRunning, which carries the tag of the section that is already active.
Start Subsequent Sections from the Section-Complete Callback
IncdOnboardingDelegate reports the end of a section through onOnboardingSectionCompleted(_ flowTag:). This is the documented signal that a section has finished, so start the next section from this callback rather than from an individual module callback such as onIdFrontCompleted(_:).
func onOnboardingSectionCompleted(_ flowTag: String) {
startNextSection() // OK here
}
func startNextSection() {
let next = IncdOnboardingFlowConfiguration()
next.addSelfieScan()
next.addFaceMatch(matchType: .idSelfie, idCategory: .primary)
IncdOnboardingManager.shared.startOnboardingSection(
flowConfig: next,
sectionTag: "face",
delegate: self
)
}
Finish the Flow and Delete Local Data
When you drive the flow section by section, call finishFlow after the last section to close the session on the server. Then call deleteLocalUserData() to remove all local user data. Both are instance methods on IncdOnboardingManager.shared.
IncdOnboardingManager.shared.finishFlow { success, error in
IncdOnboardingManager.shared.deleteLocalUserData()
}
Deleting local user data is also recommended from the terminal delegate callbacks onSuccess(), onError(_:), and userCancelledSession().
Resume an Existing Session
To resume a session—for example, after the app is relaunched mid-flow—create an IncdOnboardingSessionConfiguration with the existing interviewId or token and call setupOnboardingSession before any other API call.
let sessionConfig = IncdOnboardingSessionConfiguration(
validationModules: [.id, .faceRecognition, .liveness],
interviewId: "<EXISTING_INTERVIEW_ID>"
)
IncdOnboardingManager.shared.setupOnboardingSession(sessionConfig: sessionConfig) { result in
// Safe to run sections again
}