> ## 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 verificação de identidade: KYC

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



Prompt de integração do SDK 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.9.1")
}

\### 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 Android leve e orientado pelo servidor para verificação de identidade, que exige configuração mínima.> [card] [Repositório no GitHub](https://github.com/didit-protocol/sdk-android)
>
> Veja o código-fonte e exemplos no GitHub> [!NOTE]
>
> ### **SDK nativo**: esta é a abordagem recomendada para apps Android. Os SDKs nativos oferecem a melhor experiência do usuário, gerenciamento otimizado da câmera e suporte completo a NFC.***## Requisitos| Requisito | Versão mínima |
| - | - |
| API do Android | 23+ (Android 6.0 Marshmallow). A detecção automática por ML exige API 24+ (veja abaixo). |
| Kotlin | 1.9+ |
| Jetpack Compose | Incluído como dependência transitiva |> [!NOTE]
>
> **Disponibilidade de recursos por nível de API**: a detecção automática de documento e de rosto exige API 24+ (usando o runtime de ML incluído no SDK ou o runtime do Google Play services; veja as variantes do SDK). Em dispositivos com API 23, o SDK passa para a captura manual, com um botão de disparo temporizado. Todos os outros recursos funcionam em toda a faixa de API 23+.> [!NOTE]
>
> **O consentimento biométrico exige a versão nativa 4.10.0 ou posterior.** Para pessoas abrangidas pelas leis de Illinois, Texas ou Colorado, a Didit pode solicitar [consentimento biométrico](https://docs.didit.me/pt-br/getting-started/biometric-consent.md) explícito antes da primeira captura do rosto. O SDK Android 4.10.0 e versões posteriores exibem essa etapa. Versões anteriores não conseguem exibir a etapa: suas sessões funcionam como antes, e a decisão informa que o consentimento não foi coletado (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Atualize o SDK se você verifica pessoas nesses estados.***## Instalação### Etapa 1: Adicione 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 você usa `settings.gradle` (Groovy):```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```### Etapa 2: Adicione a dependênciaAdicione a dependência do SDK ao `build.gradle.kts` do seu app:
(!) Quanto à versão, confira no [repositório do GitHub](https://github.com/didit-protocol/sdk-android) qual é a mais recente.```kotlin theme={null}
dependencies {
    implementation("me.didit:didit-sdk:4.9.1")
}
```Ou, se você usa `build.gradle` (Groovy):```groovy theme={null}
dependencies {
    implementation "me.didit:didit-sdk:4.9.1"
}
```#### Variantes do SDKO SDK Android é distribuído como **cinco artefatos separados**, para que seu app só arque com o custo binário dos
recursos que usa. O `me.didit:didit-sdk` acima é o pacote completo. Escolha exatamente um, com uma única
exceção: os dois artefatos de detecção automática podem ser instalados juntos, como descrito abaixo:| Artefato | Detecção automática (ML) | Leitura do chip NFC | Quando usar |
| - | :-: | :-: | - |
| `me.didit:didit-sdk-core` | – | – | build menor; apenas captura manual de documentos |
| `me.didit:didit-sdk-autodetection` | ✓ | – | captura automática, sem leitura do chip de passaporte/documento de identidade |
| `me.didit:didit-sdk-autodetection-play` | ✓ | – | captura automática via o runtime de ML do Play services; \~9,85 MB a menos instalados por dispositivo (arm64) em comparação com o runtime incluído no pacote (veja abaixo) |
| `me.didit:didit-sdk-nfc` | – | ✓ | leitura do chip sem o runtime de ML da captura automática |
| `me.didit:didit-sdk` | ✓ | ✓ | todos os recursos (pacote completo) |##### Runtime de ML menor via Google Play services (opcional, desde a 4.7.0)O `me.didit:didit-sdk-autodetection-play` oferece a mesma captura automática de documentos e de rosto que o
`didit-sdk-autodetection`, mas executa a inferência no runtime de ML que o Google Play services já
disponibiliza no dispositivo, em vez de incluir um no seu APK.
O comportamento da detecção é idêntico (os dois mecanismos foram comparados quadro a quadro
em uma matriz de dispositivos físicos antes do lançamento) e a inferência costuma ser mais rápida no runtime do Play.Para ativar, substitua o artefato:```kotlin theme={null}
// before
implementation("me.didit:didit-sdk-autodetection:4.9.1")
// after
implementation("me.didit:didit-sdk-autodetection-play:4.9.1")
```O que muda:- **Tamanho**: cerca de **9,85 MB a menos de código nativo instalado por dispositivo (arm64)**, porque o runtime de ML
  deixa de ficar dentro do seu app. (Uma comparação com um APK universal não minificado de 4 ABIs mostra uma
  diferença maior, de \~43 MB, mas esse número contabiliza arquiteturas que nenhum dispositivo instala sozinho;
  o número por dispositivo acima é o que seus usuários realmente veem.)
- **Requisito**: Google Play services. Em dispositivos sem ele (por exemplo, dispositivos Huawei
  sem GMS), ou se o runtime do Play não conseguir inicializar, o SDK faz o fallback automaticamente:
  para o runtime incluído no pacote quando o `didit-sdk-autodetection` também está instalado, ou para a captura manual
  caso contrário. Ele nunca trava por causa de um runtime indisponível.
- **Escolha de cobertura**: distribua apenas o `-play` para ter o app menor (usuários sem GMS ficam com a captura
  manual), ou distribua os dois artefatos para manter a captura automática por ML em dispositivos sem GMS, com o
  tamanho original.Os dois artefatos exigem o `didit-sdk-core` 4.7.0 ou mais recente.> [!NOTE]
>
> O `didit-sdk-autodetection-play` é, por enquanto, opcional. A Didit acompanha seu desempenho em campo em comparação com
> o runtime incluído no pacote durante um ciclo de lançamentos após o lançamento; quando esses dados confirmarem a paridade, a expectativa é que o artefato do Play
> se torne a forma recomendada de instalar a detecção automática, e o
> `didit-sdk-autodetection` (incluído no pacote) continua sendo a recomendação padrão até lá.Desde a `4.6.0`, a assinatura nativa com carteira via WalletConnect é distribuída como um complemento opcional próprio, o `me.didit:didit-sdk-wallet`.
O pacote completo `me.didit:didit-sdk` já o inclui, então nada muda se você instalar o pacote completo.
Se você usa um dos artefatos mais enxutos e quer que a confirmação de propriedade da carteira rode nativamente dentro do seu app, adicione o `me.didit:didit-sdk-wallet` junto com ele; sem o complemento, o SDK conclui a confirmação de propriedade da carteira por um fluxo seguro no navegador, então o recurso continua funcionando de qualquer forma.
Tirar o WalletConnect do `didit-sdk-core` também removeu vários megabytes de dependências de carteira de todos os builds que não precisam delas.Todos os artefatos são publicados com a mesma versão, então mantenha todos na `4.9.1`.#### Mantendo o download pequenoOs modelos de detecção usados na captura automática são baixados em tempo de execução e armazenados em cache, então nunca contam no tamanho do seu app.
O que a captura automática adiciona ao seu app é a biblioteca nativa do runtime de ML, e esse custo é por arquitetura de 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 arcar com esse custo apenas uma vez:1) **Publique um Android App Bundle (AAB).** O Google Play entrega apenas a arquitetura e os idiomas do próprio dispositivo, então um celular arm64 instala cerca de 10 MB de código nativo (aproximadamente 4 MB de download compactado). Já um APK universal reúne as quatro arquiteturas, mais de 40 MB, o que é a causa mais comum de medições de tamanho inesperadamente grandes.

2) **Se você distribui um único APK** e seu público usa celulares e tablets ARM, restrinja as arquiteturas incluídas:

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

   Mantenha todas as ABIs que seus usuários realmente usam: adicione `x86_64` se você atende Chromebooks ou outros dispositivos x86, ou publique APKs divididos por ABI para que nenhum dispositivo perca o suporte.

3) **Ative o R8**: `isMinifyEnabled = true` e `isShrinkResources = true` no seu build type de release (`minifyEnabled true` / `shrinkResources true` se você usa `build.gradle` em Groovy). O SDK inclui suas próprias regras de consumidor, então o código não utilizado do SDK é removido sem nenhuma configuração extra.

4) **Limite os idiomas incluídos** com `resConfigs(...)` se você não precisa de todas as 48 localidades do SDK em um build de APK; as divisões por idioma do AAB cuidam disso automaticamente no Google Play.### Etapa 3: Adicione a exclusão de empacotamentoAdicione isto ao bloco `android` do seu app para evitar conflitos de build:```kotlin theme={null}
android {
    packaging {
        resources {
            excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
        }
    }
}
```Pronto! O Gradle resolve automaticamente todas as dependências transitivas.***## PermissõesO SDK exige as permissões a seguir. Elas são declaradas no `AndroidManifest.xml` do SDK e serão mescladas automaticamente ao manifesto do seu app:| 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` | Detectar a disponibilidade da rede | Sim |
| `CAMERA` | `didit-sdk-core` | Digitalização de documentos e verificação facial | Sim |
| `NFC` | `didit-sdk-nfc` | Leitura de chips NFC em passaportes e documentos de identidade | Mesclada automaticamente a partir de `didit-sdk-nfc` (dependência transitiva de `me.didit:didit-sdk`) |### Recursos de câmera e NFCO SDK declara `android.hardware.camera` e `android.hardware.nfc` como recursos opcionais (`android:required="false"`). Isso garante que o seu app possa ser instalado em dispositivos sem câmera ou sem hardware NFC, e o SDK lida de forma adequada com a ausência do hardware em tempo de execução.***## Início rápido### Etapa 1: inicializar o SDKInicialize o SDK no `Application.onCreate()`:```kotlin theme={null}
import me.didit.sdk.DiditSdk

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        DiditSdk.initialize(this)
    }
}
```### Etapa 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 oferece dois métodos de integração:### Método 1: UniLink (o mais simples)Não exige backend. O SDK cria a sessão diretamente usando o ID do seu fluxo de verificação (workflow) no 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 pelo backend (recomendado para produção)O seu backend cria a sessão pela [API de criação de sessão de verificação](https://docs.didit.me/pt-br/sessions-api/create-session.md) (`POST /v3/session/`) com suporte completo a parâmetros (`contact_details`, `expected_details`, `metadata`, `callback` etc.) e depois repassa 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)
}
```Essa abordagem dá a você controle total sobre:- A associação das sessões aos seus usuários (`vendor_data`)
- A definição de metadados personalizados
- A configuração de callbacks por sessão
- O envio de dados de contato e dados 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 | Padrão | Descrição |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | Idioma do dispositivo | Força um idioma específico |
| `showLanguageSelector` | `Boolean` | `false` | Exibe o seletor de idioma no estilo web na tela de boas-vindas |
| `fontFamily` | `String?` | Fonte do sistema | Nome do recurso de fonte personalizada (de `res/font/`) |
| `loggingEnabled` | `Boolean` | `false` | Ativa os logs de depuração do SDK |
| `showCloseButton` | `Boolean` | `true` | Exibe o botão de fechar (X) nas telas das etapas de verificação |
| `showExitConfirmation` | `Boolean` | `true` | Exibe uma caixa de diálogo de confirmação quando o usuário tenta sair |
| `closeOnComplete` | `Boolean` | `false` | Fecha automaticamente a interface de verificação ao concluir (equivalente no Web SDK: `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `CameraLens.BACK` | Lente usada quando a tela de captura do documento é aberta |
| `defaultLivenessCamera` | `CameraLens` | `CameraLens.FRONT` | Lente usada quando a tela de captura do rosto (prova de vida) é aberta |
| `showDocumentCameraSwitchButton` | `Boolean` | `true` | Exibe o seletor de câmera durante a captura na tela de captura do documento |
| `showLivenessCameraSwitchButton` | `Boolean` | `true` | Exibe o seletor de câmera durante a captura na tela de captura do rosto |### Opções de câmeraAs opções de câmera correspondem às [opções de câmera do Web SDK](https://docs.didit.me/pt-br/integration/web-sdks/javascript-sdk.md#opções-de-câmera).
Cada lente é `CameraLens.FRONT` ou `CameraLens.BACK`.
Se o dispositivo não tiver a lente solicitada, o SDK usa a primeira câmera disponível.
O seletor de câmera também fica oculto em dispositivos que têm apenas uma câmera.
Defina uma opção do seletor como `false` para restringir o usuário à lente padrão 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 exclusivas do mobile, `languageLocale` e `fontFamily`, existem porque o SDK mobile renderiza toda a interface de verificação de forma nativa (ao contrário do Web SDK, que delega ao frontend hospedado dentro de um iframe).> [!NOTE]
>
> **Temas e cores**: cores, fundos e configurações da tela de introdução são definidos nas suas [configurações de Marca própria](https://business.didit.me) no Didit Console, e não na configuração do SDK. Isso garante uma identidade visual consistente em todas as plataformas.***## Suporte a idiomasO SDK oferece suporte a **54 idiomas**. Se nenhum idioma for especificado, 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 compatíveis →](https://docs.didit.me/pt-br/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 **Backend Session**. O seu backend chama a [API de criação de sessão de verificação](https://docs.didit.me/pt-br/sessions-api/create-session.md) com todos os parâmetros e depois repassa o `session_token` ao SDK.***## Tratamento de resultadosA sealed class `VerificationResult` fornece o resultado da verificação:### Casos de resultado| Caso | Descrição |
| - | - |
| `Completed(session)` | O fluxo de verificação foi concluído (verifique `session.status` para saber o resultado) |
| `Cancelled(session)` | O usuário 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` | A permissão da câmera não foi concedida |
| `NotInitialized` | SDK não inicializado: chame `DiditSdk.initialize(context)` primeiro |
| `ApiError` | O backend retornou uma resposta de erro |
| `RetryBlocked` | Não é possível tentar a verificação novamente (por exemplo, o número máximo de tentativas foi atingido) |
| `Unknown(message)` | Outro erro, com mensagem |### Perda de conexãoSe o dispositivo perder a conexão durante a verificação, o SDK exibe uma tela "Sem conexão com a internet" durante o fluxo em vez de deixar uma etapa carregando indefinidamente.
Ele continua verificando em segundo plano e fecha a tela sozinho assim que a Didit volta a ficar acessível, e o usuário continua da etapa em que estava.
A tela oferece **Tentar novamente** e, quando `showCloseButton` é `true` (o padrão), **Sair da verificação**.
Sair encerra a verificação com `VerificationResult.Failed(error = VerificationError.NetworkError, session = ...)`, para que seu app saiba que o usuário saiu devido à perda de conexão.### Exemplo completo de tratamento de resultados```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
        }
    }
}
```***## Como observar o estado do SDKVocê pode 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 suas próprias regras do ProGuard do consumidor. Nenhuma configuração adicional é necessária.Se você usa o modo completo do R8, talvez precise 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. Seu backend cria a sessão, seu app 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 via webhookO resultado do SDK é prático para dar feedback na interface, mas o resultado oficial chega via webhook. Consulte o [guia de webhooks](https://docs.didit.me/pt-br/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.