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

> SDK nativo iOS em Swift da Didit para verificação de identidade, prova de vida biométrica e leitura NFC de passaporte. Pague pelo uso, $10 grátis/mês.



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



      
      

\<pre>

\`Integrate Didit identity verification into my iOS app using the native Swift SDK (DiditSDK 4.9.1).

\## Requirements
\- iOS 13.0+, Xcode 15.0+, Swift 5.9+
\- NFC chip reading requires iOS 15+ and a compatible device with NFC hardware
\- Since 4.0.0 the SDK ships in four variants; pick exactly one:
\- Core (DiditSDKCore): no NFC, no auto-detection, no OpenSSL, iOS 13.0+, smallest binary (manual capture only)
\- AutoDetection (DiditSDKAutoDetection): ML auto-capture, no NFC, no OpenSSL, iOS 13.0+
\- NFC (DiditSDKNFC): NFC passport reading, bundles OpenSSL 3.3.3, iOS 15.0+
\- All (DiditSDK — default): every feature, bundles OpenSSL 3.3.3, iOS 15.0+

\## Installation

\### Option A: Swift Package Manager (recommended)
1\. In Xcode: File > Add Package Dependencies
2\. Enter URL: https://github.com/didit-protocol/sdk-ios.git
3\. Select version 4.9.1 (or "Up to Next Major") and click Add Package
4\. Add exactly one library product for your variant:
\- All (NFC + auto-detection): product "DiditSDK"
\- Core (no NFC, no auto-detection): product "DiditSDKCore"
\- AutoDetection (auto-capture, no NFC): product "DiditSDKAutoDetection"
\- NFC (NFC, no auto-detection): product "DiditSDKNFC"

In Package.swift:
.package(url: "https://github.com/didit-protocol/sdk-ios.git", from: "4.9.1")
Then add one product, e.g. .product(name: "DiditSDK", package: "DiditSDK") or .product(name: "DiditSDKCore", package: "DiditSDK"). Your code always writes import DiditSDK regardless of variant.

\### Option B: CocoaPods (binary podspec — DiditSDK is not on the public Trunk)
podspec_url = 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.9.1/DiditSDK.podspec'
\# Pick exactly one subspec:
\# All (NFC + auto-detection, iOS 15+):
platform :ios, '15.0'
pod 'DiditSDK/All', :podspec => podspec_url
\# Core (no NFC, no auto-detection, iOS 13+):        pod 'DiditSDK/Core', :podspec => podspec_url
\# AutoDetection (auto-capture, no NFC, iOS 13+):    pod 'DiditSDK/AutoDetection', :podspec => podspec_url
\# NFC (NFC, no auto-detection, iOS 15+):            pod 'DiditSDK/NFC', :podspec => podspec_url

Then run: pod install
Open the .xcworkspace (not .xcodeproj).

On Xcode 15+ if you hit rsync "Operation not permitted", set Build Setting ENABLE_USER_SCRIPT_SANDBOXING to No on the project (Debug and Release).

\## Required Permissions (Info.plist)
\- NSCameraUsageDescription (required) — Document scanning and face verification
\- NSMicrophoneUsageDescription (required) — Video recording for liveness checks
\- NSPhotoLibraryUsageDescription (required) — Upload documents from gallery
\- NFCReaderUsageDescription (only if using the NFC or All variant) — Read NFC chips in passports/IDs
\- NSLocationWhenInUseUsageDescription (optional) — Geolocation for fraud prevention

\## NFC Configuration (NFC or All variant only — skip for the Core or AutoDetection variants)
1\. Add "Near Field Communication Tag Reading" capability in Xcode > Signing & Capabilities
2\. Add ISO7816 identifiers to Info.plist:
com.apple.developer.nfc.readersession.iso7816.select-identifiers:
\["D23300000045737445494420763335", "A0000002471001", "A0000002472001", "00000000000000", "D392F000260100000001"]
(D392F000260100000001 is the Japan My Number Card's JPKI application: without it, iOS does not report that card to the SDK.)
3\. Add to entitlements file:
com.apple.developer.nfc.readersession.formats: ["TAG"]

\## 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 iOS app (never expose DIDIT_API_KEY to the device).

\## SwiftUI Integration (recommended)
import SwiftUI
import DiditSDK

struct ContentView: View {
var body: some View {
    Button("Verify Identity") {
        // Option A: With session token from your backend (recommended)
        DiditSdk.shared.startVerification(token: "session-token-from-backend")

        // Option B: With workflow ID (SDK creates session internally — UniLink, vendorData only)
        // DiditSdk.shared.startVerification(workflowId: "your-workflow-id", vendorData: "user-id")
    }
    .diditVerification { result in
        switch result {
        case .completed(let session):
            // session.status: VerificationStatus = .approved | .pending | .declined
            if session.status == .approved { /* grant access */ }
        case .cancelled(let session):
            // User dismissed the flow; session may be nil if none was created
            \_ = session
        case .failed(let error, _):
            // VerificationError — show error.localizedDescription
            \_ = error
        }
    }
}
}

\## Programmatically dismissing the verification (3.6.0+)
Call DiditSdk.shared.dismiss() to end an active verification (e.g. on app backgrounding).
It dismisses the UI, resets state, and fires the .diditVerification handler with .cancelled(session:).
Do NOT toggle DiditSdk.shared.isPresented = false or call UIKit dismiss() on the topmost VC — that bypasses the completion pipeline.

\## Result Statuses (SDK enum / API string)
\- .approved / "Approved"  — user identity verified, grant access
\- .declined / "Declined"  — verification failed, show retry or contact support
\- .pending  / "In Review" — 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 iOS app)
\- DIDIT_API_KEY — from Didit Console > API & Webhooks
\- DIDIT_WORKFLOW_ID — from Didit Console > Workflows

\## App Store Note
If you ship the NFC or All variant, Apple may request an NFC demo video during review. Request ours from [support@didit.me](mailto:support@didit.me).

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

\</pre>



      
      

Colar em

Um SDK para iOS leve e controlado pelo servidor para verificação de identidade, que exige o mínimo de configuração. **Versão mais recente: 4.9.1.**> [card] [Repositório no GitHub](https://github.com/didit-protocol/sdk-ios)
>
> Veja o código-fonte, as versões e o changelog completo no GitHub> [!NOTE]
>
> ### **SDK nativo**: esta é a abordagem recomendada para apps iOS. Os SDKs nativos oferecem a melhor experiência do usuário, uso otimizado da câmera e suporte completo a NFC.***## Requisitos| Requisito | Versão mínima |
| - | - |
| iOS | 13.0+ |
| Xcode | 15.0+ |
| Swift | 5.9+ |### Compatibilidade com versões do iOS| Versão do iOS | Recursos disponíveis |
| - | - |
| iOS 13.0 - 14.x | Todos os recursos, **exceto** a leitura NFC de passaportes |
| iOS 15.0+ | Todos os recursos, incluindo a leitura NFC de passaportes |> [!NOTE]
>
> **O consentimento biométrico exige o SDK nativo 4.10.0 ou posterior.** Para pessoas às quais se aplicam as 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 facial. O SDK para iOS 4.10.0 e posteriores exibe 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 se você verifica pessoas nesses estados.***## InstalaçãoDesde a `4.0.0`, o SDK é distribuído em **quatro variantes instaláveis**, para que sua aplicação só arque com o custo de binário dos recursos que usa. Escolha exatamente uma variante: um subspec do CocoaPods e um produto de biblioteca do SwiftPM:| Variante | CocoaPods | Produto SwiftPM | NFC | Detecção automática | OpenSSL | iOS mínimo |
| - | - | - | :-: | :-: | - | - |
| **Core** | `DiditSDK/Core` | `DiditSDKCore` | – | – | nenhum | iOS 13.0+ |
| **AutoDetection** | `DiditSDK/AutoDetection` | `DiditSDKAutoDetection` | – | ✓ | nenhum | iOS 13.0+ |
| **NFC** | `DiditSDK/NFC` | `DiditSDKNFC` | ✓ | – | `3.3.3` incluído | iOS 15.0+ |
| **All** (padrão) | `DiditSDK/All` | `DiditSDK` | ✓ | ✓ | `3.3.3` incluído | iOS 15.0+ |- **Core**: menor tamanho, apenas captura manual. Sem `OpenSSL.xcframework`, sem runtime do CoreNFC, sem runtime de ML.
- **AutoDetection**: captura automática de documento e rosto baseada em ML, mas sem leitura de chip NFC.
- **NFC**: leitura do chip NFC de passaporte/eID sem o runtime de ML da captura automática.
- **All**: todos os recursos. É o padrão quando você instala o `DiditSDK` sem indicar um subspec/produto.Quanto cada variante acrescenta ao bundle da sua aplicação (Mach-O arm64, medido na `4.9.0`): **Core** \~11,1 MB, **NFC** \~11,7 MB mais \~4 MB de OpenSSL, **AutoDetection** \~16,0 MB, **All** \~16,6 MB mais OpenSSL.
Os próprios modelos de detecção são baixados em tempo de execução e armazenados em cache, então nunca contam no tamanho de download da sua aplicação.Desde a `4.7.1`, as variantes **AutoDetection** e **All** executam a inferência da captura automática em um runtime de ML mais enxuto, no lugar do runtime MediaPipe usado até a `4.6.0`. Trata-se de uma transição, não de uma variante opcional: ela se aplica incondicionalmente a quem estiver na `4.7.1` ou posterior, portanto não existe uma variante separada com o "motor anterior" para instalar no lugar. Medido nos artefatos de release: **-3,4 MB (-28%)** no payload de download comprimido da App Store e **-8,5 MB (-35%)** no binário arm64 distribuído dentro da sua aplicação (o próprio framework descomprimido da fatia de dispositivo fica cerca de 12 MB menor). Antes do release, verifica-se que o comportamento de detecção é idêntico, quadro a quadro, ao do motor anterior em uma matriz de dispositivos físicos, e a inferência de documentos é mensuravelmente mais rápida.> [!NOTE]
>
> **Revertendo a mudança de runtime**: como isso é uma transição e não uma variante, revertê-la significa fixar sua dependência na `4.6.0` (SwiftPM: selecione a versão `4.6.0` em vez de "Up to Next Major"; CocoaPods: aponte o `podspec_url` para a tag `4.6.0`), e não alternar uma flag. A Didit acompanha o desempenho em campo desse runtime durante um ciclo de releases após o lançamento; se surgir uma regressão, a resposta será um aviso para fixar a versão anterior e um patch release no runtime atual, nunca uma troca de variante, já que ela não existe.Desde a `4.6.0`, os frameworks distribuídos não trazem mais descritores de ABI do Swift (metadados de build que o Xcode copiava para toda aplicação, mas nunca lia) nem vídeos tutoriais que a variante não consegue reproduzir. Só atualizar a partir da `4.5.4` ou anterior já reduz sua aplicação em cerca de 7-8 MB, sem nenhuma alteração de código.
A App Store comprime os binários para a entrega, então o custo de download pela rede é menor. Consulte o relatório de tamanho da aplicação no App Store Connect para ver a diferença exata por dispositivo.> [!NOTE]
>
> As variantes **NFC** e **All** incluem o `OpenSSL.xcframework` (**OpenSSL 3.3.3**, distribuído como `OpenSSL-Universal 3.3.3001` via `NFCPassportReader`), necessário para a autenticação do chip NFC e que exige iOS 15.0+. Os releases **até a 4.0.6, inclusive,** incluíam o OpenSSL `1.1.1s`; a **4.0.7 e posteriores** trazem o OpenSSL 3.3.3 com seu próprio privacy manifest e assinatura de código. Instale sempre a **4.0.7 ou posterior**. Observe que atualizar alinha as *versões* do OpenSSL, mas não elimina conflitos de *embed*: se outra dependência da sua aplicação também incorporar um `OpenSSL.framework` (mesmo nome de arquivo, mesmo bundle id `com.github.krzyzanowskim.OpenSSL`), as duas cópias entram em conflito na etapa de embed, independentemente da versão. Mantenha exatamente uma cópia: por exemplo, substitua o outro pacote usando a identidade do SPM para usar o `OpenSSL.xcframework` publicado pela Didit, de modo que o binário no bundle seja aquele com o qual este SDK foi compilado. As variantes **Core** e **AutoDetection** não vinculam nenhum OpenSSL.O `import DiditSDK` no código da sua aplicação é o mesmo, seja qual for a variante instalada.### Swift Package Manager (recomendado)Adicione o pacote ao seu projeto pelo Xcode:1) Acesse **File > Add Package Dependencies**
2) Informe a URL do repositório:```
https://github.com/didit-protocol/sdk-ios.git
```3) Selecione a versão (ou **Up to Next Major** a partir da `4.9.1`) e clique em **Add Package**
4) Quando for solicitado a escolher um produto, escolha exatamente um produto de biblioteca para a sua variante (veja a tabela acima)Ou no seu `Package.swift`:```swift theme={null}
dependencies: [
    .package(url: "https://github.com/didit-protocol/sdk-ios.git", from: "4.9.1")
]
```Em seguida, adicione exatamente um destes produtos ao seu target:```swift theme={null}
// All (default — NFC + auto-detection)
.product(name: "DiditSDK", package: "DiditSDK")

// Core (no NFC, no auto-detection, no OpenSSL)
.product(name: "DiditSDKCore", package: "DiditSDK")

// AutoDetection (auto-capture, no NFC)
.product(name: "DiditSDKAutoDetection", package: "DiditSDK")

// NFC (NFC passport reading, no auto-detection)
.product(name: "DiditSDKNFC", package: "DiditSDK")
```> [!WARNING]
>
> **O Swift Package Manager não impõe o mínimo de iOS 15 por você.** O `Package.swift` declara
> `platforms: [.iOS(.v13)]` para o pacote inteiro, então o Xcode permite adicionar `DiditSDK` ou
> `DiditSDKNFC` a um target de iOS 13 ou 14 sem reclamar, mas ambos incluem o `OpenSSL.xcframework`
> e leem chips por meio do `NFCPassportReader`, que exigem **iOS 15.0+**. Defina você mesmo o deployment
> target do seu target como 15.0 ao usar o produto `All` ou `NFC`. O CocoaPods impõe isso
> automaticamente por meio do `deployment_target` do subspec.### CocoaPodsO `DiditSDK` é distribuído como um podspec binário hospedado no repositório (ele não está no CocoaPods Trunk público), então você deve referenciar a URL do podspec. Escolha exatamente um subspec:```ruby theme={null}
podspec_url = 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.9.1/DiditSDK.podspec'

# All (NFC + auto-detection, iOS 15.0+):
platform :ios, '15.0'
pod 'DiditSDK/All', :podspec => podspec_url

# Core (no NFC, no auto-detection, iOS 13.0+):
# pod 'DiditSDK/Core', :podspec => podspec_url

# AutoDetection (auto-capture, no NFC, iOS 13.0+):
# pod 'DiditSDK/AutoDetection', :podspec => podspec_url

# NFC (NFC passport reading, iOS 15.0+):
# pod 'DiditSDK/NFC', :podspec => podspec_url
````Core` e `AutoDetection` funcionam a partir do iOS 13; `NFC` e `All` exigem iOS 15 por causa do `NFCPassportReader`.Depois, execute:```bash theme={null}
pod install
```> [!NOTE]
>
> Após o `pod install`, abra o `.xcworkspace` gerado (não o `.xcodeproj`).> [!NOTE]
>
> **Erros de rsync no Xcode 15+**: se aparecerem erros de rsync `Operation not permitted` durante o build, defina **Build Settings → User Script Sandboxing** (`ENABLE_USER_SCRIPT_SANDBOXING`) como **No** no projeto, tanto para Debug quanto para Release.### Manual (XCFramework)Cada versão publica um XCFramework por variante. Baixe os arquivos zip da sua variante na página [GitHub Releases](https://github.com/didit-protocol/sdk-ios/releases), depois arraste as pastas `.xcframework` para o Xcode e defina **Embed & Sign**.| Variante | Download |
| - | - |
| **Core** | `DiditSDK-Core.xcframework.zip` |
| **AutoDetection** | `DiditSDK-AutoDetection.xcframework.zip` |
| **NFC** | `DiditSDK-NFC.xcframework.zip` + `OpenSSL.xcframework.zip` |
| **All** | `DiditSDK.xcframework.zip` + `OpenSSL.xcframework.zip` |***## PermissõesO SDK exige as permissões a seguir. Adicione-as ao `Info.plist` do seu app:| Permissão | Chave do Info.plist | Descrição | Obrigatória |
| - | - | - | - |
| Câmera | `NSCameraUsageDescription` | Digitalização de documentos e verificação facial | ✅ Sim |
| Microfone | `NSMicrophoneUsageDescription` | Gravação de vídeo para as checagens de prova de vida | ✅ Sim |
| Fotos | `NSPhotoLibraryUsageDescription` | Envio de documentos da galeria do dispositivo | ✅ Sim |
| NFC | `NFCReaderUsageDescription` | Leitura de chips NFC em passaportes/documentos de identidade | ⚠️ Somente SDK completo |
| Localização | `NSLocationWhenInUseUsageDescription` | Geolocalização para prevenção de fraudes | ❌ Opcional |### Exemplo de entradas no Info.plist```xml theme={null}
<key>NSCameraUsageDescription</key>
<string>Camera access is required to scan your identity documents for verification.</string>

<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required to record video for liveness verification.</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is required to upload document images.</string>

<key>NFCReaderUsageDescription</key>
<string>NFC access is required to read the chip in your identity document.</string>

<key>NSLocationWhenInUseUsageDescription</key>
<string>Location access helps verify your identity and prevent fraud.</string>
```### Configuração de NFCNecessária apenas ao instalar a variante **NFC** ou **All**. Pule esta seção se você instalou a variante **Core** ou **AutoDetection**.Para habilitar a leitura NFC de passaportes e documentos de identidade com chip:1) **Adicione a capability de NFC** no Xcode:
   * Selecione seu target → **Signing & Capabilities** → **+ Capability** → **Near Field Communication Tag Reading**

2) **Adicione os identificadores ISO7816** ao `Info.plist`:```xml theme={null}
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>D23300000045737445494420763335</string>
    <string>A0000002471001</string>
    <string>A0000002472001</string>
    <string>00000000000000</string>
    <string>D392F000260100000001</string>
</array>
````D392F000260100000001` permite que o SDK leia o My Number Card do Japão por meio do [JPKI](https://docs.didit.me/pt-br/core-technology/nfc-verification/overview.md#my-number-card-do-japão-jpki): sem ele, o iOS não informa o SDK sobre o cartão. A leitura do My Number Card ainda não está habilitada em produção, e o identificador não altera nada para outros documentos, então você já pode adicioná-lo.3) **Adicione os entitlements** (no seu arquivo `.entitlements`):```xml theme={null}
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
```> [!WARNING]
>
> **Limitação do simulador (variantes NFC e All)**: essas variantes vinculam o CoreNFC e, desde o Xcode 12, o `libnfshared.dylib` não existe nos simuladores. Consulte [esta discussão no Stack Overflow](https://stackoverflow.com/questions/63915728/xcode12-corenfc-simulator-library-not-loaded) para uma solução alternativa. Isso **não** se aplica à variante **Core** nem à **AutoDetection**. Teste os recursos de NFC apenas em dispositivos físicos.> [!NOTE]
>
> ### **Revisão da App Store (variantes NFC e All)**: se você instalar a variante **NFC** ou **All**, a Apple pode solicitar um vídeo de demonstração durante a revisão, porque há código relacionado a NFC no binário do SDK — mesmo que seu fluxo de verificação (workflow) não use NFC. Solicite nosso vídeo de demonstração de NFC para enviar à Apple pelo [support@didit.me](mailto:support@didit.me). Isso não se aplica à variante **Core** nem à **AutoDetection**.***## Início rápido### Integração com SwiftUI```swift theme={null}
import SwiftUI
import DiditSDK

struct ContentView: View {
    var body: some View {
        Button("Verify Identity") {
            // Method 1: UniLink — no backend required
            DiditSdk.shared.startVerification(workflowId: "your-workflow-id")
            
            // Method 2: Backend Session — full parameter control
            // DiditSdk.shared.startVerification(token: "your-session-token")
        }
        .diditVerification { result in
            handleResult(result)
        }
    }
    
    private func handleResult(_ result: VerificationResult) {
        switch result {
        case .completed(let session):
            print("Completed: \(session.status)")
        case .cancelled(let session):
            print("Cancelled")
        case .failed(let error, _):
            print("Failed: \(error.localizedDescription)")
        }
    }
}
```### Integração com UIKit```swift theme={null}
import UIKit
import DiditSDK

class VerificationViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Start verification when ready
        DiditSdk.shared.startVerification(token: "your-session-token")
    }
}
```***## 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 fluxo obtido no [Didit Console](https://business.didit.me). O método UniLink (`startVerification(workflowId:)`) aceita apenas `vendorData`; para qualquer outro parâmetro de sessão, use o Método 2.> [!NOTE]
>
> Para que o `vendorData` seja anexado à sessão via UniLink, habilite a opção **Vendor Data** no [Didit Console](https://business.didit.me).```swift theme={null}
DiditSdk.shared.startVerification(
    workflowId: "your-workflow-id",
    vendorData: "user-123"
)
```### Método 2: Sessão criada no backend (recomendado para produçã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.```swift theme={null}
// Your backend creates a session and returns the token
let sessionToken = await yourBackend.createVerificationSession(userId: currentUser.id)

// Pass the token to the SDK
DiditSdk.shared.startVerification(token: sessionToken)
```Essa abordagem dá a você controle total sobre:- A associação das sessões aos seus usuários (`vendor_data`)
- A definição de dados de contato e dados esperados para validação cruzada
- A definição de metadados personalizados
- A configuração de callbacks por sessão
  Esses dados (dados de contato, dados esperados, metadados, callback) são enviados à [API de criação de sessão de verificação](https://docs.didit.me/pt-br/sessions-api/create-session.md).***## ConfiguraçãoPersonalize o comportamento do SDK com `DiditSdk.Configuration`:```swift theme={null}
let configuration = DiditSdk.Configuration(
    languageLocale: .spanish,      // Force Spanish language
    showLanguageSelector: true,    // Let the user change language
    fontFamily: "Avenir",          // Custom font (must be registered in your app)
    loggingEnabled: true,          // Enable debug logging
    showCloseButton: true,         // Show close (X) button on step screens
    showExitConfirmation: true,    // Show confirmation dialog when user taps close
    closeOnComplete: false         // Don't auto-dismiss on completion
)

DiditSdk.shared.startVerification(
    token: "your-session-token",
    configuration: configuration
)
```### Opções de configuração| Propriedade | Tipo | Padrão | Descrição |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | Localidade do dispositivo | Força um idioma específico |
| `showLanguageSelector` | `Bool` | `false` | Exibe o seletor de idioma no estilo web na tela de boas-vindas |
| `fontFamily` | `String?` | Fonte do sistema | Nome da família de fontes personalizada (deve estar registrada no seu app via `UIAppFonts` no `Info.plist`) |
| `loggingEnabled` | `Bool` | `false` | Ativa os logs de depuração do SDK |
| `showCloseButton` | `Bool` | `true` | Exibe o botão de fechar (X) nas telas das etapas de verificação |
| `showExitConfirmation` | `Bool` | `true` | Exibe uma caixa de diálogo de confirmação quando o usuário tenta sair |
| `closeOnComplete` | `Bool` | `false` | Fecha automaticamente a interface de verificação ao concluir (equivalente no Web SDK: `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `.back` | Lente usada quando a tela de captura do documento é aberta |
| `defaultLivenessCamera` | `CameraLens` | `.front` | Lente usada quando a tela de captura do rosto (prova de vida) é aberta |
| `showDocumentCameraSwitchButton` | `Bool` | `true` | Exibe o seletor de câmera durante a captura na tela de captura do documento |
| `showLivenessCameraSwitchButton` | `Bool` | `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 é `.front` ou `.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 de seletor como `false` para restringir o usuário à lente padrão daquela etapa.```swift theme={null}
let configuration = DiditSdk.Configuration(
    defaultLivenessCamera: .back,
    showLivenessCameraSwitchButton: false
)
```> [!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.> [!NOTE]
>
> As opções `showLanguageSelector`, `showCloseButton`, `showExitConfirmation` e `closeOnComplete` correspondem ao `DiditSdkConfiguration` do Web SDK. As opções específicas para mobile `languageLocale` e `fontFamily` existem porque o SDK mobile renderiza toda a interface de verificação de forma nativa (diferentemente do Web SDK, que delega ao frontend hospedado dentro de um iframe).***## Suporte a idiomasO SDK oferece suporte a **54 idiomas**. Se nenhum idioma for especificado, o SDK usa a idioma do dispositivo, com o inglês como alternativa.```swift theme={null}
// Use device locale (default)
let config = DiditSdk.Configuration()

// Force specific language
let config = DiditSdk.Configuration(languageLocale: .french)

// Let the user change language on the welcome screen
let config = DiditSdk.Configuration(showLanguageSelector: true)

// Detect device locale programmatically
let deviceLanguage = SupportedLanguage.fromDeviceLocale()
```**[Ver todos os idiomas suportados →](https://docs.didit.me/pt-br/integration/supported-languages.md)*****## Parâmetros avançados de sessãoPara parâmetros avançados de sessão (`contact_details`, `expected_details`, `metadata`, `callback`), use o método **Backend Session**. 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, em seguida, passa o `session_token` ao SDK.***## Tratamento de resultadosO enum `VerificationResult` fornece 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 ver 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` |
| `country` | `String?` | Código do país (ISO 3166-1 alpha-3) |
| `documentType` | `String?` | Tipo de documento usado na verificação |### Tipos de erro| Erro | Descrição |
| - | - |
| `.sessionExpired` | A sessão expirou |
| `.networkError` | Problema de conectividade de rede |
| `.cameraAccessDenied` | Permissão de câmera não concedida |
| `.unknown(String)` | Outro erro, com mensagem |### Perda de conexãoSe o dispositivo perder a conexão durante a verificação, o SDK exibe uma tela de "Sem conexão com a internet", em vez de deixar uma etapa carregando.
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 a partir 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 `.failed(error: .networkError, session:)`, para que seu app saiba que o usuário saiu devido à perda de conexão.### Exemplo completo de tratamento de resultados```swift theme={null}
.diditVerification { result in
    switch result {
    case .completed(let session):
        switch session.status {
        case .approved:
            print("✅ Approved! Session: \(session.sessionId)")
            // User is verified - grant access
            
        case .pending:
            print("⏳ Under review. Session: \(session.sessionId)")
            // Show "verification in progress" UI
            
        case .declined:
            print("❌ Declined. Session: \(session.sessionId)")
            // Handle declined verification
        }
        
    case .cancelled(let session):
        if let session = session {
            print("🚫 Cancelled session: \(session.sessionId)")
        }
        // User chose to cancel - maybe show retry option
        
    case .failed(let error, let session):
        print("⚠️ Error: \(error.localizedDescription)")
        // Handle error - show retry or contact support
    }
}
```***## Encerrar a verificação programaticamente> [!NOTE]
>
> Disponível no DiditSDK **3.6.0+**.O app host pode encerrar programaticamente uma verificação ativa com `DiditSdk.shared.dismiss()`. Essa é a forma recomendada de encerrar a verificação quando o host precisa assumir a tela, por exemplo, quando o app vai para segundo plano.```swift theme={null}
DiditSdk.shared.dismiss()
````dismiss()` passa pelo pipeline de conclusão normal do SDK: ele fecha a UI apresentada, redefine o estado interno e chama o handler `.diditVerification` com `.cancelled(session:)`, com o `sessionId` atual se uma sessão tiver sido criada. Quando não há nenhuma verificação ativa, a chamada não tem efeito.### Exemplo: encerrar quando o app vai para segundo plano```swift theme={null}
NotificationCenter.default.addObserver(
    forName: UIApplication.didEnterBackgroundNotification,
    object: nil,
    queue: .main
) { _ in
    DiditSdk.shared.dismiss()
}
```> [!WARNING]
>
> **Não** defina `DiditSdk.shared.isPresented = false` para encerrar a verificação: o flag só dispara a apresentação na transição de falso para verdadeiro, e defini-lo como `false` não tem efeito. Da mesma forma, chamar o `dismiss(animated:)` do UIKit no view controller mais acima na hierarquia não é suportado: isso ignora o pipeline de conclusão do SDK, e o seu handler `.diditVerification` nunca é disparado.***## Observando o estado do SDKVocê pode observar o estado do SDK para criar uma UI de carregamento personalizada:```swift theme={null}
struct CustomView: View {
    @ObservedObject private var sdk = DiditSdk.shared
    
    var body: some View {
        VStack {
            switch sdk.state {
            case .idle:
                Text("Ready to verify")
            case .creatingSession:
                ProgressView("Creating session...")
            case .loading:
                ProgressView("Loading...")
            case .ready:
                Text("Verification in progress")
            case .error(let message):
                Text("Error: \(message)")
            }
        }
    }
}
```***## Exemplo de ponta a ponta (sessão no backend → SDK iOS → resultado)Esse padrão é a integração pronta para produção. O seu backend cria a sessão, o seu app iOS 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. iOS: trocar o token e iniciar o SDK```swift theme={null}
import SwiftUI
import DiditSDK

struct VerifyButton: View {
    let userId: String
    @State private var error: String?

    var body: some View {
        Button("Verify Identity") {
            Task { await start() }
        }
        .diditVerification { result in
            switch result {
            case .completed(let session) where session.status == .approved:
                // Optimistically reflect success in the UI; rely on the webhook
                // delivered to your backend as the source of truth.
                break
            case .completed(let session):
                print("Terminal status: \(session.status.rawValue)")
            case .cancelled:
                print("User cancelled")
            case .failed(let err, _):
                error = err.localizedDescription
            }
        }
    }

    private func start() async {
        do {
            var req = URLRequest(url: URL(string: "https://your-backend.example.com/api/verification/start")!)
            req.httpMethod = "POST"
            req.setValue("application/json", forHTTPHeaderField: "Content-Type")
            req.httpBody = try JSONEncoder().encode(["userId": userId])

            let (data, _) = try await URLSession.shared.data(for: req)
            struct Payload: Decodable { let session_token: String }
            let payload = try JSONDecoder().decode(Payload.self, from: data)

            await MainActor.run {
                DiditSdk.shared.startVerification(token: payload.session_token)
            }
        } catch {
            self.error = error.localizedDescription
        }
    }
}
```### 3. Backend: receber a decisão final via webhookO resultado do SDK é prático para dar retorno na UI, 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 em SwiftUI```swift theme={null}
import SwiftUI
import DiditSDK

struct HomeView: View {
    @State private var resultMessage: String?
    @State private var isVerified = false
    
    var body: some View {
        VStack(spacing: 24) {
            if isVerified {
                Image(systemName: "checkmark.circle.fill")
                    .font(.system(size: 64))
                    .foregroundColor(.green)
                Text("Identity Verified")
                    .font(.title2)
            } else {
                Button("Verify Identity") {
                    startVerification()
                }
                .font(.headline)
                .padding(.horizontal, 32)
                .padding(.vertical, 16)
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(12)
            }
            
            if let message = resultMessage {
                Text(message)
                    .foregroundColor(.secondary)
                    .multilineTextAlignment(.center)
                    .padding()
            }
        }
        .diditVerification { result in
            handleResult(result)
        }
    }
    
    private func startVerification() {
        let config = DiditSdk.Configuration(
            languageLocale: .english
        )
        
        // Method 1: UniLink — no backend required
        DiditSdk.shared.startVerification(
            workflowId: "your-workflow-id",
            vendorData: "user-123",
            configuration: config
        )
        
        // Method 2: Backend Session — full parameter control
        // DiditSdk.shared.startVerification(
        //     token: "your-session-token",
        //     configuration: config
        // )
    }
    
    private func handleResult(_ result: VerificationResult) {
        switch result {
        case .completed(let session):
            if session.status == .approved {
                isVerified = true
            }
            resultMessage = """
                Status: \(session.status.rawValue)
                Session: \(session.sessionId)
                Country: \(session.country ?? "N/A")
                Document: \(session.documentType ?? "N/A")
                """
                
        case .cancelled(let session):
            resultMessage = "Cancelled - Session: \(session?.sessionId ?? "unknown")"
            
        case .failed(let error, _):
            resultMessage = "Failed: \(error.localizedDescription)"
        }
    }
}
```***


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