> ## 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 en Kotlin de verificació d'identitat: KYC

> SDK Android natiu de Didit en Kotlin per a verificació d'identitat i prova de vida. Des de $0.33 per KYC complet; $10 gratis al mes.



Prompt d'integració de l'SDK d'Android
        Copia el prompt al porta-retalls



      
      

\<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>



      
      

Enganxa a

Un SDK d'Android lleuger i guiat pel servidor per a la verificació d'identitat, amb una configuració mínima.> [card] [Repositori de GitHub](https://github.com/didit-protocol/sdk-android)
>
> Consulta el codi font i els exemples a GitHub> [!NOTE]
>
> ### **SDK natiu**: Aquest és l'enfocament recomanat per a aplicacions d'Android. Els SDK natius ofereixen la millor experiència d'usuari, una gestió optimitzada de la càmera i suport complet de NFC.***## Requisits| Requisit | Versió mínima |
| - | - |
| API d'Android | 23+ (Android 6.0 Marshmallow). La detecció automàtica amb ML requereix l'API 24+ (vegeu més avall). |
| Kotlin | 1.9+ |
| Jetpack Compose | Inclòs com a dependència transitiva |> [!NOTE]
>
> **Disponibilitat de funcionalitats segons el nivell de l'API**: La detecció automàtica de documents i cares requereix l'API 24+ (detectors lleugers propis de Didit, inclosos a `didit-sdk-core`). En dispositius amb API 23, el SDK recorre a la captura manual amb un botó d'obturador temporitzat. La resta de funcionalitats funcionen en tot el rang d'API 23+.> [!NOTE]
>
> **El consentiment biomètric requereix el SDK natiu 4.10.0 o posterior.** Per a les persones afectades per les lleis d'Illinois, Texas o Colorado, Didit pot demanar un [consentiment biomètric](https://docs.didit.me/ca/getting-started/biometric-consent.md) explícit abans de la primera captura facial. El SDK d'Android 4.10.0 i les versions posteriors mostren aquest pas. Les versions anteriors no el poden mostrar: les seves sessions s'executen com abans, i la decisió indica que el consentiment no s'ha recollit (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Actualitza si verifiques persones en aquests estats.***## Instal·lació### Pas 1: Afegeix el repositoriAfegeix el repositori Maven de Didit al bloc `repositories` del teu `settings.gradle.kts`:```kotlin theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository") }
    }
}
```Si fas servir `settings.gradle` (Groovy), fes-ho així:```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```### Pas 2: Afegeix la dependènciaAfegeix la dependència de l'SDK al `build.gradle.kts` de la teva aplicació:
(!) Pel que fa a la versió, assegura't de consultar el [repositori de GitHub](https://github.com/didit-protocol/sdk-android) per veure l'última versió.```kotlin theme={null}
dependencies {
    implementation("me.didit:didit-sdk:4.13.2")
}
```Si fas servir `build.gradle` (Groovy), fes-ho així:```groovy theme={null}
dependencies {
    implementation "me.didit:didit-sdk:4.13.2"
}
```#### Variants de l'SDKL'SDK d'Android es distribueix en artefactes separats, de manera que la teva aplicació només assumeix el cost binari de les funcionalitats que utilitza. `me.didit:didit-sdk` de dalt és el paquet complet. Tria el que s'adapti a la teva aplicació:| Artefacte | Detecció automàtica (ML) | Lectura del xip NFC | Fes-lo servir quan |
| - | :-: | :-: | - |
| `me.didit:didit-sdk-core` | ✓ | – | la compilació més petita; captura automàtica amb els detectors propis de Didit, sense lectura del xip de passaports ni de documents d'identitat |
| `me.didit:didit-sdk-autodetection` | ✓ | – | obsolet i buit des de la 4.11.0; depèn només de `didit-sdk-core`, així que fes servir `didit-sdk-core` en el seu lloc |
| `me.didit:didit-sdk-nfc` | ✓ | ✓ | lectura del xip basada en `didit-sdk-core` |
| `me.didit:didit-sdk` | ✓ | ✓ | totes les funcionalitats (paquet complet) |A partir de la `4.6.0`, la signatura de carteres amb WalletConnect es distribueix nativament com a complement opcional propi, `me.didit:didit-sdk-wallet`.
El paquet complet `me.didit:didit-sdk` ja l'inclou, de manera que no canvia res si instal·les el paquet.
Si fas servir un dels artefactes més lleugers i vols que la confirmació de titularitat de la cartera s'executi de manera nativa dins de la teva aplicació, afegeix `me.didit:didit-sdk-wallet` al costat d'aquest; sense el complement, l'SDK completa la confirmació de la titularitat de la cartera mitjançant un flux segur al navegador, de manera que la funcionalitat continua funcionant en qualsevol cas.
Haver mogut WalletConnect fora de `didit-sdk-core` també ha suprimit diversos megabytes de dependències de cartera de totes les compilacions que no les necessiten.Tots els artefactes es publiquen amb la mateixa versió, així que mantén-los a la `4.13.2`.#### Com reduir la mida de la descàrregaEls models de detecció que s'usen per a la captura automàtica es descarreguen en temps d'execució i es guarden a la memòria cau, de manera que mai no compten per a la mida de la teva aplicació.
El que la captura automàtica afegeix a l'aplicació és la biblioteca nativa del temps d'execució de ML, i aquest cost depèn de l'arquitectura de la CPU: aproximadament 10 MB per a `arm64-v8a`, 7 MB per a `armeabi-v7a` i 13 MB per a cadascuna de les dues arquitectures x86 dels emuladors.Per pagar aquest cost només una vegada:1) **Publica un Android App Bundle (AAB).** Google Play distribueix només l'arquitectura i els idiomes del dispositiu, de manera que un telèfon arm64 instal·la aproximadament 10 MB de codi nadiu (uns 4 MB de descàrrega comprimida). En canvi, un APK universal inclou les quatre arquitectures i ocupa més de 40 MB, que és la causa més habitual de mides inesperadament grans.

2) **Si distribueixes un únic APK** i el teu públic són telèfons i tauletes ARM, restringeix les arquitectures incloses:

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

   Mantén totes les ABI que els teus usuaris fan servir de veritat: afegeix `x86_64` si t'adreces a Chromebooks o altres dispositius x86, o publica divisions d'APK per ABI perquè cap dispositiu deixi de tenir suport.

3) **Activa R8**: `isMinifyEnabled = true` i `isShrinkResources = true` al tipus de compilació de producció (`minifyEnabled true` i `shrinkResources true` si fas servir `build.gradle` amb Groovy). L'SDK inclou les seves pròpies regles de consumidor, de manera que el codi de l'SDK que no s'utilitza s'elimina sense cap configuració addicional.

4) **Limita els idiomes inclosos** amb `resConfigs(...)` si no necessites totes les 48 configuracions regionals de l'SDK en una compilació d'APK; les divisions per configuració regional de l'AAB ho gestionen automàticament a Google Play.### Pas 3: Afegeix l'exclusió d'empaquetatgeAfegeix això al bloc `android` de la teva aplicació per evitar conflictes de compilació:```kotlin theme={null}
android {
    packaging {
        resources {
            excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
        }
    }
}
```Ja està! Gradle resoldrà automàticament totes les dependències transitives.***## PermisosEl SDK requereix els permisos següents. Es declaren al `AndroidManifest.xml` del SDK i es fusionaran automàticament amb el manifest de la teva aplicació:| Permís | AAR d'origen | Descripció | Obligatori |
| - | - | - | - |
| `INTERNET` | `didit-sdk-core` | Accés a la xarxa per a la comunicació amb l'API | Sí |
| `ACCESS_NETWORK_STATE` | `didit-sdk-core` | Detecta la disponibilitat de la xarxa | Sí |
| `CAMERA` | `didit-sdk-core` | Escaneig de documents i verificació facial | Sí |
| `NFC` | `didit-sdk-nfc` | Llegeix els xips NFC de passaports i targetes d'identitat | Fusionat automàticament des de `didit-sdk-nfc` (dependència transitiva de `me.didit:didit-sdk`) |### Funcionalitats de càmera i NFCEl SDK declara `android.hardware.camera` i `android.hardware.nfc` com a funcionalitats opcionals (`android:required="false"`). Així es garanteix que la teva aplicació es pugui instal·lar en dispositius sense càmera ni maquinari NFC: el SDK gestionarà adequadament la falta de maquinari en temps d'execució.***## Inici ràpid### Pas 1: Inicialitza el SDKInicialitza el SDK al teu `Application.onCreate()`:```kotlin theme={null}
import me.didit.sdk.DiditSdk

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        DiditSdk.initialize(this)
    }
}
```### Pas 2: Inicia la verificació i gestiona els resultats```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ètodes d'integracióEl SDK admet dos mètodes d'integració:### Mètode 1: UniLink (el més senzill)No cal backend. El SDK crea la sessió directament amb l'ID del flux de treball de la Didit Console. Limitat només a `vendorData`.```kotlin theme={null}
DiditSdk.startVerification(
    workflowId = "your-workflow-id",
    vendorData = "user-123"
) { result ->
    handleResult(result)
}
```### Mètode 2: Sessió des del backend (recomanat per a producció)El teu backend crea la sessió mitjançant l'[API de creació de sessions de verificació](https://docs.didit.me/ca/sessions-api/create-session.md) (`POST /v3/session/`) amb suport complet de paràmetres (`contact_details`, `expected_details`, `metadata`, `callback`, etc.), i després passa el `session_token` al 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)
}
```Aquest enfocament et dona control total sobre:- Associar les sessions amb els teus usuaris (`vendor_data`)
- Definir metadades personalitzades
- Configurar callbacks per sessió
- Proporcionar dades de contacte i dades esperades per a la validació creuada***## ConfiguracióPersonalitza el comportament del 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)
}
```### Opcions de configuració| Propietat | Tipus | Per defecte | Descripció |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | Configuració regional del dispositiu | Força un idioma concret |
| `showLanguageSelector` | `Boolean` | `false` | Mostra el selector d'idioma d'estil web a la pantalla de benvinguda |
| `fontFamily` | `String?` | Tipus de lletra del sistema | Nom del recurs de tipus de lletra personalitzat (de `res/font/`) |
| `loggingEnabled` | `Boolean` | `false` | Activa el registre de depuració del SDK |
| `showCloseButton` | `Boolean` | `true` | Mostra el botó de tancament (X) a les pantalles dels passos de verificació |
| `showExitConfirmation` | `Boolean` | `true` | Mostra un diàleg de confirmació quan l'usuari intenta sortir |
| `closeOnComplete` | `Boolean` | `false` | Tanca automàticament la interfície de verificació en completar-se (equivalent al Web SDK: `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `CameraLens.BACK` | Objectiu que s'utilitza quan s'obre la pantalla de captura del document |
| `defaultLivenessCamera` | `CameraLens` | `CameraLens.FRONT` | Objectiu que s'utilitza quan s'obre la pantalla de captura facial (prova de vida) |
| `showDocumentCameraSwitchButton` | `Boolean` | `true` | Mostra el selector de càmera durant la captura a la pantalla de captura del document |
| `showLivenessCameraSwitchButton` | `Boolean` | `true` | Mostra el selector de càmera durant la captura a la pantalla de captura facial |### Opcions de càmeraLes opcions de càmera coincideixen amb les [opcions de càmera del Web SDK](https://docs.didit.me/ca/integration/web-sdks/javascript-sdk.md#opcions-de-càmera).
Cada objectiu és `CameraLens.FRONT` o `CameraLens.BACK`.
Si el dispositiu no té l'objectiu sol·licitat, el SDK utilitza la primera càmera que tingui.
El selector de càmera també s'amaga en dispositius que només tenen una càmera.
Estableix una opció del selector a `false` per bloquejar l'usuari a l'objectiu per defecte d'aquell pas.```kotlin theme={null}
val configuration = Configuration(
    defaultLivenessCamera = CameraLens.BACK,
    showLivenessCameraSwitchButton = false
)
```> [!NOTE]
>
> Les opcions `showLanguageSelector`, `showCloseButton`, `showExitConfirmation` i `closeOnComplete` coincideixen amb el `DiditSdkConfiguration` del Web SDK. Les opcions específiques de mòbil `languageLocale` i `fontFamily` existeixen perquè el SDK mòbil renderitza la interfície de verificació completa de manera nativa (a diferència del Web SDK, que delega a la interfície allotjada dins d'un iframe).> [!NOTE]
>
> **Personalització i colors**: els colors, els fons i la configuració de la pantalla d'introducció es configuren a través de la [configuració de Marca blanca](https://business.didit.me) de la Didit Console, i no a la configuració del SDK. Així es garanteix una imatge de marca coherent a totes les plataformes.***## Idiomes admesosEl SDK admet **54 idiomes**. Si no s'especifica cap idioma, el SDK utilitza la configuració regional del dispositiu, amb l'anglès com a idioma de reserva.```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)
```**[Consulta tots els idiomes admesos →](https://docs.didit.me/ca/integration/supported-languages.md)*****## Opcions avançadesPer als paràmetres avançats de sessió (`contact_details`, `expected_details`, `metadata`, `callback`), utilitza el mètode **Sessió des del backend**. El teu backend crida l'[API de creació de sessions de verificació](https://docs.didit.me/ca/sessions-api/create-session.md) amb tots els paràmetres i després passa el `session_token` al SDK.***## Gestió dels resultatsLa classe segellada `VerificationResult` proporciona el resultat de la verificació:### Casos de resultat| Cas | Descripció |
| - | - |
| `Completed(session)` | El flux de verificació s'ha completat (consulta `session.status` per obtenir el resultat) |
| `Cancelled(session)` | L'usuari ha cancel·lat el flux de verificació |
| `Failed(error, session)` | S'ha produït un error durant la verificació |### Propietats de SessionData| Propietat | Tipus | Descripció |
| - | - | - |
| `sessionId` | `String` | Identificador únic de la sessió |
| `status` | `VerificationStatus` | `APPROVED`, `PENDING` o `DECLINED` |### Tipus d'errorTots els errors són subclasses segellades de `me.didit.sdk.VerificationError`:| Error | Descripció |
| - | - |
| `SessionExpired` | La sessió ha caducat |
| `NetworkError` | Problema de connectivitat |
| `CameraAccessDenied` | No s'ha concedit el permís de la càmera |
| `NotInitialized` | L'SDK no està inicialitzat; crida primer `DiditSdk.initialize(context)` |
| `ApiError` | El backend ha retornat una resposta d'error |
| `RetryBlocked` | La verificació no es pot tornar a intentar (p. ex., s'ha arribat al màxim d'intents) |
| `Unknown(message)` | Un altre error amb un missatge |### Connexió perdudaSi el dispositiu perd la connexió durant la verificació, l'SDK mostra una pantalla que se sobreposa al flux, «Sense connexió a Internet», en lloc de deixar un pas carregant.
Continua comprovant-ho en segon pla i tanca la pantalla automàticament tan aviat com es pugui tornar a accedir a Didit, i l'usuari continua des del pas on era.
La pantalla ofereix **Torna-ho a provar** i, quan `showCloseButton` és `true` (el valor per defecte), **Surt de la verificació**.
En sortir, la verificació acaba amb `VerificationResult.Failed(error = VerificationError.NetworkError, session = ...)`, de manera que la teva aplicació sap que l'usuari ha sortit per la connexió.### Exemple complet de gestió del resultat```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
        }
    }
}
```***## Observació de l'estat de l'SDKPots observar l'estat de l'SDK per crear una interfície de càrrega personalitzada:```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 / R8L'SDK inclou les seves pròpies regles de ProGuard per al consumidor. No cal cap configuració addicional.Si uses el mode complet de R8, és possible que hagis d'afegir això al teu `gradle.properties`:```properties theme={null}
android.enableR8.fullMode=false
```***## Exemple de principi a fi (sessió al backend → SDK d'Android → resultat)Aquest patró és la integració a punt per a producció. El teu backend crea la sessió, la teva aplicació Android rep el `session_token` i l'SDK executa el flux.### 1. Backend: crear la sessió```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: intercanviar i iniciar l'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: rebre la decisió final mitjançant webhookEl resultat de l'SDK és útil per a la retroacció a la interfície, però el resultat autoritatiu arriba mitjançant webhook. Consulta la [guia de webhooks](https://docs.didit.me/ca/integration/webhooks.md) per a la verificació 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.