# Configure Flows Locally and Run Step by Step

Use this pattern when you want to configure the flow in your app code but run modules section by section, with control returned to your app between sections. This is useful when you need to interleave Incode SDK steps with your app's own screens, perform validation or business logic between steps, or split a long flow into logical phases.

## When to use this pattern

Use this pattern when:

- You want to define your flow's modules in code rather than in Dashboard.
- You need control returned to your app between groups of modules.
- You want to call individual SDK modules or group modules into named sections.

For a single end-to-end call that runs all modules consecutively, see [Configure Flows Locally and Run End to End](./flutter-configure-flows-locally-and-run-end-to-end). For flows configured in the Incode Dashboard, see [Run Flows Configured Online](./flutter-run-flows-configured-online).

## Prerequisites

- The SDK is initialized. See [Installation](./flutter-installation).

## 1. Set up the onboarding session

Before calling any other Onboarding SDK components, set up the onboarding session.

```dart
OnboardingSessionConfiguration sessionConfiguration = OnboardingSessionConfiguration();

IncodeOnboardingSdk.setupOnboardingSession(
  sessionConfig: sessionConfiguration,
  onError: (String error) {
    print('Incode onboarding session error: $error');
  },
  onSuccess: (OnboardingSessionResult result) {
    print('Incode Onboarding session created! $result');
  },
);
```

The `OnboardingSessionConfiguration` accepts the same parameters as the end-to-end pattern. See [Configure the onboarding session](./flutter-configure-flows-locally-and-run-end-to-end#1-configure-the-onboarding-session) on the end-to-end pattern page for the full parameter list.

## 2. Configure a section flow

Once the onboarding session is created, configure a section by creating an `OnboardingFlowConfiguration` and adding the modules for that section.

```dart
OnboardingFlowConfiguration flowConfig = OnboardingFlowConfiguration();
flowConfig.addIdScan();
```

For the full list of available modules and their configuration parameters, see [Modules](./flutter-modules).

## 3. Start the onboarding section

Call `startNewOnboardingSection` and provide a `flowTag` to identify the section. Add per-module listener callbacks to receive results as modules complete.

```dart
IncodeOnboardingSdk.startNewOnboardingSection(
  flowConfig: flowConfig,
  flowTag: 'idSection',
  onError: (String error) {
    print('Incode onboarding session error: $error');
  },
  onUserCancelled: () {
    print('User cancelled section');
  },
  onIdFrontCompleted: (IdScanResult result) {
    print('onIdFrontCompleted result: $result');
  },
  onIdBackCompleted: (IdScanResult result) {
    print('onIdBackCompleted result: $result');
  },
  onIdProcessed: (String ocrData) {
    print('onIdProcessed result: $ocrData');
  },
  onOnboardingSectionCompleted: (String flowTag) {
    print('Section completed: $flowTag');
  },
);
```

### Section callbacks

- `onError`: Called when an error occurs during section execution.
- `onOnboardingSectionCompleted`: Called when the section completes. Receives the `flowTag` you provided. This is the equivalent of `onSuccess` on `startOnboarding`.
- `onUserCancelled`: Called when the user cancels the section.
- Per-module completion callbacks: Optional. Add the callbacks for modules whose results you want to receive as they complete. See [Results](./flutter-results) for the full list of available listeners and their payloads.

### Chain multiple sections

To run more than one section within the same session, call `startNewOnboardingSection` again with a new `flowConfig` and `flowTag` after the previous section's `onOnboardingSectionCompleted` fires. Sections must be started sequentially; do not start a new section before the previous one has completed.

Example:

```dart
IncodeOnboardingSdk.startNewOnboardingSection(
  flowConfig: idFlowConfig,
  flowTag: 'idSection',
  onOnboardingSectionCompleted: (String flowTag) {
    IncodeOnboardingSdk.startNewOnboardingSection(
      flowConfig: selfieFlowConfig,
      flowTag: 'selfieSection',
      onOnboardingSectionCompleted: (String flowTag) {
        // Continue chaining, or call finishFlow() when done.
      },
      onError: (String error) { /* ... */ },
    );
  },
  onError: (String error) { /* ... */ },
);
```

Once all sections are complete, call [`finishFlow()`](./flutter-api-reference#finishflow) to end the session.

## 4. Finish the onboarding session

Call `finishFlow()` when the user has completed all sections and you won't be reusing the same `interviewId` again. `finishFlow()` signals the end of the session so it can be closed server-side.

```dart
IncodeOnboardingSdk.finishFlow();
```

`finishFlow()` is only required for section-based flows. Do not call it for flows started with `startOnboarding()`.

If you do not call `finishFlow()`, the session remains open on the server. This does not cause issues for subsequent sessions.
