> ## 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.

# SDK Android Kotlin de vérification d'identité : KYC

> SDK Android natif Didit : vérification d'identité, du vivant et lecture NFC. Dès $0.33 par KYC complet, $10 gratuits/mois, sans contrat.



Prompt d'intégration du SDK Android
        Copier le prompt dans le presse-papiers



      
      

\<pre>

\`Integrate Didit identity verification into my Android app using the native Kotlin SDK.

\## Requirements
\- Android API 23+ (Android 6.0 Marshmallow). ML-based auto-detection (document/face) requires API 24+ and falls back to manual capture below that.
\- Kotlin 1.9+
\- NFC reading requires NFC-capable device hardware

\## Installation

\### Step 1: Add Maven Repository
In settings.gradle.kts:
dependencyResolutionManagement {
repositories {
    google()
    mavenCentral()
    maven { url = uri("https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository") }
}
}

\### Step 2: Add Dependency
(!) Regarding the version ensure you check the [GitHub repository](https://github.com/didit-protocol/sdk-android) for the latest version.
In app/build.gradle.kts:
dependencies {
implementation("me.didit:didit-sdk:4.13.2")
}

\### Step 3: Add Packaging Exclusion (required to avoid build conflicts)
In the android { } block of app/build.gradle.kts:
android {
packaging {
    resources {
        excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
    }
}
}

\## Permissions (auto-merged from SDK manifest)
\- INTERNET (required) — API communication
\- ACCESS_NETWORK_STATE (required) — Network availability
\- CAMERA (required) — Document scanning and face verification
\- NFC (optional) — Read NFC chips in passports/IDs

Camera and NFC are declared as optional features (android:required="false"), so the app installs on all devices.

\## Initialization (required)
In your Application class:
import me.didit.sdk.DiditSdk

class MyApp : Application() {
override fun onCreate() {
    super.onCreate()
    DiditSdk.initialize(this)
}
}

Register in AndroidManifest.xml:
\<application android:name=".MyApp" ...>

\## Backend: Create Session (your server)
POST https://verification.didit.me/v3/session/
Headers: { "x-api-key": DIDIT_API_KEY, "Content-Type": "application/json" }
Body: { "workflow_id": DIDIT_WORKFLOW_ID, "vendor_data": "user-id" }
Response: { "session_id": "uuid", "session_token": "short-token", "url": "https://verify.didit.me/session/short-token", "status": "Not Started" }
Send session_token to the Android app (never expose DIDIT_API_KEY to the device).

\## Jetpack Compose Integration
import me.didit.sdk.DiditSdk
import me.didit.sdk.DiditSdkState
import me.didit.sdk.VerificationResult

// Observe SDK state and launch UI when ready
LaunchedEffect(Unit) {
DiditSdk.state.collect { state ->
    when (state) {
        is DiditSdkState.Ready -> DiditSdk.launchVerificationUI(activity)
        is DiditSdkState.Error -> Log.e("Didit", "Error: state.message")
        else -> { /* Loading, Idle, CreatingSession */ }
    }
}
}

// Start verification with session token from backend
import me.didit.sdk.VerificationStatus

fun startVerification(token: String) {
DiditSdk.startVerification(token = token) { result ->
    when (result) {
        is VerificationResult.Completed -> when (result.session.status) {
            VerificationStatus.APPROVED -> { /* grant access */ }
            VerificationStatus.DECLINED -> { /* show retry */ }
            VerificationStatus.PENDING  -> { /* under review */ }
        }
        is VerificationResult.Cancelled -> { /* user cancelled */ }
        is VerificationResult.Failed    -> { /* show error: result.error.message */ }
    }
}
}

\## Result Statuses (VerificationStatus enum; .rawValue gives "Approved" / "Pending" / "Declined")
\- VerificationStatus.APPROVED — user identity verified, grant access
\- VerificationStatus.DECLINED — verification failed, show retry or contact support
\- VerificationStatus.PENDING  — needs manual review by your compliance team

\## Full Verification Results
The SDK only returns the status. Full decision data (document fields, face match scores, AML hits, etc.) arrives via webhook to your backend.
Set up webhooks: https://docs.didit.me/integration/webhooks

\## Rate Limits (session creation)
\- 600 session-create requests / minute per x-api-key (see https://docs.didit.me/integration/rate-limiting)
\- On 429, retry honouring Retry-After / X-RateLimit-* headers

\## Environment Variables (backend only — never expose in the Android app)
\- DIDIT_API_KEY — from Didit Console > API & Webhooks
\- DIDIT_WORKFLOW_ID — from Didit Console > Workflows

\## Docs
\- Android SDK: https://docs.didit.me/integration/native-sdks/android-sdk
\- GitHub: https://github.com/didit-protocol/sdk-android
\- Webhooks: https://docs.didit.me/integration/webhooks
\- API Reference: https://docs.didit.me/api-reference/overview`

\</pre>



      
      

Coller dans

Un SDK Android léger et piloté par le serveur pour la vérification d'identité, avec une configuration minimale.> [card] [Dépôt GitHub](https://github.com/didit-protocol/sdk-android)
>
> Consultez le code source et les exemples sur GitHub> [!NOTE]
>
> ### **SDK natif**: Il s'agit de l'approche recommandée pour les applications Android. Les SDK natifs offrent la meilleure expérience utilisateur, une gestion optimisée de la caméra et une prise en charge complète du NFC.***## Prérequis| Prérequis | Version minimale |
| - | - |
| API Android | 23+ (Android 6.0 Marshmallow). L'autodétection ML nécessite l'API 24+ (voir ci-dessous). |
| Kotlin | 1.9+ |
| Jetpack Compose | Inclus en tant que dépendance transitive |> [!NOTE]
>
> **Disponibilité des fonctionnalités par niveau d'API** : L'autodétection de documents et de visages nécessite l'API 24+ (les détecteurs légers propres à Didit, inclus dans `didit-sdk-core`). Sur les appareils dotés de l'API 23, le SDK bascule sur une capture manuelle avec un bouton de déclenchement temporisé. Toutes les autres fonctionnalités fonctionnent sur l'ensemble de la plage d'API 23+.> [!NOTE]
>
> **Le consentement biométrique nécessite la version native 4.10.0 ou ultérieure.** Pour les personnes couvertes par les lois de l'Illinois, du Texas ou du Colorado, Didit peut demander un [consentement biométrique](https://docs.didit.me/fr/getting-started/biometric-consent.md) explicite avant la première capture de visage. Le SDK Android 4.10.0 et versions ultérieures affichent cette étape. Les versions antérieures ne peuvent pas afficher l'étape : leurs sessions se déroulent comme auparavant, et la décision indique que le consentement n'a pas été collecté (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Mettez à niveau si vous vérifiez des personnes dans ces États.***## Installation### Étape 1 : Ajouter le dépôtAjoutez le dépôt Maven de Didit au bloc `repositories` de votre fichier `settings.gradle.kts` :```kotlin theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository") }
    }
}
```Si vous utilisez `settings.gradle` (Groovy) :```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```### Étape 2 : Ajouter la dépendanceAjoutez la dépendance du SDK au fichier `build.gradle.kts` de votre application :
(!) Concernant la version, vérifiez la [dernière version sur le dépôt GitHub](https://github.com/didit-protocol/sdk-android).```kotlin theme={null}
dependencies {
    implementation("me.didit:didit-sdk:4.13.2")
}
```Si vous utilisez `build.gradle` (Groovy) :```groovy theme={null}
dependencies {
    implementation "me.didit:didit-sdk:4.13.2"
}
```#### Variantes du SDKLe SDK Android est distribué sous forme d'artefacts distincts, de sorte que votre application n'inclut que la taille binaire des
fonctionnalités qu'elle utilise. `me.didit:didit-sdk` ci-dessus est le bundle complet. Choisissez celui qui convient à votre application :| Artefact | Détection automatique (ML) | Lecture de puce NFC | À utiliser quand |
| - | :-: | :-: | - |
| `me.didit:didit-sdk-core` | ✓ | – | build de taille minimale ; capture automatique avec les détecteurs propres à Didit, sans lecture de la puce du passeport ou de la pièce d'identité |
| `me.didit:didit-sdk-autodetection` | ✓ | – | obsolète et vide depuis la 4.11.0 ; ne dépend que de `didit-sdk-core`, utilisez donc plutôt `didit-sdk-core` |
| `me.didit:didit-sdk-nfc` | ✓ | ✓ | lecture de puce en plus de `didit-sdk-core` |
| `me.didit:didit-sdk` | ✓ | ✓ | toutes les fonctionnalités (bundle complet) |Depuis la `4.6.0`, la signature de portefeuille native via WalletConnect est proposée sous forme de module complémentaire optionnel distinct, `me.didit:didit-sdk-wallet`.
Le bundle complet `me.didit:didit-sdk` l'inclut déjà, donc rien ne change si vous installez le bundle.
Si vous utilisez l'un des artefacts plus légers et souhaitez que la confirmation de propriété du portefeuille soit effectuée nativement dans votre application, ajoutez `me.didit:didit-sdk-wallet` à côté ; sans ce module complémentaire, le SDK effectue la confirmation de propriété via un parcours sécurisé dans le navigateur, de sorte que la fonctionnalité continue de fonctionner dans les deux cas.
Le déplacement de WalletConnect hors de `didit-sdk-core` a également retiré plusieurs mégaoctets de dépendances de portefeuille de chaque build qui n'en a pas besoin.Tous les artefacts sont publiés dans la même version, gardez-les donc sur `4.13.2`.#### Réduire la taille du téléchargementLes modèles de détection utilisés pour la capture automatique sont téléchargés à l'exécution puis mis en cache, de sorte qu'ils ne comptent jamais dans la taille de votre application.
Ce qu'ajoute la capture automatique à votre application, c'est la bibliothèque native du runtime ML, et ce coût dépend de l'architecture CPU : environ 10 Mo pour `arm64-v8a`, 7 Mo pour `armeabi-v7a`, et 13 Mo pour chacune des deux architectures x86 des émulateurs.Pour ne payer ce coût qu'une seule fois :1) **Publiez un Android App Bundle (AAB).** Google Play ne livre que l'architecture et les langues propres à l'appareil, donc un téléphone arm64 installe environ 10 Mo de code natif (environ 4 Mo de téléchargement compressé). Un APK universel, en revanche, regroupe les quatre architectures, soit plus de 40 Mo, ce qui est la cause la plus courante de mesures de taille anormalement élevées.

2) **Si vous distribuez un APK unique** et que votre public utilise des téléphones et tablettes ARM, limitez les architectures embarquées :

   ```kotlin theme={null}
   android {
       defaultConfig {
           ndk { abiFilters += listOf("arm64-v8a", "armeabi-v7a") }
       }
   }
   ```

   Conservez toutes les ABI que vos utilisateurs utilisent réellement : ajoutez `x86_64` si vous ciblez les Chromebooks ou d'autres appareils x86, ou publiez des APK distincts par ABI afin que tous les appareils restent pris en charge.

3) **Activez R8** : `isMinifyEnabled = true` et `isShrinkResources = true` dans le type de build de publication (`minifyEnabled true` / `shrinkResources true` si vous utilisez le `build.gradle` Groovy). Le SDK fournit ses propres règles de consommation, donc le code inutilisé du SDK est supprimé sans configuration supplémentaire.

4) **Limitez les langues embarquées** avec `resConfigs(...)` si vous n'avez pas besoin des 48 paramètres régionaux du SDK dans un build APK ; les divisions de langues des AAB le font automatiquement sur Google Play.### Étape 3 : Ajouter l'exclusion lors du packagingAjoutez ceci au bloc `android` de votre application pour éviter les conflits de build :```kotlin theme={null}
android {
    packaging {
        resources {
            excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
        }
    }
}
```Et voilà ! Gradle résout automatiquement toutes les dépendances transitives.***## AutorisationsLe SDK requiert les autorisations suivantes. Celles-ci sont déclarées dans le fichier `AndroidManifest.xml` du SDK et seront automatiquement fusionnées dans le manifeste de votre application :| Autorisation | Source AAR | Description | Requise |
| - | - | - | - |
| `INTERNET` | `didit-sdk-core` | Accès réseau pour la communication avec l'API | Oui |
| `ACCESS_NETWORK_STATE` | `didit-sdk-core` | Détection de la disponibilité du réseau | Oui |
| `CAMERA` | `didit-sdk-core` | Numérisation de documents et vérification faciale | Oui |
| `NFC` | `didit-sdk-nfc` | Lecture des puces NFC dans les passeports/cartes d'identité | Fusionnée automatiquement depuis `didit-sdk-nfc` (dépendance transitive de `me.didit:didit-sdk`) |### Fonctionnalités Appareil photo et NFCLe SDK déclare `android.hardware.camera` et `android.hardware.nfc` comme fonctionnalités facultatives (`android:required="false"`). Cela garantit que votre application peut être installée sur des appareils dépourvus d'appareil photo ou de matériel NFC — le SDK gérera de manière fluide l'absence de matériel au moment de l'exécution.***## Démarrage rapide### Étape 1 : Initialiser le SDKInitialisez le SDK dans la méthode `Application.onCreate()` :```kotlin theme={null}
import me.didit.sdk.DiditSdk

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        DiditSdk.initialize(this)
    }
}
```### Étape 2 : Démarrer la vérification et traiter les résultats```kotlin theme={null}
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}")
            }
            is VerificationResult.Cancelled -> {
                Log.d("Didit", "User cancelled")
            }
            is VerificationResult.Failed -> {
                Log.e("Didit", "Failed: ${result.error.message}")
            }
        }
    }
}
```***## Méthodes d'intégrationLe SDK prend en charge deux méthodes d'intégration :### Méthode 1 : UniLink (la plus simple)Aucun backend requis. Le SDK crée directement la session en utilisant votre identifiant de workflow depuis la Console Didit. Limité uniquement à `vendorData`.```kotlin theme={null}
DiditSdk.startVerification(
    workflowId = "your-workflow-id",
    vendorData = "user-123"
) { result ->
    handleResult(result)
}
```### Méthode 2 : Session backend (recommandée pour la production)Votre backend crée la session via l'[API Create Verification Session](https://docs.didit.me/fr/sessions-api/create-session.md) (`POST /v3/session/`) avec la prise en charge complète des paramètres (`contact_details`, `expected_details`, `metadata`, `callback`, etc.), puis transmet le `session_token` au SDK.```kotlin theme={null}
// 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)
}
```Cette approche vous donne un contrôle total sur :- L'association des sessions à vos utilisateurs (`vendor_data`)
- La définition de métadonnées personnalisées
- La configuration des rappels par session
- La transmission des coordonnées et des informations attendues pour la validation croisée***## ConfigurationPersonnalisez le comportement du SDK :```kotlin theme={null}
import me.didit.sdk.Configuration
import me.didit.sdk.core.localization.SupportedLanguage

val configuration = Configuration(
    languageLocale = SupportedLanguage.SPANISH,  // Force Spanish language
    showLanguageSelector = true,                  // Let the user change 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)
}
```### Options de configuration| Propriété | Type | Par défaut | Description |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | Paramètres régionaux de l'appareil | Forcer une langue spécifique |
| `showLanguageSelector` | `Boolean` | `false` | Afficher le sélecteur de langue façon web sur l'écran d'accueil |
| `fontFamily` | `String?` | Police système | Nom de la ressource de police personnalisée (depuis `res/font/`) |
| `loggingEnabled` | `Boolean` | `false` | Activer les journaux de débogage du SDK |
| `showCloseButton` | `Boolean` | `true` | Afficher le bouton de fermeture (X) sur les écrans des étapes de vérification |
| `showExitConfirmation` | `Boolean` | `true` | Afficher une boîte de dialogue de confirmation lorsque l'utilisateur tente de quitter |
| `closeOnComplete` | `Boolean` | `false` | Fermer automatiquement l'interface utilisateur de vérification une fois terminée (équivalent Web SDK : `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `CameraLens.BACK` | Objectif utilisé à l'ouverture de l'écran de capture du document |
| `defaultLivenessCamera` | `CameraLens` | `CameraLens.FRONT` | Objectif utilisé à l'ouverture de l'écran de capture faciale (détection du vivant) |
| `showDocumentCameraSwitchButton` | `Boolean` | `true` | Afficher le sélecteur d'appareil photo pendant la capture sur l'écran de capture du document |
| `showLivenessCameraSwitchButton` | `Boolean` | `true` | Afficher le sélecteur d'appareil photo pendant la capture sur l'écran de capture faciale |### Options de l'appareil photoLes options de l'appareil photo correspondent aux [options de l'appareil photo du Web SDK](https://docs.didit.me/fr/integration/web-sdks/javascript-sdk.md#options-de-caméra).
Chaque objectif est `CameraLens.FRONT` ou `CameraLens.BACK`.
Si l'appareil ne dispose pas de l'objectif demandé, le SDK utilise le premier appareil photo disponible.
Le sélecteur d'appareil photo est également masqué sur les appareils qui ne possèdent qu'un seul appareil photo.
Définissez une option de sélecteur sur `false` pour imposer à l'utilisateur l'objectif par défaut de cette étape.```kotlin theme={null}
val configuration = Configuration(
    defaultLivenessCamera = CameraLens.BACK,
    showLivenessCameraSwitchButton = false
)
```> [!NOTE]
>
> Les options `showLanguageSelector`, `showCloseButton`, `showExitConfirmation` et `closeOnComplete` correspondent au `DiditSdkConfiguration` du Web SDK. Les options spécifiques au mobile `languageLocale` et `fontFamily` existent parce que le SDK mobile affiche l'intégralité de l'interface de vérification de manière native (contrairement au Web SDK qui délègue au frontend hébergé dans une iframe).> [!NOTE]
>
> **Thème et couleurs** : les couleurs, les arrière-plans et les paramètres de l'écran d'introduction sont configurés par le biais de vos [paramètres de marque blanche](https://business.didit.me) dans la Console Didit, et non dans la configuration du SDK. Cela garantit une image de marque cohérente sur toutes les plateformes.***## Prise en charge des languesLe SDK prend en charge **54 langues**. Si aucune langue n'est spécifiée, le SDK utilise les paramètres régionaux de l'appareil avec l'anglais comme langue de secours.```kotlin theme={null}
// Use device locale (default)
val config = Configuration()

// Force specific language
val config = Configuration(languageLocale = SupportedLanguage.FRENCH)

// Let the user change language on the welcome screen
val config = Configuration(showLanguageSelector = true)
```**[Voir toutes les langues prises en charge →](https://docs.didit.me/fr/integration/supported-languages.md)*****## Options avancéesPour les paramètres de session avancés (`contact_details`, `expected_details`, `metadata`, `callback`), utilisez la méthode **de session via le backend**. Votre backend appelle l'[API Create Verification Session](https://docs.didit.me/fr/sessions-api/create-session.md) avec l'ensemble des paramètres, puis transmet le `session_token` au SDK.***## Traitement des résultatsLa classe scellée `VerificationResult` fournit le résultat de la vérification :### Cas de résultats| Cas | Description |
| - | - |
| `Completed(session)` | Le workflow de vérification est terminé (vérifiez `session.status` pour le résultat) |
| `Cancelled(session)` | L'utilisateur a annulé le workflow de vérification |
| `Failed(error, session)` | Une erreur est survenue pendant la vérification |### Propriétés de SessionData| Propriété | Type | Description |
| - | - | - |
| `sessionId` | `String` | Identifiant unique de session |
| `status` | `VerificationStatus` | `APPROVED`, `PENDING` ou `DECLINED` |### Types d'erreursToutes les erreurs sont des sous-classes scellées de `me.didit.sdk.VerificationError` :| Erreur | Description |
| - | - |
| `SessionExpired` | La session a expiré |
| `NetworkError` | Problème de connectivité réseau |
| `CameraAccessDenied` | Autorisation de la caméra non accordée |
| `NotInitialized` | SDK non initialisé — appelez d'abord `DiditSdk.initialize(context)` |
| `ApiError` | Le backend a renvoyé une réponse d'erreur |
| `RetryBlocked` | La vérification ne peut pas être réessayée (par ex. nombre maximal de tentatives atteint) |
| `Unknown(message)` | Autre erreur avec un message |### Perte de connexionSi l'appareil perd sa connexion pendant la vérification, le SDK affiche un écran « Pas de connexion Internet » par-dessus le flux au lieu de laisser une étape en chargement.
Il continue de vérifier en arrière-plan et ferme automatiquement cet écran dès que Didit est de nouveau accessible, permettant à l'utilisateur de reprendre à l'étape où il s'était arrêté.
L'écran propose **Réessayer** et, lorsque `showCloseButton` est `true` (valeur par défaut), **Quitter la vérification**.
Quitter met fin à la vérification avec `VerificationResult.Failed(error = VerificationError.NetworkError, session = ...)`, afin que votre application sache que l'utilisateur est parti à cause de la connexion.### Exemple complet de traitement des résultats```kotlin theme={null}
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
        }
    }
}
```***## Observer l'état du SDKVous pouvez observer l'état du SDK pour afficher une interface de chargement personnalisée :```kotlin theme={null}
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 / R8Le SDK inclut ses propres règles ProGuard destinées aux consommateurs. Aucune configuration supplémentaire n'est requise.Si vous utilisez le mode complet de R8, vous devrez peut-être ajouter ceci à votre `gradle.properties` :```properties theme={null}
android.enableR8.fullMode=false
```***## Exemple de bout en bout (Session backend → SDK Android → Résultat)Ce modèle constitue l'intégration prête pour la production. Votre backend crée la session, votre application Android reçoit le `session_token`, et le SDK exécute le workflow.### 1. Backend — créer la session```ts theme={null}
// Node.js / Express example. Run on your server. NEVER ship DIDIT_API_KEY to the device.
import express from "express";

const app = express();
app.use(express.json());

app.post("/api/verification/start", async (req, res) => {
  const response = await fetch("https://verification.didit.me/v3/session/", {
    method: "POST",
    headers: {
      "x-api-key": process.env.DIDIT_API_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      workflow_id: process.env.DIDIT_WORKFLOW_ID,
      vendor_data: req.body.userId, // your stable user id
    }),
  });

  if (!response.ok) {
    return res.status(500).json({ error: `Didit ${response.status}` });
  }

  const { session_id, session_token } = await response.json();
  // Persist session_id <-> userId so you can match the webhook later.
  res.json({ session_id, session_token });
});
```### 2. Android — échanger et démarrer le SDK```kotlin theme={null}
import android.app.Activity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.didit.sdk.DiditSdk
import me.didit.sdk.VerificationResult
import me.didit.sdk.VerificationStatus
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.MediaType.Companion.toMediaType
import org.json.JSONObject

class VerificationFlow(private val activity: ComponentActivity) {
    private val http = OkHttpClient()
    private val json = "application/json".toMediaType()

    fun start(userId: String) {
        activity.lifecycleScope.launch {
            val token = withContext(Dispatchers.IO) {
                val body = JSONObject().put("userId", userId).toString().toRequestBody(json)
                val req = Request.Builder()
                    .url("https://your-backend.example.com/api/verification/start")
                    .post(body)
                    .build()
                http.newCall(req).execute().use { resp ->
                    JSONObject(resp.body!!.string()).getString("session_token")
                }
            }

            DiditSdk.startVerification(token = token) { result ->
                when (result) {
                    is VerificationResult.Completed -> when (result.session.status) {
                        VerificationStatus.APPROVED -> { /* optimistic UI; rely on webhook for source of truth */ }
                        VerificationStatus.PENDING  -> { /* show "under review" */ }
                        VerificationStatus.DECLINED -> { /* show retry/contact support */ }
                    }
                    is VerificationResult.Cancelled -> { /* user cancelled */ }
                    is VerificationResult.Failed    -> { /* show error: result.error.message */ }
                }
            }
        }
    }
}
```### 3. Backend — recevoir la décision finale par webhookLe résultat du SDK est pratique pour le retour visuel dans l'interface, mais la décision faisant foi arrive par webhook. Consultez le [guide des webhooks](https://docs.didit.me/fr/integration/webhooks.md) pour la vérification HMAC.```ts theme={null}
app.post("/api/webhooks/didit", express.raw({ type: "application/json" }), (req, res) => {
  // 1. Verify the X-Signature header (see Webhooks docs)
  // 2. Parse the body
  const event = JSON.parse(req.body.toString());
  if (event.webhook_type === "status.updated") {
    // event.session_id, event.status ("Approved" | "Declined" | "In Review" | ...)
    // Look up the user by session_id and update their verification state.
  }
  res.sendStatus(200);
});
```***## Exemple complet```kotlin theme={null}
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}")
            }
        }
    }
}
```***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.