# Configure Flows Locally and Run End to End

This is the standard integration pattern for the Incode Android SDK. It involves:

- Defining the onboarding flow locally in code with `FlowConfig`
- Implementing an `OnboardingListener` to receive results
- Running the session with one call to `startOnboarding()`

The SDK presents the Incode UI for each module in turn.

Use this integration pattern when you want full control over the flow in client code. If you prefer to define the flow in Dashboard instead, see [Run Flows Configured in Dashboard](https://developer.incode.com/docs/android-run-flows-configured-online). If you need to insert your own screens or logic between SDK modules, see [Configure Flows Locally and Run Step by Step](https://developer.incode.com/docs/android-configure-flows-locally-and-run-step-by-step). For more information about these patterns, see [Common Integration Approaches](https://developer.incode.com/docs/android-common-implementation-patterns#integration-patterns).

This page covers session creation and section execution only. Ensure you have followed the steps to [Install and Initialize](https://developer.incode.com/docs/android-installation) the Incode Android SDK first.

***

## Imports and Package Paths

The snippets below use short class names. The full package paths are:

- `com.incode.welcome_sdk`: Entry point and core classes, including `IncodeWelcome`, `FlowConfig`, and `SessionConfig`.
- `com.incode.welcome_sdk.modules`: Module config classes, such as `IdScan`, `SelfieScan`, and `FaceMatch`.
- `com.incode.welcome_sdk.results`: Result types, such as `IdScanResult`, `SelfieScanResult`, and `FaceMatchResult`.

`OnboardingListener` is a nested class. Import it as `IncodeWelcome.OnboardingListener`. See [API Reference](https://developer.incode.com/docs/android-api-reference) for the full package layout.

***

## Set Up This Integration Pattern

The pattern uses four objects and one call: initialize the SDK, build a `FlowConfig`, create an `OnboardingListener`, and call `startOnboarding()`.&#x20;

`startOnboarding()` requires a `SessionConfig` argument: Its contents are optional; pass `SessionConfig.Builder().build()` if you don't need to customize the session. `CommonConfig` is a separate optional customization. Both are covered below.

### Build a Flow Configuration

In the `Activity` where you want to show the onboarding UI, build a `FlowConfig` inside `onCreate()`. Add the modules you want in the flow:

```kotlin
val flowConfig: FlowConfig = FlowConfig.Builder()
    .addPhone()
    .addID(IdScan.Builder()
        .setIdType(IdScan.IdType.ID)
        .setShowIdTutorials(true)
        .setWaitForTutorials(true)
        .build())
    .addProcessId(ProcessId.Builder().build())
    .addDocumentScan(DocumentScan.Builder().build())
    .addGeolocation()
    .addSelfieScan(SelfieScan.Builder().build())
    .addFaceMatch()
    .addUserConsent(UserConsent.Builder().build())
    .addSignature()
    .addCaptcha()
    .addVideoSelfie()
    .addConference()
    .build()
```
```java
FlowConfig flowConfig = new FlowConfig.Builder()
        .addPhone()
        .addID(new IdScan.Builder()
            .setIdType(IdScan.IdType.ID)
            .setShowIdTutorials(true)
            .setWaitForTutorials(true)
            .build())
        .addProcessId(new ProcessId.Builder().build())
        .addDocumentScan(new DocumentScan.Builder().build())
        .addGeolocation()
        .addSelfieScan(new SelfieScan.Builder().build())
        .addFaceMatch()
        .addUserConsent(new UserConsent.Builder().build())
        .addSignature()
        .addCaptcha()
        .addVideoSelfie()
        .addConference()
        .build();
```

This creates a `FlowConfig` with all the modules you want in the onboarding flow. Omitted modules are not shown. Modules appear in the order you add them to the builder.

<Callout icon="❗" theme="error">
  ### Warning

  Some modules are mandatory. Some modules have order dependencies. For example, every onboarding flow needs the [ID Scan](https://developer.incode.com/docs/android-id-scan) and [Selfie Scan](https://developer.incode.com/docs/android-selfie-scan) modules, and the Results module must come after modules that add or process data. If any of these rules are broken, `FlowConfig.Builder.build()` throws `ModuleConfigurationException`.
</Callout>

Each module has its own configuration options exposed through its `Builder` class. See each page in the [Individual Modules](doc:individual-modules) catalog for details.

A few general notes:

- Some modules require a module config instance obtained and customized through the module's `Builder` class. For example, `IdScan.Builder().build()` for the ID Scan module.
- Some modules show tutorials by default. Disable them by calling `setShowTutorials(false)` on the builder.

See [API Reference](https://developer.incode.com/docs/android-api-reference) for the complete `FlowConfig` specification.

### Create a Callback to Receive SDK Results

Implement an `OnboardingListener` to receive results from each module and from the overall flow:

```kotlin
val onboardingListener: OnboardingListener = object : OnboardingListener() {
    override fun onOnboardingSessionCreated(token: String?, interviewId: String?, region: String) {
        // Onboarding Session Created successfully
    }

    override fun onIntroCompleted() {
        // Intro screen completed
    }

    override fun onAddPhoneCompleted(phoneNumberResult: PhoneNumberResult) {
        // Add phone completed
    }

    override fun onQRScanCompleted(qrScanResult: QRScanResult) {
        // QR scan completed
    }

    override fun onIdFrontCompleted(frontIdScanResult: IdScanResult) {
        // Scanning the front of an ID completed
    }

    override fun onIdBackCompleted(backIdScanResult: IdScanResult) {
        // Scanning the back of an ID completed
    }

    override fun onIdProcessed(idProcessResult: IdProcessResult) {
        // ID Validation completed
    }

    override fun onNfcScanCompleted(nfcScanResult: NfcScanResult) {
        // NFC scan completed
    }

    override fun onDocumentValidationCompleted(
        documentType: DocumentType,
        result: DocumentValidationResult
    ) {
        // Document validation completed
    }

    override fun onSelfieScanCompleted(selfieScanResult: SelfieScanResult) {
        // Selfie scan completed
    }

    override fun onFaceMatchCompleted(faceMatchResult: FaceMatchResult) {
        // Face match completed
    }

    override fun onSignatureCollected(signatureFormResult: SignatureFormResult) {
        // Signature collected
    }

    override fun onUserConsentCompleted() {
        // User consent complete
    }

    override fun onVideoRecorded(videoSelfieResult: VideoSelfieResult) {
        // Video selfie finished successfully
    }

    override fun onCaptchaCollected(captchaResult: CaptchaResult) {
        // Captcha collected
    }

    override fun onGeolocationFetched(geolocationResult: GeolocationResult) {
        // Geolocation collected
    }

    override fun onApproveCompleted(approveResult: ApproveResult) {
        // User's onboarding approval completed
    }

    override fun onResultsShown(userScoreResult: UserScoreResult) {
        // Results shown to the user
    }

    override fun onQueuePositionChanged(newQueuePosition: Int) {
        // Queue position for the video call changed
    }

    override fun onEstimatedWaitingTime(waitingTimeInSeconds: Int) {
        // Called only once with the estimated waiting time in the queue. Waiting time is in seconds.
    }

    override fun onConferenceEnded() {
        // Called when the video conference has ended
    }

    override fun onSuccess() {
        // User successfully finished whole onboarding flow
    }

    override fun onError(error: Throwable) {
        // Onboarding flow was aborted due to error
    }

    override fun onUserCancelled() {
        // User cancelled the flow
    }
}
```
```java
OnboardingListener onboardingListener = new IncodeWelcome.OnboardingListener() {
    @Override
    public void onOnboardingSessionCreated(@Nullable String token, @Nullable String interviewId, @NonNull String region) {
        // Onboarding Session Created successfully
    }

    @Override
    public void onIntroCompleted() {
        // Intro screen completed
    }

    @Override
    public void onAddPhoneCompleted(@NonNull PhoneNumberResult phoneNumberResult) {
        // Add phone completed
    }

    @Override
    public void onQRScanCompleted(@NonNull QRScanResult qrScanResult) {
        // QR scan completed
    }

    @Override
    public void onIdFrontCompleted(@NonNull IdScanResult frontIdScanResult) {
        // Scanning the front of an ID completed
    }

    @Override
    public void onIdBackCompleted(@NonNull IdScanResult backIdScanResult) {
        // Scanning the back of an ID completed
    }

    @Override
    public void onIdProcessed(@NonNull IdProcessResult idProcessResult) {
        // ID Validation completed
    }

    @Override
    public void onNfcScanCompleted(@NonNull NfcScanResult nfcScanResult) {
        // NFC scan completed
    }

    @Override
    public void onDocumentValidationCompleted(@NonNull DocumentType documentType, @NonNull DocumentValidationResult result) {
        // Document validation completed
    }

    @Override
    public void onSelfieScanCompleted(@NonNull SelfieScanResult selfieScanResult) {
        // Selfie scan completed
    }

    @Override
    public void onFaceMatchCompleted(@NonNull FaceMatchResult faceMatchResult) {
        // Face match completed
    }

    @Override
    public void onSignatureCollected(@NonNull SignatureFormResult signatureFormResult) {
        // Signature collected
    }

    @Override
    public void onUserConsentCompleted() {
        // User consent complete
    }

    @Override
    public void onVideoRecorded(@NonNull VideoSelfieResult videoSelfieResult) {
        // Video selfie finished successfully
    }

    @Override
    public void onCaptchaCollected(@NonNull CaptchaResult captchaResult) {
        // Captcha collected
    }

    @Override
    public void onGeolocationFetched(@NonNull GeolocationResult geolocationResult) {
        // Geolocation collected
    }

    @Override
    public void onApproveCompleted(@NonNull ApproveResult approveResult) {
        // User's onboarding approval completed
    }

    @Override
    public void onResultsShown(@NonNull UserScoreResult userScoreResult) {
        // Results shown to the user
    }

    @Override
    public void onQueuePositionChanged(int newQueuePosition) {
        // Queue position for the video call changed
    }

    @Override
    public void onEstimatedWaitingTime(int waitingTimeInSeconds) {
        // Called only once with the estimated waiting time in the queue. Waiting time is in seconds.
    }

    @Override
    public void onConferenceEnded() {
        // Called when the video conference has ended
    }

    @Override
    public void onSuccess() {
        // User successfully finished whole onboarding flow
    }

    @Override
    public void onError(@NonNull Throwable error) {
        // Onboarding flow was aborted due to error
    }

    @Override
    public void onUserCancelled() {
        // User cancelled the flow
    }
};
```

For the shape and fields of each result object, see [Results](https://developer.incode.com/docs/android-results-reference).

The SDK has multiple exit paths. Call `IncodeWelcome.deleteUserLocalData(context)` after the flow ends to delete all local user data. This is a static method that takes a `Context`. Call `deleteUserLocalData()` in these callbacks:

```kotlin
fun onSuccess()
fun onError(error: Throwable)
fun onUserCancelled()
```
```java
public void onSuccess()
public void onError(Throwable error)
public void onUserCancelled()
```

### Start the Onboarding Process

After creating the `FlowConfig` and `OnboardingListener` objects, start your session by calling `startOnboarding()`. The only signature is `startOnboarding(context, sessionConfig, flowConfig, onboardingListener)`, so a `SessionConfig` argument is **required**. Its contents are optional. If you don't need to bind a Dashboard flow, resume a session, or set custom fields, pass an empty `SessionConfig.Builder().build()`. See [Session Configuration](#session-configuration) below for customization options.

```kotlin
val sessionConfig: SessionConfig = SessionConfig.Builder().build() // or a customized SessionConfig (see below)
IncodeWelcome.getInstance().startOnboarding(activityContext, sessionConfig, flowConfig, onboardingListener)
```
```java
SessionConfig sessionConfig = new SessionConfig.Builder().build(); // or a customized SessionConfig (see below)
IncodeWelcome.getInstance().startOnboarding(activityContext, sessionConfig, flowConfig, onboardingListener);
```

See [API Reference](https://developer.incode.com/docs/android-api-reference) for the complete specification of the `startOnboarding()` method and the `OnboardingListener` interface.

***

## Optional Configuration

These two configuration objects are optional. Use them to bind a Dashboard flow, resume a session, or adjust thresholds and UX behaviors.

### Session Configuration

Customize the onboarding session by creating a `SessionConfig`. Use these `SessionConfig.Builder` APIs:

| API                       | Description                                                                                                                                                                                         |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `setConfigurationId`      | Specifies the flow ID from Dashboard to use the configurations applied to that flow. You still must add onboarding steps via `FlowConfig` to display the flow to the user.                          |
| `setValidationModuleList` | Sets the list of onboarding validation modules used for user scoring and approval. Defaults to `id`, `liveness`, `faceRecognition`.                                                                 |
| `setCustomFields`         | Provides a list of custom fields stored for this session.                                                                                                                                           |
| `setInterviewId`          | Specifies the ID of the onboarding session. Use to resume an existing session.                                                                                                                      |
| `setExternalToken`        | Specifies the JSON Web Token (JWT) of the onboarding session. Use to resume an existing session.                                                                                                    |
| `setExternalId`           | Sets an ID used outside of the Incode Platform. If the first session is interrupted and a session with the same `externalId` already exists, that session is resumed instead of creating a new one. |
| `setExternalCustomerId`   | Sets an ID similar to `setExternalId`, but always creates a new session if interrupted, even if a session with the same `externalCustomerId` already exists.                                        |
| `setQueueName`            | Specifies the queue the user enters after the flow completes when using the Conference module. If none is specified, the user goes to the default queue.                                            |

```kotlin
val sessionConfig: SessionConfig = SessionConfig.Builder()
    .setConfigurationId("xxxxxxxxxxxxxxxx")
    .build()
```
```java
SessionConfig sessionConfig = new SessionConfig.Builder()
    .setConfigurationId("xxxxxxxxxxxxxxxx")
    .build();
```

To resume an existing session, for example one started API to API:

```kotlin
val sessionConfig = SessionConfig.Builder()
    .setInterviewId(...)
    .build()
```
```java
SessionConfig sessionConfig = new SessionConfig.Builder()
    .setInterviewId(...)
    .build();
```

### Common Configuration

Customize thresholds or UX behaviors by creating a `CommonConfig`. Use these `CommonConfig.Builder` APIs:

| API                                   | Description                                                                                                                    |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `setShowCloseButton`                  | Shows or hides the close button on all screens. Hidden by default.                                                             |
| `setShowExitConfirmation`             | Shows or hides a dialog asking a user to confirm they want to leave the flow after pressing the back button. Shown by default. |
| `setShowDelayedOnboardingIntroScreen` | Shows or hides the introduction screen when the SDK starts in Delayed mode. Shown by default.                                  |

<Callout icon="📘" theme="info">
  ### Note

  Only on-device thresholds get overridden by calling the APIs above.
</Callout>

```kotlin
val commonConfig = CommonConfig.Builder()
    .setShowCloseButton(...)
    .setShowExitConfirmation(...)
    .setShowDelayedOnboardingIntroScreen(...)
    .build()

IncodeWelcome.getInstance().setCommonConfig(commonConfig)
```
```java
CommonConfig commonConfig = new CommonConfig.Builder()
        .setShowCloseButton(...)
        .setShowExitConfirmation(...)
        .setShowDelayedOnboardingIntroScreen(...)
        .build();

IncodeWelcome.getInstance().setCommonConfig(commonConfig);
```

<br />
