> ## 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 vérification d'identité : KYC mobile

> SDK iOS Swift de Didit pour la vérification d'identité, la détection du vivant et la lecture NFC des passeports. $10 gratuits/mois, sans contrat.



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



      
      

\<pre>

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

\## 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.13.2 (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.13.2")
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.13.2/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>



      
      

Coller dans

Un SDK iOS léger, piloté par le serveur, pour la vérification d'identité avec une configuration minimale. **Dernière version : 4.13.2.**> [card] [Dépôt GitHub](https://github.com/didit-protocol/sdk-ios)
>
> Consultez le code source, les versions et le journal des modifications complet sur GitHub> [!NOTE]
>
> ### **SDK natif**: Il s'agit de l'approche recommandée pour les applications iOS. Les SDK natifs offrent la meilleure expérience utilisateur, une gestion optimisée de la caméra et la prise en charge complète du NFC.***## Prérequis| Exigence | Version minimale |
| - | - |
| iOS | 13.0+ |
| Xcode | 15.0+ |
| Swift | 5.9+ |### Compatibilité des versions d'iOS| Version d'iOS | Fonctionnalités disponibles |
| - | - |
| iOS 13.0 - 14.x | Toutes les fonctionnalités **sauf** la lecture NFC du passeport |
| iOS 15.0+ | Toutes les fonctionnalités, y compris la lecture NFC du passeport |> [!NOTE]
>
> **Le consentement biométrique nécessite la version 4.10.0 ou ultérieure du SDK natif.** Pour les personnes couvertes par les lois de l'Illinois, du Texas ou du Colorado, Didit peut demander un [consentement biométrique](https://docs.didit.me/fr/getting-started/biometric-consent.md) explicite avant la première capture faciale. Le SDK iOS 4.10.0 et les versions ultérieures affichent cette étape. Les versions antérieures ne peuvent pas afficher cette étape : leurs sessions se déroulent comme auparavant, et la décision indique que le consentement n'a pas été recueilli (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Mettez à jour si vous vérifiez des personnes dans ces États.***## InstallationDepuis la version `4.0.0`, le SDK est livré en plusieurs variantes installables. Votre application n'embarque ainsi que le poids binaire des fonctionnalités qu'elle utilise. Choisissez exactement une variante : une sous-spécification CocoaPods et un produit de bibliothèque SwiftPM.| Variante | CocoaPods | Produit SwiftPM | NFC | Détection automatique | OpenSSL | iOS minimum |
| - | - | - | :-: | :-: | - | - |
| **Core** | `DiditSDK/Core` | `DiditSDKCore` | – | ✓ | aucun | iOS 13.0+ |
| **AutoDetection** (obsolète) | `DiditSDK/AutoDetection` | `DiditSDKAutoDetection` | – | ✓ | aucun | iOS 13.0+ |
| **NFC** | `DiditSDK/NFC` | `DiditSDKNFC` | ✓ | ✓ | `3.3.3` inclus | iOS 15.0+ |
| **All** (par défaut) | `DiditSDK/All` | `DiditSDK` | ✓ | ✓ | `3.3.3` inclus | iOS 15.0+ |- **Core** : la variante la plus légère, avec capture automatique du document et du selfie grâce aux détecteurs légers propres à Didit. Pas de `OpenSSL.xcframework`, pas de runtime CoreNFC.
- **AutoDetection** : obsolète depuis la version 4.11.0 et identique à **Core** ; utilisez plutôt **Core**.
- **NFC** : **Core** plus la lecture des puces des passeports et des cartes d'identité électroniques (eID) en NFC.
- **All** : toutes les fonctionnalités. C'est la variante par défaut lorsque vous installez `DiditSDK` sans nommer de sous-spécification ni de produit.Ce que chaque variante ajoute au bundle de votre application (Mach-O arm64, mesuré avec la version `4.9.0`) : **Core** environ 11,1 MB, **NFC** environ 11,7 MB plus environ 4 MB d'OpenSSL, **AutoDetection** environ 16,0 MB, **All** environ 16,6 MB plus OpenSSL.
Les modèles de détection sont eux-mêmes téléchargés à l'exécution puis mis en cache. Ils ne comptent donc jamais dans la taille de téléchargement de votre application.Depuis la version `4.11.0`, la capture automatique repose sur les détecteurs légers propres à Didit, dans toutes les variantes. TensorFlow Lite ne fait plus partie du SDK. Le framework est plus petit, car ses traductions sont chargées depuis l'extérieur du binaire.Depuis la version `4.6.0`, les frameworks livrés ne contiennent plus les descripteurs ABI Swift (métadonnées de build que Xcode copiait dans chaque application sans jamais les lire) ni les vidéos didactiques que la variante ne peut pas lire. La mise à niveau depuis la version `4.5.4` ou antérieure réduit donc votre application d'environ 7-8 MB à elle seule, sans modification de code.
L'App Store compresse les binaires pour la livraison, de sorte que le coût réel au téléchargement est plus faible. Consultez le rapport de taille d'application dans App Store Connect pour connaître l'écart exact par appareil.> [!NOTE]
>
> Les variantes **NFC** et **All** embarquent `OpenSSL.xcframework` (**OpenSSL 3.3.3**, livré sous la forme `OpenSSL-Universal 3.3.3001` via `NFCPassportReader`), nécessaire à l'authentification des puces NFC, et elles exigent iOS 15.0+. Les versions **jusqu'à la 4.0.6 incluse** embarquaient OpenSSL `1.1.1s` ; les **versions 4.0.7 et ultérieures** livrent OpenSSL 3.3.3 avec son propre manifeste de confidentialité et sa propre signature de code. Installez toujours la **version 4.0.7 ou ultérieure**. Notez que la mise à niveau aligne les *versions* d'OpenSSL, mais ne supprime pas les conflits d'*embarquement* : si une autre dépendance de votre application embarque aussi un `OpenSSL.framework` (même nom de fichier, même identifiant de bundle `com.github.krzyzanowskim.OpenSSL`), les deux copies entrent en conflit lors de l'étape d'embarquement, quelle que soit leur version. Ne gardez qu'une seule copie. Par exemple, remplacez l'autre paquet en utilisant son identité SPM pour utiliser le `OpenSSL.xcframework` publié par Didit, afin que le binaire présent dans le bundle soit celui avec lequel ce SDK a été compilé. Les variantes **Core** et **AutoDetection** n'associent aucune bibliothèque OpenSSL.`import DiditSDK` reste identique dans le code de votre application, quelle que soit la variante installée.### Swift Package Manager (recommandé)Ajoutez le paquet à votre projet avec Xcode :1) Allez dans **File > Add Package Dependencies**
2) Saisissez l'URL du dépôt :```
https://github.com/didit-protocol/sdk-ios.git
```3) Sélectionnez la version (ou **Up to Next Major** à partir de `4.13.2`), puis cliquez sur **Add Package**
4) Lorsqu'on vous demande de choisir un produit, sélectionnez exactement un produit de bibliothèque correspondant à votre variante (voir le tableau ci-dessus)Ou dans votre `Package.swift` :```swift theme={null}
dependencies: [
    .package(url: "https://github.com/didit-protocol/sdk-ios.git", from: "4.13.2")
]
```Ajoutez ensuite exactement un de ces produits à votre cible :```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]
>
> **Swift Package Manager n'applique pas à votre place le minimum iOS 15.** `Package.swift` déclare `platforms: [.iOS(.v13)]` pour l'ensemble du paquet. Xcode vous laissera donc ajouter `DiditSDK` ou `DiditSDKNFC` à une cible iOS 13 ou 14 sans broncher. Or ces deux produits embarquent `OpenSSL.xcframework` et lisent les puces via `NFCPassportReader`, qui exigent **iOS 15.0+**. Réglez vous-même la version minimale de déploiement de votre cible sur 15.0 lorsque vous utilisez le produit `All` ou `NFC`. CocoaPods applique cette règle automatiquement grâce au paramètre `deployment_target` de la sous-spécification.### CocoaPods`DiditSDK` est distribué sous forme de podspec binaire hébergé dans le dépôt (il ne figure pas sur le CocoaPods Trunk public). Vous devez donc indiquer l'URL du podspec. Choisissez exactement une sous-spécification :```ruby theme={null}
podspec_url = 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.13.2/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` et `AutoDetection` fonctionnent à partir d'iOS 13. `NFC` et `All` exigent iOS 15 à cause de `NFCPassportReader`.Exécutez ensuite :```bash theme={null}
pod install
```> [!NOTE]
>
> Après `pod install`, ouvrez le fichier `.xcworkspace` généré (et non le `.xcodeproj`).> [!NOTE]
>
> **Erreurs rsync avec Xcode 15+** : si vous voyez des erreurs rsync `Operation not permitted` pendant le build, réglez **Build Settings → User Script Sandboxing** (`ENABLE_USER_SCRIPT_SANDBOXING`) sur **Non** pour le projet, en Debug comme en Release.### Manuel (XCFramework)Chaque version publie un XCFramework par variante. Téléchargez les archives zip de votre variante depuis la page [GitHub Releases](https://github.com/didit-protocol/sdk-ios/releases), faites glisser les dossiers `.xcframework` dans Xcode, puis réglez **Embed & Sign**.| Variante | Téléchargement |
| - | - |
| **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` |***## AutorisationsLe SDK nécessite les autorisations suivantes. Ajoutez-les au fichier `Info.plist` de votre application :| Autorisation | Clé Info.plist | Description | Obligatoire |
| - | - | - | - |
| Caméra | `NSCameraUsageDescription` | Numérisation des documents et vérification faciale | ✅ Oui |
| Microphone | `NSMicrophoneUsageDescription` | Enregistrement vidéo pour les contrôles de détection du vivant | ✅ Oui |
| Photothèque | `NSPhotoLibraryUsageDescription` | Importation de documents depuis la galerie de l'appareil | ✅ Oui |
| NFC | `NFCReaderUsageDescription` | Lecture des puces NFC des passeports et cartes d'identité | ⚠️ SDK complet uniquement |
| Localisation | `NSLocationWhenInUseUsageDescription` | Géolocalisation pour la prévention de la fraude | ❌ Facultatif |### Exemples d'entrées 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>
```### Configuration NFCObligatoire uniquement lors de l'installation de la variante **NFC** ou **All**. Ignorez cette section si vous avez installé la variante **Core** ou **AutoDetection**.Pour activer la lecture NFC des passeports et cartes d'identité à puce :1) **Ajoutez la capacité NFC** dans Xcode :
   * Sélectionnez votre cible → **Signing & Capabilities** → **+ Capability** → **Near Field Communication Tag Reading**

2) **Ajoutez les identifiants ISO7816 à `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` permet au SDK de lire la Japan My Number Card via [JPKI](https://docs.didit.me/fr/core-technology/nfc-verification/overview.md#carte-my-number-japonaise-jpki) : sans lui, iOS ne transmet pas la carte au SDK. La lecture de la My Number Card n'est pas encore activée en production, et cet identifiant ne change rien pour les autres documents : vous pouvez donc l'ajouter dès maintenant.3) **Ajoutez les droits** (dans votre fichier `.entitlements`) :```xml theme={null}
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
```> [!WARNING]
>
> **Limitation du simulateur (variantes NFC et All)** : Ces variantes lient CoreNFC, et depuis Xcode 12, `libnfshared.dylib` est absent des simulateurs. Consultez [ce fil Stack Overflow](https://stackoverflow.com/questions/63915728/xcode12-corenfc-simulator-library-not-loaded) pour une solution de contournement. Cela ne s'applique **pas** aux variantes **Core** ou **AutoDetection**. Testez les fonctionnalités NFC uniquement sur des appareils physiques.> [!NOTE]
>
> ### **Examen App Store (variantes NFC et All)** : Si vous installez la variante **NFC** ou **All**, Apple peut demander une vidéo de démonstration pendant l'examen, car du code lié à la NFC fait partie du binaire du SDK, même si votre workflow n'utilise pas la NFC. Demandez notre vidéo de démonstration NFC à l’adresse [support@didit.me](mailto:support@didit.me) pour la soumettre à Apple. Cela ne s'applique pas à la variante **Core** ou **AutoDetection**.***## Démarrage rapide### Intégration 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)")
        }
    }
}
```### Intégration 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éthodes d'intégrationLe SDK prend en charge deux méthodes d'intégration :### Méthode 1 : UniLink (la plus simple)Aucun backend requis. Le SDK crée la session directement à partir de l'identifiant de votre workflow dans la [Didit Console](https://business.didit.me). La méthode UniLink (`startVerification(workflowId:)`) ne prend en charge que `vendorData` : pour tout autre paramètre de session, utilisez la méthode 2.> [!NOTE]
>
> Pour que `vendorData` soit associé à la session via UniLink, activez l'option **Données du vendeur** dans la [Didit Console](https://business.didit.me).```swift theme={null}
DiditSdk.shared.startVerification(
    workflowId: "your-workflow-id",
    vendorData: "user-123"
)
```### Méthode 2 : session backend (recommandée pour la production)Votre backend crée la session via l'[API de création de session de vérification](https://docs.didit.me/fr/sessions-api/create-session.md) (`POST /v3/session/`), qui prend en charge l'ensemble des paramètres (`contact_details`, `expected_details`, `metadata`, `callback`, etc.), puis transmet le `session_token` au 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)
```Cette approche vous donne un contrôle total sur :- L'association des sessions à vos utilisateurs (`vendor_data`)
- La définition des coordonnées et des informations attendues pour la validation croisée
- La définition de métadonnées personnalisées
- La configuration des callbacks par sessionCes données (coordonnées, informations attendues, métadonnées, callback) sont envoyées à l'[API de création de session de vérification](https://docs.didit.me/fr/sessions-api/create-session.md).***## ConfigurationPersonnalisez le comportement du SDK avec `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
)
```### Options de configuration| Propriété | Type | Valeur par défaut | Description |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | Paramètres régionaux de l'appareil | Forcer une langue spécifique |
| `showLanguageSelector` | `Bool` | `false` | Afficher le sélecteur de langue de type Web sur l'écran d'accueil |
| `fontFamily` | `String?` | Police du système | Nom de la famille de polices personnalisée (doit être enregistrée dans votre application via `UIAppFonts` dans `Info.plist`) |
| `loggingEnabled` | `Bool` | `false` | Activer la journalisation de débogage du SDK |
| `showCloseButton` | `Bool` | `true` | Afficher le bouton de fermeture (X) sur les écrans des étapes de vérification |
| `showExitConfirmation` | `Bool` | `true` | Afficher une boîte de dialogue de confirmation lorsque l'utilisateur tente de quitter |
| `closeOnComplete` | `Bool` | `false` | Fermer automatiquement l'interface de vérification une fois terminée (équivalent du SDK Web : `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `.back` | Objectif utilisé à l'ouverture de l'écran de capture du document |
| `defaultLivenessCamera` | `CameraLens` | `.front` | Objectif utilisé à l'ouverture de l'écran de capture du visage (détection du vivant) |
| `showDocumentCameraSwitchButton` | `Bool` | `true` | Afficher le sélecteur de caméra pendant la capture sur l'écran de capture du document |
| `showLivenessCameraSwitchButton` | `Bool` | `true` | Afficher le sélecteur de caméra pendant la capture sur l'écran de capture du visage |### Options de caméraLes options de caméra correspondent aux [options de caméra du SDK Web](https://docs.didit.me/fr/integration/web-sdks/javascript-sdk.md#options-de-caméra).
Chaque objectif est `.front` ou `.back`.
Si l'appareil ne dispose pas de l'objectif demandé, le SDK utilise la première caméra disponible.
Le sélecteur de caméra est également masqué sur les appareils qui n'ont qu'une seule caméra.
Définissez une option de sélecteur sur `false` pour verrouiller l'utilisateur sur l'objectif par défaut de cette étape.```swift theme={null}
let configuration = DiditSdk.Configuration(
    defaultLivenessCamera: .back,
    showLivenessCameraSwitchButton: false
)
```> [!NOTE]
>
> **Thème et couleurs** : les couleurs, les arrière-plans et les paramètres de l'écran d'introduction se configurent dans vos [paramètres de marque blanche](https://business.didit.me) dans la Didit Console, et non dans la configuration du SDK. Cela garantit une identité visuelle cohérente sur toutes les plateformes.> [!NOTE]
>
> Les options `showLanguageSelector`, `showCloseButton`, `showExitConfirmation` et `closeOnComplete` correspondent à `DiditSdkConfiguration` du SDK Web. Les options propres au mobile `languageLocale` et `fontFamily` existent parce que le SDK mobile affiche l'intégralité de l'interface de vérification de manière native (contrairement au SDK Web, qui délègue l'interface frontend hébergée dans un iframe).***## Langues prises en chargeLe SDK prend en charge **54 langues**. Si aucune langue n'est spécifiée, le SDK utilise les paramètres régionaux de l'appareil, avec l'anglais en repli.```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()
```**[Voir toutes les langues prises en charge →](https://docs.didit.me/fr/integration/supported-languages.md)*****## Paramètres de session avancésPour les paramètres de session avancés (`contact_details`, `expected_details`, `metadata`, `callback`), utilisez la méthode **Session backend**. Votre backend appelle l'[API de création de session de vérification](https://docs.didit.me/fr/sessions-api/create-session.md) avec l'ensemble des paramètres, puis transmet le `session_token` au SDK.***## Gestion des résultatsL'énumération `VerificationResult` fournit le résultat de la vérification :### Cas de résultat| Cas | Description |
| - | - |
| `.completed(session:)` | Flux de vérification terminé (vérifiez `session.status` pour le résultat) |
| `.cancelled(session:)` | L'utilisateur a annulé le flux de vérification |
| `.failed(error:session:)` | Une erreur s'est produite pendant la vérification |### Propriétés de SessionData| Propriété | Type | Description |
| - | - | - |
| `sessionId` | `String` | Identifiant unique de la session |
| `status` | `VerificationStatus` | `.approved`, `.pending` ou `.declined` |
| `country` | `String?` | Code pays (ISO 3166-1 alpha-3) |
| `documentType` | `String?` | Type de document utilisé pour la vérification |### Types d'erreurs| Erreur | Description |
| - | - |
| `.sessionExpired` | La session a expiré |
| `.networkError` | Problème de connectivité réseau |
| `.cameraAccessDenied` | Autorisation de la caméra non accordée |
| `.unknown(String)` | Autre erreur accompagnée d'un message |### Connexion perdueSi l'appareil perd sa connexion pendant la vérification, le SDK affiche par-dessus le flux un écran « Aucune connexion Internet » au lieu de laisser une étape en cours de chargement.
Il continue de vérifier la connexion en arrière-plan et ferme l'écran dès que Didit redevient joignable. L'utilisateur reprend alors à l'étape où il se trouvait.
L'écran propose **Réessayer** et, lorsque `showCloseButton` est `true` (valeur par défaut), **Quitter la vérification**.
Quitter met fin à la vérification avec `.failed(error: .networkError, session:)`, afin que votre application sache que l'utilisateur est parti à cause de la connexion.### Exemple complet de gestion des résultats```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
    }
}
```***## Fermer programmatiquement la vérification> [!NOTE]
>
> Disponible dans DiditSDK **3.6.0+**.L'application hôte peut mettre fin à une vérification en cours par programmation avec `DiditSdk.shared.dismiss()`. C'est la méthode recommandée pour arrêter la vérification lorsque l'application doit reprendre le contrôle de l'écran, par exemple lorsqu'elle passe en arrière-plan.```swift theme={null}
DiditSdk.shared.dismiss()
````dismiss()` passe par la chaîne de traitement de fin habituelle du SDK : il ferme l'interface présentée, réinitialise l'état interne et appelle le gestionnaire `.diditVerification` avec `.cancelled(session:)`, qui transporte le `sessionId` courant si une session a été créée. Cette méthode est sans effet lorsqu'aucune vérification n'est active.### Exemple de fermeture lorsque l'application passe en arrière-plan```swift theme={null}
NotificationCenter.default.addObserver(
    forName: UIApplication.didEnterBackgroundNotification,
    object: nil,
    queue: .main
) { _ in
    DiditSdk.shared.dismiss()
}
```> [!WARNING]
>
> Ne **définissez** pas `DiditSdk.shared.isPresented = false` pour fermer la vérification : cet indicateur ne déclenche la présentation que sur son front montant, et le mettre à `false` est sans effet. De même, appeler `dismiss(animated:)` d'UIKit sur le contrôleur de vue au sommet n'est pas pris en charge : cela contourne la chaîne de traitement de fin du SDK, si bien que votre gestionnaire `.diditVerification` n'est jamais déclenché.***## Observer l'état du SDKVous pouvez observer l'état du SDK pour personnaliser l'interface de chargement :```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)")
            }
        }
    }
}
```***## Exemple de bout en bout (session backend → SDK iOS → résultat)Ce schéma correspond à une intégration prête pour la production. Votre backend crée la session, votre application iOS reçoit le `session_token`, et le SDK exécute le parcours.### 1. Côté backend, création de la session```ts theme={null}
// Node.js / Express example. Run on your server. NEVER ship DIDIT_API_KEY to the device.
import express from "express";

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

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

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

  const { session_id, session_token } = await response.json();
  // Persist session_id <-> userId so you can match the webhook later.
  res.json({ session_id, session_token });
});
```### 2. Côté iOS, échange du token et démarrage du 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. Côté backend, réception de la décision finale par webhookLe résultat du SDK est pratique pour le retour à l'utilisateur, mais le résultat faisant autorité est transmis par webhook. Consultez le [guide des webhooks](https://docs.didit.me/fr/integration/webhooks.md) pour la vérification HMAC.```ts theme={null}
app.post("/api/webhooks/didit", express.raw({ type: "application/json" }), (req, res) => {
  // 1. Verify the X-Signature header (see Webhooks docs)
  // 2. Parse the body
  const event = JSON.parse(req.body.toString());
  if (event.webhook_type === "status.updated") {
    // event.session_id, event.status ("Approved" | "Declined" | "In Review" | ...)
    // Look up the user by session_id and update their verification state.
  }
  res.sendStatus(200);
});
```***## Exemple SwiftUI complet```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.