Using Standard Mobile SDK

Integrate the IDWise Standard SDK into your mobile app or web application to start, monitor, and resume ID verification journeys.

Introduction

Integrate the IDWise Standard SDK into your mobile app or web application to start, monitor, and resume ID verification journeys.

Use the Standard SDK when you want IDWise to manage the full verification UI and journey flow inside your app.

Requirements

Before you start:

  1. Install the IDWise SDK for your target platform by following the SDK integration requirements and installation guide.
  2. Generate your clientKey by following the SDK authentication guide.
  3. Get the flowId for the journey flow you want to launch from IDWise Studio.

AI integration prompt

IDWise Standard SDK Integration Prompt

AI Prompt

Copy this prompt into your AI coding assistant (Cursor, Claude Code, Copilot, etc.) to integrate the IDWise Standard SDK into your project. Replace [PLATFORM] with Android, iOS, Flutter, React Native, Cordova, or Capacitor.

View Integration Prompt
You are an expert mobile SDK integration engineer.

I am integrating the IDWise Standard SDK into the project this prompt is pasted in.
Detect the platform (Android / iOS / Flutter / React Native) from the project. If signals are mixed or ambiguous, ask before continuing.

## Source-of-truth docs (use these exact pages — don't substitute)
- Standard SDK runtime: https://docs.idwise.com/docs/simple-sdk
- Install / build setup index: https://docs.idwise.com/docs/sdk-integration-1 → follow the platform-specific child page
- Latest version: pull from the platform's release-notes page on docs.idwise.com (Android, iOS, Flutter, React Native each have one). Use the latest entry — do not leave a `<VERSION>` placeholder.

## Hard rules

1. **Implement every abstract member** of the journey-callbacks interface, even ones the docs don't list. A compile error of the form "does not implement abstract member X" means X exists and must be implemented — do not work around it.
2. **Do not invent methods.** If something I asked for isn't exposed by the resolved artifact, say so explicitly and stop — do not fabricate a signature.
3. **Not done until it builds.** Run the platform build, fix until zero compile errors, and paste the final command + last ~10 lines of output as proof.

## Ask before guessing

If any of the following are unclear from the project, ask me — do not assume:
- Which screen / button / action should trigger `startJourney` (and `resumeJourney` if applicable). If multiple candidates exist, list them.
- Whether to wire `resumeJourney` at all, or only `startJourney`.
- Where init should live (app entry point vs. lazy-init at first journey).
- Whether to persist `journeyId` for resume across app restarts, or keep in memory only.
- Whether the host app already has a runtime-permissions pattern I should match before I add my own.
- Any applicant-details fields I should populate beyond the SDK-required minimum.

Group related questions into one round.

## What to deliver

### A. Build setup
- Add IDWise repositories / package sources.
- Dependency at the actual latest version from the release-notes page.
- Required build flags from the install page (e.g. on Android: `multiDexEnabled`, `dataBinding`, min/target SDK).
- Camera permission entries:
  - Android: `<uses-permission android:name="android.permission.CAMERA"/>` + `<uses-feature android:name="android.hardware.camera"/>`
  - iOS: `NSCameraUsageDescription` (plus microphone/photo if applicable)
  - Flutter / RN: both of the above in their platform folders
- Register the Application / AppDelegate / plugin entry-point if init lives there.

### B. Runtime integration
1. SDK initialization with `<YOUR_CLIENT_KEY>`, theme, onSuccess, onError — at app start.
2. Start a new journey with `<FLOW_ID>`, `<REFERENCE_NUMBER>`, locale, applicant details, journey callbacks. 
3. Resume an unfinished journey with `<FLOW_ID>`, `<JOURNEY_ID>`, locale, journey callbacks.
4. Full implementation of every journey callback (started / resumed / completed / cancelled / blocked / error / any others the interface declares), each logging the full info payload.
5. Runtime camera-permission request before launching a journey, on platforms that require it.
6. Persist `journeyId` from `onJourneyStarted` so resume is wired end-to-end.

### C. Placeholders to keep verbatim
- `<YOUR_CLIENT_KEY>` — in init only
- `<FLOW_ID>` — as a constant
- `<REFERENCE_NUMBER>` — as a constant
- `<JOURNEY_ID>` — fallback when no stored id exists

### D. Execution & report
Apply the changes directly to the project — edit the actual files, do not just print snippets. At minimum:
- App entry point (Application / AppDelegate / plugin init) — created or modified.
- The screen / action that triggers the journey — wired up.
- Manifest / Info.plist — permission and entry-point registrations added.
- Dependency / build-config files — repositories, dependency line, required flags added.

After applying changes, report:
- Short platform checklist of what was done.
- List of files created / modified, with a one-line note on each.
- One sentence per callback on where it connects in the app lifecycle.
- Final build command and last ~10 lines of its output, as proof of a green build.

Full integration sequence diagram

This sequence diagram shows the steps performed after integrating the Standard SDK with your mobile app or web application.

Standard SDK integration sequence diagram

SDK usage

Use these methods to interact with the IDWise Standard SDK from your app.

1. Import the SDK

You can import the SDK into your code file as follows:

import com.idwise.sdk.IDWise
import com.idwise.sdk.data.models.*
import com.idwise.sdk.IDWiseJourneyCallbacks
import IDWiseSDK

// If using the NFC SDK, import this instead
import IDWiseNFC
import 'package:idwise_flutter_sdk/idwise.dart';
// If using the NFC SDK, import this instead
import 'package:idwise_nfc_flutter_sdk/idwise.dart';
import {IDWise} from 'idwise-react-native-sdk/src/IDWise';
import {IDWiseTheme} from 'idwise-react-native-sdk/src/IDWiseConstants';

// If using the NFC SDK, import this instead
import {IDWise} from 'idwise-nfc-react-native-sdk/src/IDWise';
import {IDWiseTheme} from 'idwise-nfc-react-native-sdk/src/IDWiseConstants';
There is no need to Import SDK in Capacitor

2. Initialize the SDK

To use the SDK features, you have to initialize it first by calling the following method:

val clientKey = "<YOUR_CLIENT_KEY>"
val theme = IDWiseTheme.SYSTEM_DEFAULT //[LIGHT, DARK, SYSTEM_DEFAULT]

 IDWise.initialize(
   clientKey = clientKey,
   theme = theme,
   onSuccess = {
      Log.d("IDWiseSDKCallback", "initialize Success") 
   },
   onError = { error: IDWiseError? ->
     // handle error, show some alert or any other logic
		Log.d("IDWiseSDKCallback", "initialize error: $error")
   }
 )
let clientKey = "<YOUR_CLIENT_KEY>"
let theme = IDWiseTheme.systemDefault //[.light, .dark, .systemDefault]

IDWise.initialize(clientKey: clientKey,theme: theme, onSuccess: {
       print("SDK Initialized Successfully")
  }, onError: { err in
       if let error = err {
        // handle error, show some alert or any other logic
       }
  })
String clientKey = "<YOUR_CLIENT_KEY>"
IDWiseTheme theme = IDWiseTheme.LIGHT //[DARK, LIGHT, SYSTEM_DEFAULT]

IDWise.initialize(
  clientKey: clientKey,
  theme: theme,
  onSuccess: () {
     print("SDK Initialized Successfully");
  },
  onError: (error) {
      print("onError in _idwiseFlutterPlugin: $error");
  });
const clientKey = "<YOUR_CLIENT_KEY>";
const theme = IDWiseTheme.SYSTEM_DEFAULT; //[LIGHT, DARK, SYSTEM_DEFAULT]

IDWise.initialize(clientKey, theme, {
 onSuccess() {
      console.log('Event onInitializeSuccess');
  },
  onError(error) {
      console.log(' onInitializeError: ', error);
  }
});
function error(error) {
   //error callback for errors occurred in initialize
    console.log(
      "onError :",
      error.code,
      error.message
    );
}

var clientKey = "<YOUR_CLIENT_KEY>"; //provided by IDWise
var theme = "SYSTEM_DEFAULT"; //available values: LIGHT, DARK, SYSTEM_DEFAULT

IDWise.initialize(clientKey, theme, error);

initialize method takes two parameters and an onError callback which will be triggered if an error occurred during initialisation:

  • clientKey: A key used to authenticate your app with the IDWise backend. You can generate this key by following the instructions here.
  • theme: is an enum to indicate the theme (Light or Dark) to use for IDWise's UI.

3. Start a new journey

Once the SDK is initialized, it becomes ready to start an ID verification journey flow. To commence the flow, the SDK offers a startJourney method, as demonstrated below.

val flowId = "<FLOW_ID>"
val referenceNo = "<REFERENCE_NUMBER>"
val locale = "en"

val applicantDetails = hashMapOf<String, String>()
applicantDetails[ApplicantDetailsKeys.FULL_NAME] = "John Doe"
applicantDetails[ApplicantDetailsKeys.BIRTH_DATE] = "2000-02-13"
applicantDetails[ApplicantDetailsKeys.SEX] = "male"
applicantDetails[ApplicantDetailsKeys.ADDRESS] = "Apartment Number, Building Name, Building Number, Street Name, Suburb, City, District, Postal Code, State, Country"


IDWise.startJourney(
  application = application,
  flowId = flowId,
  locale = locale,
  referenceNo = referenceNo,
  applicantDetails = applicantDetails, //Optional
  journeyCallbacks = journeyCallbacks
)
let flowId = "<FLOW_ID>"
let referenceNo = "<REFERENCE_NUMBER>"
let locale = "en"
let applicantDetails: [String:String] = [
            ApplicantDetailsKeys.FULL_NAME: "John Doe",
            ApplicantDetailsKeys.BIRTH_DATE: "2000-02-13",
            ApplicantDetailsKeys.SEX: "male",
            ApplicantDetailsKeys.ADDRESS: "Apartment Number, Building Name, Building Number, Street Name, Suburb, City, District, Postal Code, State, Country",
            ApplicantDetailsKeys.COUNTRY_CODE: "USA"
        ]

IDWise.startJourney(flowId: flowId,
                    referenceNumber: referenceNo,
                    locale: locale,
                    applicantDetails: applicantDetails, // can be passed as nil If you don't want to pass any applicant details
                    journeyCallbacks: self)
String flowId = "<FLOW_ID>"
String referenceNo = "<REFERENCE_NUMBER>";
String locale = "en";

Map<String, String> applicantDetails = HashMap();
applicantDetails["full_name"] = "John Doe";
applicantDetails["birth_date"] = "2000-02-13";
applicantDetails["sex"] = "male";
applicantDetails["address"] = "Apartment Number, Building Name, Building Number, Street Name, Suburb, City, District, Postal Code, State, Country";

IDWise.startJourney(
  flowId: flowId,
  referenceNo: referenceNo,
  locale: locale,
  applicantDetails: applicantDetails, //Optional
  journeyCallbacks: _journeyCallbacks);
var flowId = "<FLOW_ID>"
var referenceNo = "<REFERENCE_NUMBER>"
var locale = "en"

const applicantDetails = {};
applicantDetails[ApplicantDetailsKeys.FULL_NAME] = 'John Doe';
applicantDetails[ApplicantDetailsKeys.BIRTH_DATE] = "2000-02-13";
applicantDetails[ApplicantDetailsKeys.SEX] = 'male';
applicantDetails[ApplicantDetailsKeys.ADDRESS] = 'Apartment Number, Building Name, Building Number, Street Name, Suburb, City, District, Postal Code, State, Country';

IDWise.startJourney(
  flowId,
  referenceNo,
  locale,
  applicantDetails, //Optional. Can pass Null if not needed
  journeyCallbacks
);
var flowId = "<FLOW_ID>"
var referenceNo = "<REFERENCE_NUMBER>"
var locale = "en"

const applicantDetails = {};
applicantDetails[ApplicantDetailsKeys.FULL_NAME] = 'John Doe';
applicantDetails[ApplicantDetailsKeys.BIRTH_DATE] = "2000-02-13";
applicantDetails[ApplicantDetailsKeys.SEX] = 'male';
applicantDetails[ApplicantDetailsKeys.ADDRESS] = 'Apartment Number, Building Name, Building Number, Street Name, Suburb, City, District, Postal Code, State, Country';

IDWise.startJourney(
  flowId,
  referenceNo, 
  locale, 
  applicantDetails,//optional
  journeyCallbacks
);

This method takes the following parameters:

  • flowId: This is a unique identifier that identifies your journey flow. You can get access to all your flows from here .
  • referenceNo: (Optional) This parameter allows you to attach a unique identifier (such as a reference number) with the user undergoing the current journey. It's beneficial for connecting the journey to the user and/or the application that initiated it. You will receive this reference number in the webhook request.
  • locale (Optional): This parameter specifies the ISO code for the desired language of the SDK's user interface screens. If not provided, English will be used as the default language. For a list of available languages, adding additional languages, please contact IDWise Support or you can add additional languages via IDWise Theme Designer.
  • applicantDetails:(Optional) This parameter allows you to pass applicantDetails which is Information about the applicant. If you don't want to pass any applicantDetails then you can just pass nil.
  • journeyCallbacks: This parameter is used to provide a set of event handlers to handle the different events that are triggered from IDWise SDK. These events indicate the lifetime of a journey and provide an opportunity for your application to react to certain journey events.This is the object for call-back events. These events are described below:

4. Handle journey callbacks

During the journey, you can subscribe to these events to get the updates:

val journeyCallbacks = object : IDWiseJourneyCallbacks {
        override fun onJourneyStarted(journeyStartedInfo: JourneyStartedInfo) {
          Log.d("IDWiseSDKCallback", "onJourneyStarted $journeyStartedInfo")
        }
        
         override fun onJourneyCompleted(journeyCompletedInfo: JourneyCompletedInfo) {
             Log.d("IDWiseSDKCallback", "onJourneyCompleted $journeyCompletedInfo")
        }
         
        override fun onJourneyResumed(journeyResumedInfo: JourneyResumedInfo) {
             Log.d("IDWiseSDKCallback", "onJourneyResumed $journeyResumedInfo")
        }
    
        override fun onJourneyCancelled(journeyCancelledInfo: JourneyCancelledInfo) {
             Log.d("IDWiseSDKCallback", "onJourneyCancelled $journeyCancelledInfo")
        }

        override fun onJourneyBlocked(journeyBlockedInfo: JourneyBlockedInfo) {
             Log.d("IDWiseSDKCallback", "onJourneyBlocked $journeyBlockedInfo")
        }
        
        override fun onError(error: IDWiseError) {
            Log.d("IDWiseSDKCallback", "onError $error")
        }
    }
extension ViewController:IDWiseJourneyCallbacks {
   func onJourneyStarted(journeyStartedInfo: JourneyStartedInfo) {
        print("IDWiseSDKCallback", "onJourneyStarted")
     }
  
   func onJourneyCompleted(journeyCompletedInfo: JourneyCompletedInfo) { 
        print("IDWiseSDKCallback", "onJourneyCompleted")
     }
  
   func onJourneyResumed(journeyResumedInfo: JourneyResumedInfo) {
        print("IDWiseSDKCallback", "onJourneyResumed")
     }
 
   func onJourneyCancelled(journeyCancelledInfo: JourneyCancelledInfo) {
        print("IDWiseSDKCallback", "onJourneyCancelled")
     }
  
   func onJourneyBlocked(journeyBlockedInfo: JourneyBlockedInfo) {
        print("IDWiseSDKCallback", "onJourneyBlocked")
     }
 
   func onError(error : IDWiseError) { 
       print("IDWiseSDKCallback", "onError \(error.message)")
     }
}
IDWiseJourneyCallbacks _journeyCallbacks = IDWiseJourneyCallbacks(
    onJourneyStarted: (dynamic journeyStartedInfo) {
      print("IDWiseSDKCallback: onJourneyStarted, $journeyStartedInfo");
    },
  
    onJourneyCompleted: (dynamic journeyCompletedInfo){
        print("IDWiseSDKCallback: onJourneyCompleted: $journeyCompletedInfo");
    },
  
    onJourneyCancelled: (dynamic journeyCancelledInfo) {
        print("IDWiseSDKCallback: onJourneyCancelled: $journeyCancelledInfo");
    },
  
    onJourneyResumed: (dynamic journeyResumedInfo) {
      print("IDWiseSDKCallback: onJourneyResumed, ${journeyResumedInfo["journeyId"]}");
    },

    onJourneyBlocked: (dynamic journeyBlockedInfo) {
      print("IDWiseSDKCallback: onJourneyBlocked, $journeyBlockedInfo");
    },
  
    onError: (dynamic error) {
      print("onError $error");
    }
  );
const journeyCallbacks = {
  onJourneyStarted(journeyStartedInfo) {
    console.log('onJourneyStarted:', journeyStartedInfo);
  },
  onJourneyResumed(journeyResumedInfo) {
    console.log('onJourneyResumed:', journeyResumedInfo);
  },
  onJourneyCompleted(journeyCompletedInfo) {
    console.log('onJourneyCompleted:', journeyCompletedInfo);
  },
  onJourneyCancelled(journeyCancelledInfo) {
    console.log('onJourneyCancelled:', journeyCancelledInfo);
  },
  onJourneyBlocked(journeyBlockedInfo) {
    console.log('onJourneyBlocked:', journeyBlockedInfo);
  },
  onError(error) {
    console.log('onError:', error);
  },
};
const journeyCallbacks = {
    onJourneyStarted(journeyStartedInfo) {
      console.log(`Journey Started with id ${journeyStartedInfo.journeyId}`);
    },
    onJourneyResumed(journeyResumedInfo) {
      console.log(`Journey Resumed with id ${journeyResumedInfo.journeyId}`);
    },
    onJourneyCompleted(journeyCompletedInfo) {
      console.log(`Journey Finished with id ${journeyCompletedInfo.journeyId}`);
    },
    onJourneyCancelled(journeyCancelledInfo) {
      console.log(`Journey Cancelled with id ${journeyCancelledInfo.journeyId}`);
    },
    onJourneyBlocked(journeyBlockedInfo) {
      console.log(`Journey Blocked with id ${journeyBlockedInfo.journeyId}`);
    },
    onError(error) {
      console.log(
        "Event onJourneyError received:",
        error.code,
        error.message
      );
    },
};

Journey callbacks are detailed below:

callbackNameDescriptionObject Payload
onJourneyStartedTriggered when a user’s journey begins (after calling startJourney and the journey is created). At this point, the UI control is transferred to the IDWise SDK. Your app should hide any loading indicators and pause showing any UI until the SDK returns control.JourneyStartedInfo object:
journeyId (String): The journey ID created by calling the startJourney method.
onJourneyResumedTriggered when a journey is resumed (after calling resumeJourney and the journey is ready). The UI control is now with the IDWise SDK, and your app should hide spinners and UI elements until control is returned.JourneyResumedInfo object:
journeyId (String): The resumed journey ID.
onJourneyCompletedTriggered when the user finishes all steps in the journey. Control is returned to your application and the SDK UI is dismissed. The journey may still be processing on the backend (e.g., fraud checks), so expect a delay before receiving the final webhook.JourneyCompletedInfo object:
journeyId (String): The completed journey ID.
onJourneyCancelledTriggered when the user presses the cancel button or system back button or when the session expires. The SDK UI is hidden, and control is returned to your app. You may prompt the user to resume and complete the journey later.JourneyCancelledInfo object:
journeyId (String): The cancelled journey ID.
cancellationReason (String): indicates the reason for cancellation. the possible values for reason are: user_cancelled or token_expired
onJourneyBlockedTriggered when the journey is blocked and control is returned to your app.JourneyBlockedInfo object.
onErrorTriggered when an error occurs during the journey. Your app should handle this by responding to known error cases. Unexpected errors should be logged along with the error code and message for IDWise Support. Error code documentationErrorInfo object:
errorCode (String): Machine-readable error code.
errorMessage (String): Human-readable message describing the error.

5. Resume a journey

If you want to resume an unfinished journey, you can do so as below:

val flowId = "<FLOW_ID>"
val locale = "en"
val journeyId = "<JOURNEY_ID>"

IDWise.resumeJourney(
  application = application,
  journeyId = journeyId,
  flowId = flowId,
  locale = locale,
  journeyCallbacks = journeyCallbacks
)
let flowId = "<FLOW_ID>"
let journeyId = "<JOURNEY_ID>"
let locale = "en"

 IDWise.resumeJourney(flowId: flowId,
                      journeyId: journeyId,
                      locale: locale,
                      journeyCallbacks: self)
String flowId = "<FLOW_ID>"
String locale = "en";
String journeyId = "<JOURNEY_ID>";

IDWise.resumeJourney(
  flowId,
  journeyId,
  locale, 
  journeyCallbacks
);
var flowId = "<FLOW_ID>"
var journeyId = "<JOURNEY_ID>";
var locale = "en"

IDWise.resumeJourney(
  flowId,
  journeyId,
  locale,
  journeyCallbacks
);
var flowId = "<FLOW_ID>"
var journeyId = "<JOURNEY_ID>"
var locale = "en"

IDWise.resumeJourney(flowId, journeyId, locale, journeyCallbacks);

This method takes the following parameters:

  • flowId: This is a unique identifier for your journey flow. The flowId must match the flowId from which the journeyId was created. You can access all your flows from here .

  • journeyId: This is a unique identifier that identifies your journey and it can be used to resume. This is received in the implementation of IDWiseSDKJourneyDelegate interface in onJourneyStarted method when you started the journey the first time.

  • locale :(Optional) Language code of the language to be used to display the journey user interface. This is either an ISO 639-1 (2-letter for example en, ar or 3-letter for example ckb) or IETF BCP 47 (2-letter plus extended language specified for example zh-HK or zh-CN). You can know the locale code for the language by referring to it from IDWise Studio > Theme Designer > Content Management section.

  • journeyCallbacks: This parameter is used to provide a set of event handlers to handle the different events that are triggered from IDWise SDK. These events indicate the lifetime of a journey and provide opportunity for your application to react to certain events.

    Once journey resumes from the backend, the onJourneyResumed call-back from IDWiseJourneyCallbacks will be invoked.


Optional: Sample projects

Use these sample projects as platform-specific references for the Standard SDK integration: