Skip to main content

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

Requirements

RequirementMinimum Version
Android API23+ (Android 6.0 Marshmallow)
Kotlin1.9+
Jetpack ComposeIncluded 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:
PermissionDescriptionRequired
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: 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)
}
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

PropertyTypeDefaultDescription
languageLocaleSupportedLanguage?Device localeForce a specific language
fontFamilyString?System fontCustom 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

CaseDescription
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

PropertyTypeDescription
sessionIdStringUnique session identifier
statusVerificationStatusAPPROVED, PENDING, or DECLINED

Error Types

ErrorDescription
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}")
            }
        }
    }
}