> ## 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.

# iOS Swift SDK für Identitätsverifizierung: Mobiles KYC

> Natives iOS Swift SDK von Didit für Ausweisverifizierung, Liveness-Erkennung & NFC-Scan. Pay-per-Use-Preise, $10 gratis/Monat, ohne Vertrag.



Prompt zur Integration des iOS-SDK
        Prompt in die Zwischenablage kopieren



      
      

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



      
      

Einfügen in

Ein schlankes, serverbasiertes iOS-SDK für die Identitätsverifizierung, das nur minimale Konfiguration erfordert. **Neueste Version: 4.13.2.**> [card] [GitHub-Repository](https://github.com/didit-protocol/sdk-ios)
>
> Quellcode, Releases und das vollständige Changelog auf GitHub ansehen> [!NOTE]
>
> ### **Native SDK**: Dies ist der empfohlene Ansatz für iOS-Apps. Native SDKs bieten die beste Nutzererfahrung, optimierte Kamerasteuerung und volle NFC-Unterstützung.***## Voraussetzungen| Anforderung | Mindestversion |
| - | - |
| iOS | 13.0+ |
| Xcode | 15.0+ |
| Swift | 5.9+ |### iOS-Versionskompatibilität| iOS-Version | Verfügbare Funktionen |
| - | - |
| iOS 13.0 - 14.x | Alle Funktionen **außer** NFC-Passauslesen |
| iOS 15.0+ | Alle Funktionen inklusive NFC-Passauslesen |> [!NOTE]
>
> **Biometrische Einwilligung erfordert das native SDK ab Version 4.10.0.** Für Personen, die unter die Gesetze von Illinois, Texas oder Colorado fallen, kann Didit vor der ersten Gesichtserfassung eine ausdrückliche [biometrische Einwilligung](https://docs.didit.me/de/getting-started/biometric-consent.md) einholen. Das iOS-SDK ab Version 4.10.0 zeigt diesen Schritt an. Ältere Versionen können den Schritt nicht anzeigen: Ihre Sitzungen laufen wie zuvor ab, und die Entscheidung meldet die Einwilligung als nicht erfasst (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Führen Sie ein Upgrade durch, wenn Sie Personen in diesen Bundesstaaten verifizieren.***## InstallationSeit `4.0.0` wird das SDK in mehreren installierbaren Varianten ausgeliefert, sodass Ihre App nur die Binärgröße der Funktionen trägt, die sie tatsächlich nutzt. Wählen Sie genau eine Variante aus, also genau ein CocoaPods-Subspec und genau ein SwiftPM-Bibliotheksprodukt:| Variante | CocoaPods | SwiftPM-Produkt | NFC | Auto-Erkennung | OpenSSL | Mindest-iOS |
| - | - | - | :-: | :-: | - | - |
| **Core** | `DiditSDK/Core` | `DiditSDKCore` | – | ✓ | keines | iOS 13.0+ |
| **AutoDetection** (veraltet) | `DiditSDK/AutoDetection` | `DiditSDKAutoDetection` | – | ✓ | keines | iOS 13.0+ |
| **NFC** | `DiditSDK/NFC` | `DiditSDKNFC` | ✓ | ✓ | `3.3.3` enthalten | iOS 15.0+ |
| **All** (Standard) | `DiditSDK/All` | `DiditSDK` | ✓ | ✓ | `3.3.3` enthalten | iOS 15.0+ |- **Core**: der kleinste Footprint, mit automatischer Dokument- und Selfie-Aufnahme über die eigenen schlanken Detektoren von Didit. Kein `OpenSSL.xcframework`, keine CoreNFC-Laufzeitumgebung.
- **AutoDetection**: seit 4.11.0 veraltet und identisch mit **Core**. Verwenden Sie stattdessen **Core**.
- **NFC**: **Core** plus das Auslesen von NFC-Chips in Reisepässen und eID-Karten.
- **All**: alle Funktionen. Dies ist die Standardvariante, wenn Sie `DiditSDK` ohne Angabe eines Subspecs oder Produkts installieren.Was jede Variante zum App-Bundle hinzufügt (arm64 Mach-O, gemessen an `4.9.0`): **Core** etwa 11,1 MB, **NFC** etwa 11,7 MB plus etwa 4 MB OpenSSL, **AutoDetection** etwa 16,0 MB, **All** etwa 16,6 MB plus OpenSSL.
Die Erkennungsmodelle selbst werden zur Laufzeit heruntergeladen und zwischengespeichert, sodass sie niemals in die Download-Größe Ihrer App eingerechnet werden.Seit `4.11.0` läuft die automatische Aufnahme in jeder Variante über die eigenen schlanken Detektoren von Didit. TensorFlow Lite ist nicht mehr Bestandteil des SDK, und das Framework ist kleiner, weil seine Übersetzungen von außerhalb der Binärdatei geladen werden.Seit `4.6.0` enthalten die ausgelieferten Frameworks keine Swift-ABI-Deskriptoren (Build-Metadaten, die Xcode in jede App kopiert, aber nie liest) und keine Tutorial-Videos, die die Variante nicht abspielen kann. Wenn Sie von `4.5.4` oder einer früheren Version aktualisieren, wird Ihre App allein dadurch um etwa 7-8 MB kleiner, ohne Codeänderungen.
Der App Store komprimiert Binärdateien für die Auslieferung, daher fallen die Kosten der Over-the-Air-Übertragung geringer aus. Den genauen Unterschied pro Gerät finden Sie im App-Größenbericht in App Store Connect.> [!NOTE]
>
> Die Varianten **NFC** und **All** bündeln `OpenSSL.xcframework` (**OpenSSL 3.3.3**, ausgeliefert als `OpenSSL-Universal 3.3.3001` über `NFCPassportReader`), das für die NFC-Chip-Authentifizierung erforderlich ist und iOS 15.0+ voraussetzt. Releases **bis einschließlich 4.0.6** bündelten OpenSSL `1.1.1s`; **ab 4.0.7** wird OpenSSL 3.3.3 mit eigenem Privacy-Manifest und eigener Code-Signatur ausgeliefert. Installieren Sie daher immer **4.0.7 oder neuer**. Beachten Sie, dass das Upgrade zwar die OpenSSL-*Versionen* angleicht, aber keine *Embed-Konflikte* beseitigt: Wenn eine andere Abhängigkeit in Ihrer App ebenfalls ein `OpenSSL.framework` einbettet (gleicher Dateiname, gleiche Bundle-ID `com.github.krzyzanowskim.OpenSSL`), kollidieren beide Kopien im Embed-Schritt unabhängig von der Version. Behalten Sie genau eine Kopie bei, zum Beispiel indem Sie das andere Paket anhand seiner SPM-Identität überschreiben, um das von Didit veröffentlichte `OpenSSL.xcframework` zu verwenden. So ist die Binärdatei im Bundle dieselbe, gegen die dieses SDK gebaut wurde. Die Varianten **Core** und **AutoDetection** binden überhaupt kein OpenSSL ein.`import DiditSDK` ist in Ihrem App-Code unabhängig von der installierten Variante gleich.### Swift Package Manager (empfohlen)Fügen Sie das Paket mit Xcode zu Ihrem Projekt hinzu:1) Öffnen Sie **File > Add Package Dependencies**
2) Geben Sie die Repository-URL ein:```
https://github.com/didit-protocol/sdk-ios.git
```3) Wählen Sie die Version (oder **Up to Next Major** ab `4.13.2`) und klicken Sie auf **Add Package**
4) Wenn Sie aufgefordert werden, ein Produkt auszuwählen, wählen Sie genau ein Bibliotheksprodukt für Ihre Variante (siehe Tabelle oben)Oder in Ihrer `Package.swift`:```swift theme={null}
dependencies: [
    .package(url: "https://github.com/didit-protocol/sdk-ios.git", from: "4.13.2")
]
```Fügen Sie dann genau eines dieser Produkte zu Ihrem Target hinzu:```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 erzwingt die Untergrenze iOS 15 nicht für Sie.** `Package.swift` deklariert
> `platforms: [.iOS(.v13)]` für das gesamte Paket. Xcode lässt Sie daher `DiditSDK` oder
> `DiditSDKNFC` ohne Beanstandung zu einem iOS-13- oder iOS-14-Target hinzufügen. Beide bündeln jedoch `OpenSSL.xcframework` und lesen Chips über `NFCPassportReader`, was **iOS 15.0+** voraussetzt. Setzen Sie das Deployment-Target Ihres Targets selbst auf 15.0, wenn Sie das Produkt `All` oder `NFC` verwenden. CocoaPods erzwingt dies automatisch über das `deployment_target` des Subspecs.### CocoaPods`DiditSDK` wird als binäres Podspec im Repository bereitgestellt. Es ist nicht im öffentlichen CocoaPods-Trunk verfügbar, daher müssen Sie die URL des Podspecs angeben. Wählen Sie genau ein Subspec aus:```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` und `AutoDetection` unterstützen iOS 13 als Mindestversion. `NFC` und `All` erfordern iOS 15 wegen `NFCPassportReader`.Führen Sie danach aus:```bash theme={null}
pod install
```> [!NOTE]
>
> Öffnen Sie nach `pod install` die erzeugte `.xcworkspace`-Datei (nicht die `.xcodeproj`-Datei).> [!NOTE]
>
> **rsync-Fehler in Xcode 15+**: Wenn während des Builds rsync-Fehler mit `Operation not permitted` auftreten, setzen Sie **Build Settings → User Script Sandboxing** (`ENABLE_USER_SCRIPT_SANDBOXING`) für das Projekt sowohl für Debug als auch für Release auf **No**.### Manuell (XCFramework)Jedes Release veröffentlicht ein XCFramework pro Variante. Laden Sie die ZIP-Dateien für Ihre Variante von [GitHub Releases](https://github.com/didit-protocol/sdk-ios/releases) herunter, ziehen Sie dann die `.xcframework`-Ordner in Xcode und setzen Sie **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` |***## BerechtigungenDas SDK erfordert die folgenden Berechtigungen. Fügen Sie diese der `Info.plist` Ihrer App hinzu:| Berechtigung | Info.plist-Schlüssel | Beschreibung | Erforderlich |
| - | - | - | - |
| Kamera | `NSCameraUsageDescription` | Dokumentenscan und Gesichtsverifizierung | ✅ Ja |
| Mikrofon | `NSMicrophoneUsageDescription` | Videoaufnahme für Liveness-Prüfungen | ✅ Ja |
| Fotomediathek | `NSPhotoLibraryUsageDescription` | Dokumente aus der Gerätegalerie hochladen | ✅ Ja |
| NFC | `NFCReaderUsageDescription` | NFC-Chips in Reisepässen/Ausweisen auslesen | ⚠️ Nur im vollständigen SDK |
| Standort | `NSLocationWhenInUseUsageDescription` | Geolokalisierung zur Betrugsprävention | ❌ Optional |### Beispielhafte Info.plist-Einträge```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>
```### NFC-KonfigurationNur erforderlich bei der Installation der Variante **NFC** oder **All**. Überspringen Sie diesen Abschnitt, wenn Sie die Variante **Core** oder **AutoDetection** installiert haben.So aktivieren Sie das Auslesen von NFC-Chips für Reisepässe und Ausweise mit Chip:1) **NFC-Capability hinzufügen** in Xcode:
   * Wählen Sie Ihr Target aus → **Signing & Capabilities** → **+ Capability** → **Near Field Communication Tag Reading**

2) **ISO7816-Identifikatoren hinzufügen** zu `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` ermöglicht dem SDK das Auslesen der japanischen My Number Card über [JPKI](https://docs.didit.me/de/core-technology/nfc-verification/overview.md#japan-my-number-card-jpki): Ohne diesen Identifikator gibt iOS die Karte nicht an das SDK weiter. Das Auslesen der My Number Card ist in der Produktion noch nicht aktiviert, und der Identifikator ändert nichts für andere Dokumente, sodass Sie ihn bereits jetzt hinzufügen können.3) **Entitlements hinzufügen** (in Ihrer `.entitlements`-Datei):```xml theme={null}
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
```> [!WARNING]
>
> **Simulator-Einschränkung (NFC- und All-Varianten)**: Diese Varianten binden CoreNFC ein, und seit Xcode 12 fehlt `libnfshared.dylib` in Simulatoren. Siehe [diesen Stack-Overflow-Thread](https://stackoverflow.com/questions/63915728/xcode12-corenfc-simulator-library-not-loaded) für einen Workaround. Dies gilt **nicht** für die Variante **Core** oder **AutoDetection**. Testen Sie NFC-Funktionen ausschließlich auf physischen Geräten.> [!NOTE]
>
> ### **App-Store-Prüfung (NFC- und All-Varianten)**: Wenn Sie die Variante **NFC** oder **All** installieren, verlangt Apple während der Prüfung möglicherweise ein Demo-Video, da NFC-bezogener Code Teil der SDK-Binärdatei ist – selbst wenn Ihr Workflow kein NFC verwendet. Fordern Sie unser NFC-Demo-Video zur Einreichung bei Apple unter [support@didit.me](mailto:support@didit.me) an. Dies gilt nicht für die Variante **Core** oder **AutoDetection**.***## Schnellstart### SwiftUI-Integration```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)")
        }
    }
}
```### UIKit-Integration```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")
    }
}
```***## IntegrationsmethodenDas SDK unterstützt zwei Integrationsmethoden:### Methode 1: UniLink (Am einfachsten)Kein Backend erforderlich. Das SDK erstellt die Sitzung direkt mit Ihrer Workflow-ID aus der [Didit Console](https://business.didit.me). Die UniLink-Methode (`startVerification(workflowId:)`) unterstützt nur `vendorData`; für alle anderen Sitzungsparameter verwenden Sie Methode 2.> [!NOTE]
>
> Damit `vendorData` über UniLink an die Sitzung angehängt werden kann, aktivieren Sie die Option **Vendor Data** in der [Didit Console](https://business.didit.me).```swift theme={null}
DiditSdk.shared.startVerification(
    workflowId: "your-workflow-id",
    vendorData: "user-123"
)
```### Methode 2: Backend-Sitzung (Empfohlen für die Produktion)Ihr Backend erstellt die Sitzung über die [Create Verification Session API](https://docs.didit.me/de/sessions-api/create-session.md) (`POST /v3/session/`) mit vollständiger Parameterunterstützung (`contact_details`, `expected_details`, `metadata`, `callback` usw.) und übergibt anschließend das `session_token` an das 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)
```Dieser Ansatz gibt Ihnen die volle Kontrolle über:- Die Verknüpfung von Sitzungen mit Ihren Benutzern (`vendor_data`)
- Das Festlegen von Kontaktdaten und erwarteten Details für den Kreuzabgleich
- Das Setzen benutzerdefinierter Metadaten
- Das Konfigurieren von Callbacks pro Sitzung
  Diese Daten (Kontaktdaten, erwartete Details, Metadaten, Callback) werden an die [Create Verification Session API](https://docs.didit.me/de/sessions-api/create-session.md) gesendet.***## KonfigurationPassen Sie das Verhalten des SDKs mit `DiditSdk.Configuration` an:```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
)
```### Konfigurationsoptionen| Eigenschaft | Typ | Standard | Beschreibung |
| - | - | - | - |
| `languageLocale` | `SupportedLanguage?` | Geräte-Locale | Bestimmte Sprache erzwingen |
| `showLanguageSelector` | `Bool` | `false` | Web-ähnliche Sprachauswahl auf dem Willkommensbildschirm anzeigen |
| `fontFamily` | `String?` | Systemschrift | Benutzerdefinierter Name der Schriftfamilie (muss in Ihrer App über `UIAppFonts` in der `Info.plist` registriert sein) |
| `loggingEnabled` | `Bool` | `false` | SDK-Debug-Protokollierung aktivieren |
| `showCloseButton` | `Bool` | `true` | Schließen-Schaltfläche (X) auf den Bildschirmen der Verifizierungsschritte anzeigen |
| `showExitConfirmation` | `Bool` | `true` | Bestätigungsdialog anzeigen, wenn der Benutzer versucht, den Vorgang zu beenden |
| `closeOnComplete` | `Bool` | `false` | Verifizierungs-UI nach Abschluss automatisch schließen (Web-SDK-Äquivalent: `closeModalOnComplete`) |
| `defaultDocumentCamera` | `CameraLens` | `.back` | Objektiv, das beim Öffnen des Bildschirms zur Dokumentenerfassung verwendet wird |
| `defaultLivenessCamera` | `CameraLens` | `.front` | Objektiv, das beim Öffnen des Bildschirms zur Gesichtserfassung (Liveness) verwendet wird |
| `showDocumentCameraSwitchButton` | `Bool` | `true` | Kamerawechsel-Schaltfläche während der Aufnahme auf dem Bildschirm zur Dokumentenerfassung anzeigen |
| `showLivenessCameraSwitchButton` | `Bool` | `true` | Kamerawechsel-Schaltfläche während der Aufnahme auf dem Bildschirm zur Gesichtserfassung anzeigen |### KameraoptionenDie Kameraoptionen entsprechen den [Web-SDK-Kameraoptionen](https://docs.didit.me/de/integration/web-sdks/javascript-sdk.md#kameraoptionen).
Jedes Objektiv ist `.front` oder `.back`.
Wenn das Gerät nicht über das angeforderte Objektiv verfügt, verwendet das SDK die erste verfügbare Kamera.
Auf Geräten mit nur einer Kamera wird der Kamerawechsler ebenfalls ausgeblendet.
Setzen Sie eine Kamerawechseloption auf `false`, um den Benutzer auf das Standardobjektiv dieses Schritts festzulegen.```swift theme={null}
let configuration = DiditSdk.Configuration(
    defaultLivenessCamera: .back,
    showLivenessCameraSwitchButton: false
)
```> [!NOTE]
>
> **Gestaltung und Farben**: Farben, Hintergründe und Einstellungen für den Startbildschirm werden über Ihre [White-Label-Einstellungen](https://business.didit.me) in der Didit Console konfiguriert, nicht in der SDK-Konfiguration. Dies gewährleistet ein einheitliches Branding über alle Plattformen hinweg.> [!NOTE]
>
> Die Optionen `showLanguageSelector`, `showCloseButton`, `showExitConfirmation` und `closeOnComplete` entsprechen der `DiditSdkConfiguration` des Web SDKs. Die mobilspezifischen Optionen `languageLocale` und `fontFamily` existieren, da das mobile SDK die gesamte Verifizierungs-UI nativ rendert (im Gegensatz zum Web SDK, das dies an das gehostete Frontend innerhalb eines iFrames delegiert).***## SprachunterstützungDas SDK unterstützt **54 Sprachen**. Wenn keine Sprache angegeben wird, verwendet das SDK die Geräte-Locale mit Englisch als Fallback.```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()
```**[Alle unterstützten Sprachen anzeigen →](https://docs.didit.me/de/integration/supported-languages.md)*****## Erweiterte SitzungsparameterVerwenden Sie für erweiterte Sitzungsparameter (`contact_details`, `expected_details`, `metadata`, `callback`) die Methode **Backend-Sitzung**. Ihr Backend ruft die [API zur Erstellung von Verifizierungssitzungen](https://docs.didit.me/de/sessions-api/create-session.md) mit allen Parametern auf und übergibt anschließend das `session_token` an das SDK.***## Ergebnisse verarbeitenDas `VerificationResult`-Enum liefert das Ergebnis der Verifizierung:### Ergebnisfälle| Fall | Beschreibung |
| - | - |
| `.completed(session:)` | Verifizierungs-Workflow abgeschlossen (überprüfen Sie `session.status` für das Ergebnis) |
| `.cancelled(session:)` | Benutzer hat den Verifizierungs-Workflow abgebrochen |
| `.failed(error:session:)` | Während der Verifizierung ist ein Fehler aufgetreten |### SessionData-Eigenschaften| Eigenschaft | Typ | Beschreibung |
| - | - | - |
| `sessionId` | `String` | Eindeutige Sitzungskennung |
| `status` | `VerificationStatus` | `.approved`, `.pending` oder `.declined` |
| `country` | `String?` | Ländercode (ISO 3166-1 Alpha-3) |
| `documentType` | `String?` | Für die Verifizierung verwendeter Dokumenttyp |### Fehlertypen| Fehler | Beschreibung |
| - | - |
| `.sessionExpired` | Die Sitzung ist abgelaufen |
| `.networkError` | Problem mit der Netzwerkverbindung |
| `.cameraAccessDenied` | Kameraberechtigung nicht erteilt |
| `.unknown(String)` | Sonstiger Fehler mit Nachricht |### VerbindungsabbruchWenn das Gerät während der Verifizierung die Verbindung verliert, blendet das SDK anstelle eines ladenden Schritts einen Bildschirm mit dem Hinweis „Keine Internetverbindung“ ein.
Es prüft die Verbindung im Hintergrund weiter und schließt den Bildschirm automatisch, sobald Didit wieder erreichbar ist, sodass der Benutzer an dem Schritt fortfahren kann, an dem er sich befand.
Der Bildschirm bietet **Erneut versuchen** und, wenn `showCloseButton` auf `true` gesetzt ist (Standardwert), **Verifizierung beenden**.
Das Beenden beendet die Verifizierung mit `.failed(error: .networkError, session:)`, sodass Ihre App erkennt, dass der Benutzer den Vorgang aufgrund des Verbindungsabbruchs verlassen hat.### Vollständiges Beispiel für die Ergebnisverarbeitung```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
    }
}
```***## Schließen der Verifizierung per Programmcode> [!NOTE]
>
> Verfügbar in DiditSDK **3.6.0+**.Die Host-App kann eine aktive Verifizierung programmgesteuert mit `DiditSdk.shared.dismiss()` beenden. Dies ist die empfohlene Methode, um die Verifizierung zu beenden, wenn die Host-App den Bildschirm übernehmen muss – beispielsweise, wenn die App in den Hintergrund wechselt.```swift theme={null}
DiditSdk.shared.dismiss()
````dismiss()` durchläuft die reguläre Abschluss-Pipeline des SDK: Es schließt die angezeigte Benutzeroberfläche, setzt den internen Status zurück und ruft den `.diditVerification`-Handler mit `.cancelled(session:)` auf, der die aktuelle `sessionId` enthält, sofern eine Sitzung erstellt wurde. Es ist ein No-Op, wenn keine Verifizierung aktiv ist.### Beispiel: Schließen, wenn die App in den Hintergrund wechselt```swift theme={null}
NotificationCenter.default.addObserver(
    forName: UIApplication.didEnterBackgroundNotification,
    object: nil,
    queue: .main
) { _ in
    DiditSdk.shared.dismiss()
}
```> [!WARNING]
>
> Setzen Sie `DiditSdk.shared.isPresented = false` **nicht**, um die Ansicht zu schließen – das Flag löst die Anzeige nur bei einer steigenden Flanke aus, und das Setzen auf `false` ist ein No-Op. Ebenso wird das Aufrufen von UIKit-`dismiss(animated:)` auf dem obersten View Controller nicht unterstützt: Es umgeht die Abschluss-Pipeline des SDK, sodass Ihr `.diditVerification`-Handler niemals ausgelöst wird.***## Beobachten des SDK-StatusSie können den SDK-Status beobachten, um eine benutzerdefinierte Ladeoberfläche anzuzeigen:```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)")
            }
        }
    }
}
```***## End-to-End-Beispiel (Backend-Sitzung → iOS-SDK → Ergebnis)Dieses Muster ist die produktionsreife Integration. Ihr Backend erstellt die Sitzung, Ihre iOS-App empfängt das `session_token` und das SDK führt den Workflow aus.### 1. Backend – Sitzung erstellen```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 – Austausch und SDK starten```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 – Endgültige Entscheidung per Webhook empfangenDas SDK-Ergebnis eignet sich für Feedback in der Benutzeroberfläche, das verbindliche Ergebnis trifft jedoch per Webhook ein. Informationen zur HMAC-Prüfung finden Sie im [Webhook-Leitfaden](https://docs.didit.me/de/integration/webhooks.md).```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);
});
```***## Vollständiges SwiftUI-Beispiel```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.