> ## 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 de verificação de identidade (KYC) em Kotlin

> Didit: SDK Android Kotlin para verificação de identidade, prova de vida e NFC. A partir de $0.33 por KYC completo, $10 grátis/mês, sem contratos.



Prompt de integração do SDK para Android
        Copiar o prompt para a área de transferência



      
      

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



      
      

Colar em

Um SDK para Android leve e orientado pelo servidor, para verificação de identidade com configuração mínima.> [card] [Repositório no GitHub](https://github.com/didit-protocol/sdk-android)
>
> Consulte o código-fonte e os exemplos no GitHub> [!NOTE]
>
> ### **SDK nativo**: Esta é a abordagem recomendada para aplicações Android. Os SDKs nativos oferecem a melhor experiência do utilizador, um tratamento otimizado da câmara e suporte completo a NFC.***## Requisitos| Requisito | Versão mínima |
| - | - |
| API Android | 23+ (Android 6.0 Marshmallow). A deteção automática por ML requer API 24+ (ver abaixo). |
| Kotlin | 1.9+ |
| Jetpack Compose | Incluído como dependência transitiva |> [!NOTE]
>
> **Disponibilidade de funcionalidades por nível de API**: a deteção automática de documentos e de rostos requer API 24+ (detetores leves próprios da Didit, incluídos em `didit-sdk-core`). Em dispositivos com API 23, o SDK recorre à captura manual, com um botão de disparo temporizado. Todas as restantes funcionalidades funcionam em todo o intervalo abrangido pela API 23+.> [!NOTE]
>
> **O consentimento biométrico requer o SDK nativo 4.10.0 ou posterior.** Para pessoas abrangidas pela legislação do Illinois, do Texas ou do Colorado, a Didit pode pedir um [consentimento biométrico](https://docs.didit.me/pt/getting-started/biometric-consent.md) explícito antes da primeira captura facial. O SDK Android 4.10.0 e versões posteriores apresentam essa etapa. As versões anteriores não a conseguem apresentar: as suas sessões são executadas como antes, e a decisão indica que o consentimento não foi recolhido (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Atualize se verifica pessoas nesses estados.***## Instalação### Passo 1: adicionar o repositórioAdicione o repositório Maven da Didit ao bloco `repositories` do seu `settings.gradle.kts`:```kotlin theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository") }
    }
}
```Ou, se usar `settings.gradle` (Groovy):```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```### Passo 2: adicionar a dependênciaAdicione a dependência do SDK ao `build.gradle.kts` da sua aplicação:
(!) Quanto à versão, certifique-se de que consulta o [repositório do GitHub](https://github.com/didit-protocol/sdk-android) para ver a versão mais recente.```kotlin theme={null}
dependencies {
    implementation("me.didit:didit-sdk:4.13.2")
}
```Ou, se usar `build.gradle` (Groovy):```groovy theme={null}
dependencies {
    implementation "me.didit:didit-sdk:4.13.2"
}
```#### Variantes do SDKO SDK para Android é distribuído em artefactos separados, pelo que a sua aplicação só paga o custo binário das funcionalidades que usa. `me.didit:didit-sdk` acima é o pacote completo. Escolha o que se adapta à sua aplicação:| Artefacto | Deteção automática (ML) | Leitura do chip NFC | Utilizar quando |
| - | :-: | :-: | - |
| `me.didit:didit-sdk-core` | ✓ | – | compilação mais pequena; captura automática com os detetores da própria Didit, sem leitura do chip de passaporte ou documento de identificação |
| `me.didit:didit-sdk-autodetection` | ✓ | – | obsoleto e vazio desde a versão 4.11.0; depende apenas de `didit-sdk-core`, por isso, use `didit-sdk-core` em vez disso |
| `me.didit:didit-sdk-nfc` | ✓ | ✓ | leitura do chip, além de `didit-sdk-core` |
| `me.didit:didit-sdk` | ✓ | ✓ | todas as funcionalidades (pacote completo) |Desde a versão `4.6.0`, a assinatura nativa de carteiras com WalletConnect é distribuída como um complemento opcional próprio, `me.didit:didit-sdk-wallet`.
O pacote completo `me.didit:didit-sdk` já o inclui, por isso nada muda se instalar o pacote.
Se usar um dos artefactos mais leves e quiser que a confirmação de titularidade da carteira seja executada nativamente na sua aplicação, adicione `me.didit:didit-sdk-wallet` junto a ele; sem o complemento, o SDK concretiza a titularidade da carteira através de um fluxo seguro no navegador, pelo que a funcionalidade continua a funcionar em qualquer dos casos.
Mover o WalletConnect para fora de `didit-sdk-core` também eliminou vários megabytes de dependências de carteiras de todas as compilações que não as necessitam.Todos os artefactos são publicados na mesma versão, por isso mantenha-os na versão `4.13.2`.#### Manter o tamanho da transferência reduzidoOs modelos de deteção usados na captura automática são transferidos em tempo de execução e guardados em cache, pelo que nunca contam para o tamanho da sua aplicação.
O que a captura automática acrescenta à aplicação é a biblioteca nativa do ambiente de execução de ML, e esse custo depende da arquitetura da CPU: cerca de 10 MB para `arm64-v8a`, 7 MB para `armeabi-v7a` e 13 MB para cada uma das duas arquiteturas de emulador x86.Para pagar esse custo apenas uma vez:1) **Publique um Android App Bundle (AAB).** A Google Play entrega apenas a arquitetura e os idiomas do próprio dispositivo, pelo que um telemóvel arm64 instala cerca de 10 MB de código nativo (cerca de 4 MB de transferência comprimida). Um APK universal, em contrapartida, inclui as quatro arquiteturas, com mais de 40 MB, o que é a causa mais comum de medições de tamanho inesperadamente grandes.

2) **Se distribuir um único APK** e o seu público for constituído por utilizadores de telemóveis e tablets ARM, restrinja as arquiteturas incluídas:

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

   Mantenha todas as ABI que os seus utilizadores realmente usam: acrescente `x86_64` se visar Chromebooks ou outros dispositivos x86, ou publique divisões de APK por ABI para que nenhum dispositivo perca suporte.

3) **Ative o R8**: `isMinifyEnabled = true` e `isShrinkResources = true` no tipo de compilação de lançamento (`minifyEnabled true` / `shrinkResources true` se usar `build.gradle` em Groovy). O SDK inclui as suas próprias regras de consumidor, pelo que o código do SDK não utilizado é removido sem configuração adicional.

4) **Limite os idiomas incluídos** com `resConfigs(...)` se não precisar de todos os 48 idiomas do SDK numa compilação em APK; as divisões de idioma do AAB tratam disto automaticamente na Google Play.### Passo 3: adicionar a exclusão de empacotamentoAdicione isto ao bloco `android` da sua aplicação para evitar conflitos de compilação:```kotlin theme={null}
android {
    packaging {
        resources {
            excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
        }
    }
}
```É tudo! O Gradle resolve automaticamente todas as dependências transitivas.***## PermissõesO SDK requer as seguintes permissões. Estas são declaradas no `AndroidManifest.xml` do SDK e serão integradas automaticamente no manifesto da sua aplicação:| Permissão | AAR de origem | Descrição | Obrigatória |
| - | - | - | - |
| `INTERNET` | `didit-sdk-core` | Acesso à rede para comunicação com a API | Sim |
| `ACCESS_NETWORK_STATE` | `didit-sdk-core` | Deteta a disponibilidade da rede | Sim |
| `CAMERA` | `didit-sdk-core` | Digitalização de documentos e verificação facial | Sim |
| `NFC` | `didit-sdk-nfc` | Lê os chips NFC de passaportes e cartões de identidade | Integrada automaticamente a partir de `didit-sdk-nfc` (dependência transitiva de `me.didit:didit-sdk`) |### Funcionalidades de câmara e NFCO SDK declara `android.hardware.camera` e `android.hardware.nfc` como funcionalidades opcionais (`android:required="false"`). Isto garante que a sua aplicação pode ser instalada em dispositivos sem câmara ou hardware NFC: o SDK trata a ausência de hardware de forma adequada em tempo de execução.***## Início rápido### Passo 1: Inicializar o SDKInicialize o SDK em `Application.onCreate()`:```kotlin theme={null}
import me.didit.sdk.DiditSdk

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        DiditSdk.initialize(this)
    }
}
```### Passo 2: Iniciar a verificação e tratar os resultados```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étodos de integraçãoO SDK suporta dois métodos de integração:### Método 1: UniLink (o mais simples)Não requer backend. O SDK cria a sessão diretamente com o ID do seu fluxo de verificação na Didit Console. Limitado apenas a `vendorData`.```kotlin theme={null}
DiditSdk.startVerification(
    workflowId = "your-workflow-id",
    vendorData = "user-123"
) { result ->
    handleResult(result)
}
```### Método 2: Sessão no backend (recomendado para produção)O seu backend cria a sessão através da [API de criação de sessões de verificação](https://docs.didit.me/pt/sessions-api/create-session.md) (`POST /v3/session/`), com suporte total dos parâmetros (`contact_details`, `expected_details`, `metadata`, `callback`, etc.), e depois transmite o `session_token` ao 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)
}
```Esta abordagem oferece controlo total sobre:- Associar sessões aos seus utilizadores (`vendor_data`)
- Definir metadados personalizados
- Configurar callbacks por sessão
- Fornecer detalhes de contacto e detalhes esperados para validação cruzada***## ConfiguraçãoPersonalize o comportamento do 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)
}
```### Opções de configuração| Propriedade | Tipo | Predefinição | Descrição |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | Localidade do dispositivo | Força um idioma específico |
| `showLanguageSelector` | `Boolean` | `false` | Mostra o seletor de idioma, no estilo da versão Web, no ecrã de boas-vindas |
| `fontFamily` | `String?` | Tipo de letra do sistema | Nome do recurso de tipo de letra personalizado (de `res/font/`) |
| `loggingEnabled` | `Boolean` | `false` | Ativa o registo de depuração do SDK |
| `showCloseButton` | `Boolean` | `true` | Mostra o botão de fechar (X) nos ecrãs das etapas de verificação |
| `showExitConfirmation` | `Boolean` | `true` | Mostra uma caixa de confirmação quando o utilizador tenta sair |
| `closeOnComplete` | `Boolean` | `false` | Fecha automaticamente a interface de verificação quando esta é concluída (equivalente no Web SDK: `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `CameraLens.BACK` | Objetiva usada quando o ecrã de captura do documento abre |
| `defaultLivenessCamera` | `CameraLens` | `CameraLens.FRONT` | Objetiva usada quando o ecrã de captura facial (prova de vida) abre |
| `showDocumentCameraSwitchButton` | `Boolean` | `true` | Mostra o seletor de câmara durante a captura no ecrã de captura do documento |
| `showLivenessCameraSwitchButton` | `Boolean` | `true` | Mostra o seletor de câmara durante a captura no ecrã de captura facial |### Opções de câmaraAs opções de câmara correspondem às [opções de câmara do Web SDK](https://docs.didit.me/pt/integration/web-sdks/javascript-sdk.md#opções-de-câmara).
Cada objetiva é `CameraLens.FRONT` ou `CameraLens.BACK`.
Se o dispositivo não tiver a objetiva pedida, o SDK usa a primeira câmara de que dispõe.
O seletor de câmara também fica oculto em dispositivos que tenham apenas uma câmara.
Defina uma opção de seletor como `false` para fixar o utilizador na objetiva predefinida dessa etapa.```kotlin theme={null}
val configuration = Configuration(
    defaultLivenessCamera = CameraLens.BACK,
    showLivenessCameraSwitchButton = false
)
```> [!NOTE]
>
> As opções `showLanguageSelector`, `showCloseButton`, `showExitConfirmation` e `closeOnComplete` correspondem à `DiditSdkConfiguration` do Web SDK. As opções específicas para dispositivos móveis `languageLocale` e `fontFamily` existem porque o SDK para dispositivos móveis apresenta a interface completa de verificação de forma nativa (ao contrário do Web SDK, que delega no frontend alojado dentro de um iframe).> [!NOTE]
>
> **Temas e cores**: As cores, os fundos e as definições do ecrã de introdução são configurados nas suas [definições de Marca branca](https://business.didit.me) na Didit Console, e não na configuração do SDK. Isto garante uma identidade visual consistente em todas as plataformas.***## Suporte de idiomasO SDK suporta **54 idiomas**. Se não for indicado nenhum idioma, o SDK usa a localidade do dispositivo, com inglês como alternativa.```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)
```**[Ver todos os idiomas suportados →](https://docs.didit.me/pt/integration/supported-languages.md)*****## Opções avançadasPara parâmetros avançados de sessão (`contact_details`, `expected_details`, `metadata`, `callback`), use o método **Sessão no backend**. O seu backend chama a [API de criação de sessões de verificação](https://docs.didit.me/pt/sessions-api/create-session.md) com todos os parâmetros e depois transmite o `session_token` ao SDK.***## Processamento dos resultadosA classe selada `VerificationResult` indica o resultado da verificação:### Casos de resultado| Caso | Descrição |
| - | - |
| `Completed(session)` | O fluxo de verificação foi concluído (consulte `session.status` para o resultado) |
| `Cancelled(session)` | O utilizador cancelou o fluxo de verificação |
| `Failed(error, session)` | Ocorreu um erro durante a verificação |### Propriedades de SessionData| Propriedade | Tipo | Descrição |
| - | - | - |
| `sessionId` | `String` | Identificador único da sessão |
| `status` | `VerificationStatus` | `APPROVED`, `PENDING` ou `DECLINED` |### Tipos de erroTodos os erros são subclasses seladas de `me.didit.sdk.VerificationError`:| Erro | Descrição |
| - | - |
| `SessionExpired` | A sessão expirou |
| `NetworkError` | Problema de conectividade de rede |
| `CameraAccessDenied` | Permissão da câmara não concedida |
| `NotInitialized` | SDK não inicializado: chame `DiditSdk.initialize(context)` primeiro |
| `ApiError` | O backend devolveu uma resposta de erro |
| `RetryBlocked` | A verificação não pode ser repetida (por exemplo, número máximo de tentativas atingido) |
| `Unknown(message)` | Outro erro com mensagem |### Ligação perdidaSe o dispositivo perder a ligação durante a verificação, o SDK cobre o fluxo com um ecrã "Sem ligação à Internet" em vez de deixar um passo a carregar.
Continua a verificar em segundo plano e fecha o ecrã automaticamente assim que a Didit voltar a estar acessível, e o utilizador continua a partir do passo em que estava.
O ecrã oferece **Tentar novamente** e, quando `showCloseButton` tem o valor `true` (predefinido), **Sair da verificação**.
Sair termina a verificação com `VerificationResult.Failed(error = VerificationError.NetworkError, session = ...)`, para que a sua aplicação saiba que o utilizador saiu por causa da ligação.### Exemplo completo de tratamento do resultado```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
        }
    }
}
```***## Observar o estado do SDKPode observar o estado do SDK para criar uma interface de carregamento personalizada:```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 / R8O SDK inclui as suas próprias regras ProGuard para a aplicação que integra o SDK. Não é necessária nenhuma configuração adicional.Se utilizar o modo completo do R8, pode ser necessário adicionar isto ao seu `gradle.properties`:```properties theme={null}
android.enableR8.fullMode=false
```***## Exemplo de ponta a ponta (sessão no backend → SDK Android → resultado)Este padrão é a integração pronta para produção. O seu backend cria a sessão, a sua aplicação Android recebe o `session_token` e o SDK executa o fluxo.### 1. Backend: criar a sessão```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: trocar o token e iniciar o 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: receber a decisão final através de webhookO resultado do SDK é útil para o feedback na interface, mas o resultado definitivo chega através de webhook. Consulte o [Guia de webhooks](https://docs.didit.me/pt/integration/webhooks.md) para a verificação 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);
});
```***## Exemplo completo```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.