Documentation Index Fetch the complete documentation index at: https://docs.didit.me/llms.txt
Use this file to discover all available pages before exploring further.
A lightweight, server-driven Android SDK for identity verification with minimal configuration required.
GitHub Repository View source code and examples on GitHub
Native SDK : This is the recommended approach for Android apps. Native SDKs provide the best user experience, optimized camera handling, and full NFC support.
Requirements
Requirement Minimum Version Android API 23+ (Android 6.0 Marshmallow) Kotlin 1.9+ Jetpack Compose Included as transitive dependency
Installation
Step 1: Add the Repository
Add the Didit Maven repository to the repositories block in your settings.gradle.kts:
dependencyResolutionManagement {
repositories {
google ()
mavenCentral ()
maven { url = uri ( "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" ) }
}
}
Or if using settings.gradle (Groovy):
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
}
}
Step 2: Add the Dependency
Add the SDK dependency to your app’s build.gradle.kts:
(!) Regarding the version ensure you check the GitHub repository for the latest version.
dependencies {
implementation ( "me.didit:didit-sdk:3.4.2" )
}
Or if using build.gradle (Groovy):
dependencies {
implementation "me.didit:didit-sdk:3.4.2"
}
Step 3: Add Packaging Exclusion
Add this to your app’s android block to avoid build conflicts:
android {
packaging {
resources {
excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
}
}
}
That’s it! Gradle will automatically resolve all transitive dependencies.
Permissions
The SDK requires the following permissions. These are declared in the SDK’s AndroidManifest.xml and will be merged automatically into your app’s manifest:
Permission Description Required INTERNETNetwork access for API communication ✅ Yes ACCESS_NETWORK_STATEDetect network availability ✅ Yes CAMERADocument scanning and face verification ✅ Yes NFCRead NFC chips in passports/ID cards ⚠️ If using NFC
Camera and NFC Features
The SDK declares android.hardware.camera and android.hardware.nfc as optional features (android:required="false"). This ensures your app can be installed on devices without a camera or NFC hardware — the SDK will gracefully handle missing hardware at runtime.
Quick Start
Step 1: Initialize the SDK
Initialize the SDK in your Application.onCreate():
import me.didit.sdk.DiditSdk
class MyApp : Application () {
override fun onCreate () {
super . onCreate ()
DiditSdk. initialize ( this )
}
}
Step 2: Start Verification and Handle Results
import me.didit.sdk.DiditSdk
import me.didit.sdk.DiditSdkState
import me.didit.sdk.VerificationResult
class MainActivity : ComponentActivity () {
override fun onCreate (savedInstanceState: Bundle ?) {
super . onCreate (savedInstanceState)
// Observe SDK state to launch UI when ready
lifecycleScope. launch {
DiditSdk.state. collect { state ->
when (state) {
is DiditSdkState.Ready -> DiditSdk. launchVerificationUI ( this@MainActivity )
is DiditSdkState.Error -> Log. e ( "Didit" , "Error: ${ state.message } " )
else -> { /* Loading, Idle, CreatingSession */ }
}
}
}
}
private fun startVerification () {
// Method 1: UniLink (no backend required)
DiditSdk. startVerification (
workflowId = "your-workflow-id" ,
vendorData = "user-123"
) { result ->
handleResult (result)
}
// Method 2: Backend Session (recommended for production)
// DiditSdk.startVerification(
// token = "your-session-token"
// ) { result ->
// handleResult(result)
// }
}
private fun handleResult (result: VerificationResult ) {
when (result) {
is VerificationResult.Completed -> {
Log. d ( "Didit" , "Session: ${ result.session.sessionId } " )
Log. d ( "Didit" , "Status: ${ result.session.status.rawValue } " )
}
is VerificationResult.Cancelled -> {
Log. d ( "Didit" , "User cancelled" )
}
is VerificationResult.Failed -> {
Log. e ( "Didit" , "Failed: ${ result.error.message } " )
}
}
}
}
Integration Methods
The SDK supports two integration methods:
Method 1: UniLink (Simplest)
No backend required. The SDK creates the session directly using your workflow ID from the Didit Console. Limited to vendorData only.
DiditSdk. startVerification (
workflowId = "your-workflow-id" ,
vendorData = "user-123"
) { result ->
handleResult (result)
}
Method 2: Backend Session (Recommended for Production)
Your backend creates the session via the Create Verification Session API (POST /v3/session/) with full parameter support (contact_details, expected_details, metadata, callback, etc.), then passes the session_token to the SDK.
// Your backend creates a session and returns the token
val sessionToken = yourBackend. createVerificationSession (userId = currentUser.id)
// Pass the token to the SDK
DiditSdk. startVerification (
token = sessionToken
) { result ->
handleResult (result)
}
This approach gives you full control over:
Associating sessions with your users (vendor_data)
Setting custom metadata
Configuring callbacks per session
Providing contact details and expected details for cross-validation
Configuration
Customize the SDK behavior:
import me.didit.sdk.Configuration
import me.didit.sdk.core.localization.SupportedLanguage
val configuration = Configuration (
languageLocale = SupportedLanguage.SPANISH, // Force Spanish language
fontFamily = "my_custom_font" , // Custom font (must be in res/font/)
loggingEnabled = true // Enable debug logging
)
DiditSdk. startVerification (
token = "your-session-token" ,
configuration = configuration
) { result ->
handleResult (result)
}
Configuration Options
Property Type Default Description languageLocaleSupportedLanguage?Device locale Force a specific language fontFamilyString?System font Custom font resource name (from res/font/) loggingEnabledBooleanfalseEnable SDK debug logging showCloseButtonBooleantrueShow close (X) button on verification step screens showExitConfirmationBooleantrueShow confirmation dialog when user attempts to exit closeOnCompleteBooleanfalseAuto-dismiss verification UI when complete (Web SDK equivalent: closeModalOnComplete)
Options showCloseButton, showExitConfirmation, and closeOnComplete match the Web SDK’s DiditSdkConfiguration. Mobile-specific options languageLocale and fontFamily exist because the mobile SDK renders the full verification UI natively (unlike the Web SDK which delegates to the hosted frontend inside an iframe).
Theming & Colors : Colors, backgrounds, and intro screen settings are configured through your White Label settings in the Didit Console, not in the SDK configuration. This ensures consistent branding across all platforms.
Language Support
The SDK supports 40+ languages . If no language is specified, the SDK uses the device locale with English as fallback.
// Use device locale (default)
val config = Configuration ()
// Force specific language
val config = Configuration (languageLocale = SupportedLanguage.FRENCH)
View All Supported Languages →
Advanced Options
For advanced session parameters (contact_details, expected_details, metadata, callback), use the Backend Session method. Your backend calls the Create Verification Session API with full parameters, then passes the session_token to the SDK.
Handling Results
The VerificationResult sealed class provides the outcome of the verification:
Result Cases
Case Description Completed(session)Verification flow completed (check session.status for result) Cancelled(session)User cancelled the verification flow Failed(error, session)An error occurred during verification
SessionData Properties
Property Type Description sessionIdStringUnique session identifier statusVerificationStatusAPPROVED, PENDING, or DECLINED
Error Types
Error Description SessionExpiredThe session has expired NetworkErrorNetwork connectivity issue CameraAccessDeniedCamera permission not granted NotInitializedSDK not initialized Unknown(message)Other error with message
Complete Result Handling Example
DiditSdk. startVerification (token = "your-token" ) { result ->
when (result) {
is VerificationResult.Completed -> {
when (result.session.status) {
VerificationStatus.APPROVED -> {
Log. d ( "Didit" , "Approved! Session: ${ result.session.sessionId } " )
// User is verified - grant access
}
VerificationStatus.PENDING -> {
Log. d ( "Didit" , "Under review. Session: ${ result.session.sessionId } " )
// Show "verification in progress" UI
}
VerificationStatus.DECLINED -> {
Log. d ( "Didit" , "Declined. Session: ${ result.session.sessionId } " )
// Handle declined verification
}
}
}
is VerificationResult.Cancelled -> {
Log. d ( "Didit" , "Cancelled: ${ result.session?.sessionId ?: "unknown" } " )
// User chose to cancel - maybe show retry option
}
is VerificationResult.Failed -> {
Log. e ( "Didit" , "Error: ${ result.error.message } " )
// Handle error - show retry or contact support
}
}
}
Observing SDK State
You can observe the SDK state for custom loading UI:
lifecycleScope. launch {
DiditSdk.state. collect { state ->
when (state) {
is DiditSdkState.Idle -> {
// Ready to start verification
}
is DiditSdkState.CreatingSession -> {
// Show "Creating session..." progress
}
is DiditSdkState.Loading -> {
// Show loading indicator
}
is DiditSdkState.Ready -> {
// Verification UI is ready - launch it
DiditSdk. launchVerificationUI ( this@MainActivity )
}
is DiditSdkState.Error -> {
// Show error message
Log. e ( "Didit" , "Error: ${ state.message } " )
}
}
}
}
ProGuard / R8
The SDK includes its own consumer ProGuard rules. No additional configuration is needed.
If you use R8 full mode, you may need to add this to your gradle.properties:
android.enableR8.fullMode =false
Complete Example
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import me.didit.sdk.Configuration
import me.didit.sdk.DiditSdk
import me.didit.sdk.DiditSdkState
import me.didit.sdk.VerificationResult
import me.didit.sdk.VerificationStatus
import me.didit.sdk.core.localization.SupportedLanguage
class MainActivity : ComponentActivity () {
override fun onCreate (savedInstanceState: Bundle ?) {
super . onCreate (savedInstanceState)
// Observe SDK state
lifecycleScope. launch {
DiditSdk.state. collect { state ->
when (state) {
is DiditSdkState.Ready -> DiditSdk. launchVerificationUI ( this@MainActivity )
is DiditSdkState.Error -> Log. e ( "Didit" , "Error: ${ state.message } " )
else -> { /* Idle, Loading, CreatingSession */ }
}
}
}
}
fun startVerification () {
val config = Configuration (
languageLocale = SupportedLanguage.ENGLISH,
loggingEnabled = true
)
// Method 1: UniLink (no backend required)
DiditSdk. startVerification (
workflowId = "your-workflow-id" ,
vendorData = "user-123" ,
configuration = config
) { result ->
handleResult (result)
}
// Method 2: Backend Session (recommended for production)
// DiditSdk.startVerification(
// token = "your-session-token",
// configuration = config
// ) { result ->
// handleResult(result)
// }
}
private fun handleResult (result: VerificationResult ) {
when (result) {
is VerificationResult.Completed -> {
when (result.session.status) {
VerificationStatus.APPROVED -> {
Log. d ( "Didit" , "Approved! Session: ${ result.session.sessionId } " )
}
VerificationStatus.PENDING -> {
Log. d ( "Didit" , "Under review" )
}
VerificationStatus.DECLINED -> {
Log. d ( "Didit" , "Declined" )
}
}
}
is VerificationResult.Cancelled -> {
Log. d ( "Didit" , "Cancelled: ${ result.session?.sessionId ?: "unknown" } " )
}
is VerificationResult.Failed -> {
Log. e ( "Didit" , "Error: ${ result.error.message } " )
}
}
}
}