> For the complete documentation index, see [llms.txt](https://docs.vida.id/identity-stack/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.vida.id/identity-stack/verify/kyc-mobile-sdk/integration-overview/ios-sdk/integration.md).

# Integration

This section explains the core integration flow of the VIDA KYC SDK within an iOS application. Each step ensures the correct initialization, execution, and cleanup of the SDK lifecycle.

{% stepper %}
{% step %}

### Import VIDA KYC

Import the VIDAKYC framework in your view controller or wherever you need to use it and acts as the entry point for all operations.

```kotlin
import vidaKYC
```

{% endstep %}

{% step %}

### Create VIDA KYC Instance

The VIDAKYC instance serves as the entry point for all KYC operations — initialization, starting and stopping the verification process, and releasing resources.

```kotlin
let vidaKYC = VIDAKYC()
```

{% endstep %}

{% step %}

### Initialize VIDA KYC

```kotlin
vidaKYC.initialize(
    kycConfig: kycConfig,
    presentNavigationController: navigationController,
    languageCode: "en" // Optional: ISO 639-1 language code
)
```

This method prepares the SDK for the KYC flow by:

* Verifying SDK configuration and network readiness
* Establishing internal resources such as camera and backend connections
* Triggering the onInitialized() callback once the setup is complete

Important: You must call this method before any other KYC operation. If initialization fails, the SDK notifies the host application through the onError() callback.
{% endstep %}

{% step %}

### Start KYC Detection

```kotlin
vidaKYC.startFlow()
```

The startFlow() method begins the KYC capture and verification flow, launching the SDK camera interface and guiding users through:

* Document scanning (e.g., KTP, MyKAD, Passport, or other ID types)
* Face capture and matching (if required by the selected flow)

It handles frame processing, OCR extraction, liveness checks, and backend verification automatically. When the flow completes successfully, the SDK invokes onSuccess(response:) on the delegate.
{% endstep %}

{% step %}

### Stop KYC Detection

```kotlin
vidaKYC.stopFlow()
```

This method allows the host app to manually stop the KYC process before it finishes, typically in cases where:

* The user cancels the process
* An external condition (like network loss) requires halting detection

The SDK gracefully stops all camera operations and releases partial resources.
{% endstep %}

{% step %}

### Release Resources

```kotlin
vidaKYC.releaseSDK()
```

Releasing resources is essential after completing or canceling the flow. It ensures all camera sessions, background threads, and temporary memory allocations used by the SDK are properly disposed of.

Best Practice: Always invoke releaseSDK() in your view controller's cleanup methods or after a completed session to prevent memory leaks or background processing issues.
{% endstep %}

{% step %}

### VIDAKYCDelegate Implementation

```kotlin
public protocol VIDAKYCDelegate: AnyObject 
    /// Called on successful completion of kyc flow.
    func onSuccess(response: VIDAKYCResponse)
    
    /// Called when an error occurs during the kyc flow.
    func onError(errorCode: Int, errorMessage: String, response: VIDAKYCResponse)
    
    /// Called when VIDAKYC is initialized successfully.
    func onInitialized()
}
```

The VIDAKYCDelegate protocol enables the host application to respond to SDK lifecycle events:

* **onInitialized()**

Called when the SDK is successfully initialized and ready to start KYC operations. You should only call startFlow() after this callback.

* **onSuccess(response: VIDAKYCResponse)**

Triggered upon successful completion of the KYC flow. The VIDAKYCResponse contains results of all backend and OCR verifications, including scores and metadata.

* **onError(errorCode: Int, errorMessage: String, response: VIDAKYCResponse)**

Called when an error occurs during initialization or the KYC process. The response object may include diagnostic data if available.
{% endstep %}

{% step %}

### VIDAKYCConfig

The VIDAKYCConfig class defines the configuration and authentication parameters for the KYC process.

```kotlin
let config = VIDAKYCConfig(
    token: "YOUR_ACCESS_TOKEN",
    keys: keys, //VIDAKYCKeys for configuring liveness and fraud
    livenessConfig: livenessConfig, // Optional: VIDALivenessConfig instance
    flow: .idVerification,
    delegate: self,
    errorConfiguration: errorConfig,
    uiConfiguration: uiConfig,
    viewFactory: viewFactory, // Optional: VIDAKYCViewFactory instance for custom tutorial page injections
    defaultDocumentType: .KTP,
    sdkRegion: .indonesia,
    passportCountryCode: "IDN", // Optional, for passport scanning
    enableDocAutoCapture: true,
    captureAdditionalImageWithFlash: true,     
    docAutoCaptureMinimumStableFrames: 5,
    docCaptureTimeout: 60.0,
    autoCapturePauseTimeout: 20,
    luminanceThreshold: 0.23
)
```

**Parameters**

<table><thead><tr><th>Parameter</th><th width="211.275390625">Type</th><th>Description</th></tr></thead><tbody><tr><td>token</td><td>String</td><td>Token to be used for authentication</td></tr><tr><td>keys</td><td>VIDAKYCKeys</td><td>Contains required keys for configuring liveness AND/OR fraudshield within sdk</td></tr><tr><td>livenessConfig</td><td>VIDALivenessConfig?</td><td>Configuration for liveness SDK (optional, required for liveness flows)</td></tr><tr><td>flow</td><td>VIDAKYCFlow</td><td>Flow type: .kyc, or .idVerification</td></tr><tr><td>delegate</td><td>VIDAKYCDelegate</td><td>Delegate for callbacks</td></tr><tr><td>errorConfiguration</td><td>VIDAKYCErrorConfig</td><td>Error page configuration</td></tr><tr><td>uiConfiguration</td><td>VIDAKYCUIConfig</td><td>UI customization configuration</td></tr><tr><td>viewFactory</td><td>VIDAKYCViewFactory</td><td>A factory protocol to inject custom tutorial screens in SDK</td></tr><tr><td>defaultDocumentType</td><td>VIDAKYCDocumentType</td><td>Default document type if selection is disabled</td></tr><tr><td>sdkRegion</td><td>VIDAKYCSDKRegion</td><td>Region: .indonesia or .malaysia</td></tr><tr><td>passportCountryCode</td><td>String?</td><td>ISO 3166-1 alpha-3 code for passport scanning</td></tr><tr><td>enableDocAutoCapture</td><td>Bool</td><td>Enables/Disables autocapture throughout doc capture flows. Default is true</td></tr><tr><td>captureAdditionalImageWithFlash</td><td>Bool</td><td>If enabled captures 2 images, normal and with flash for material check</td></tr><tr><td>docAutoCaptureMinimumStableFrames</td><td>Int</td><td>Minimum valid frames for auto capture</td></tr><tr><td>docCaptureTimeout</td><td>TimeInterval</td><td>Max time for each capture</td></tr><tr><td>autoCapturePauseTimeout</td><td>TimeInterval</td><td>Max time at which if autocapture enabled, switching to manual pop up is shown</td></tr><tr><td>luminanceThreshold</td><td>Float</td><td>Threshold value to identify whether the image is dark or not. Range (0-1). default value is 0.23</td></tr></tbody></table>

#### VIDAKYCKeys

```kotlin
///   - apiKey: API key provided by VIDA
    ///   - licenseKey: License key provided by VIDA
    ///   - clientId: Client ID provided by VIDA for ID Shield, If passed fraudshield will be used in the flows
    ///   - userId: user Id from the clients application. User ID from the client's application. Optional — if not provided, a default value is used.
@objc public class VIDAKYCKeys: NSObject {
    let apiKey: String
    let licenseKey: String
    let fraudShieldClientId: String?
    let userId: String?
}
```

#### VIDAKYCFlow

```kotlin
public enum VIDAKYCFlow: Int {
    case idVerification
    case kyc
}
```

#### Detailed Configuration Guide:

For comprehensive documentation on configuring the VIDA Liveness SDK, including all available parameters, UI customization options, and best practices, please refer to:

#### VIDA iOS SDK FraudShield/Liveness Configuration:

1. Add shared activation key in the application’s Info.plist under vida\_activation\_key

```kotlin
<key>vida_activation_key</key>
<string>__activation_key_provided_by_vida__</string>
```

2. Configure the sdk with parameters within the `VIDALivenessConfig`

```kotlin
<key>vida_activation_key</key>
<string>__activation_key_provided_by_vida__</string>
```

{% hint style="info" %}
**Note**: For additional configuration details, checkout the liveness sdk integration guide <https://docs.vida.id/vida-identity-platform/integration-methods/sdk/ios-sdk>
{% endhint %}

#### VIDAKYCDocumentType

SDK currently supports the following documents:

<table><thead><tr><th width="289.6953125">ID Card Type</th><th>Description</th></tr></thead><tbody><tr><td>KTP</td><td>Indonesian National ID</td></tr><tr><td>DL</td><td>Driving License</td></tr><tr><td>myKAD</td><td>Malaysian ID Card</td></tr><tr><td>myKAS</td><td>Malaysian temporary resident identification card</td></tr><tr><td>myPR</td><td>Malaysian Permanent Resident ID Card</td></tr><tr><td>myTentera</td><td>Malaysian Military ID Card</td></tr><tr><td>Passport</td><td></td></tr></tbody></table>

#### VIDAKYCSDKRegion

```kotlin
public enum VIDAKYCSDKRegion: Int {
    case indonesia
    case malaysia
}
```

{% endstep %}

{% step %}

### VIDAKYCResponse

The `VIDAKYCResponse` class encapsulates the results of the entire KYC verification process.

```kotlin
public class VIDAKYCResponse {
    public let livenessResponse: VIDALivenessResponse?
    public let ocrIdVerificationResponse: OCRIdVerificationResponse?
    public let faceVerificationResponse: FaceVerificationResponse?
    public let failedOperation: String?
}
```

The response serves as the final structured output from the VIDA SDK, passed via the `onSuccess()` or `onError()` callbacks in `VIDAKYCDelegate`. `failedOperation` will have ocrFront/ocrBack/liveness/faceMatch as the options.

#### 9.1 Liveness

{% code expandable="true" %}

```kotlin
class VidaLivenessDetails {
    var imageData: Data?
    var livenessScore: Double
    var manipulationScore: Double
    var errorDetails: String?
    var sessionId: String?
    var transactionId: String?
    var additionalImages: [Data]?
    let attemptedTransactionIds: VidaVerificationTransactionIds?
}
```

{% endcode %}

<table><thead><tr><th width="259.1796875">Parameter</th><th>Description</th></tr></thead><tbody><tr><td>imageData</td><td>Final liveness frame. nil on some errors.</td></tr><tr><td>livenessScore</td><td>0…1. -1 when unavailable.</td></tr><tr><td>manipulationScore</td><td>0…1. -1 when unavailable.</td></tr><tr><td>errorDetails</td><td>Additional error context when available.</td></tr><tr><td>sessionId</td><td>Session ID for the whole liveness transaction.</td></tr><tr><td>transactionId</td><td>Backend transaction ID for the final liveness attempt.</td></tr><tr><td>additionalImages</td><td>Final frames from active liveness flow.</td></tr><tr><td>attemptedTransactionIds</td><td>All attempted transaction IDs, separated by success/failure.</td></tr></tbody></table>

#### 9.2 ID Card Verification & Face Match Branch

{% code expandable="true" %}

```kotlin
class VidaIdCardVerificationDetails {
    let frontCardVerificationDetails: VidaVerifyResponseDTO?
    let backCardVerificationDetails: VidaVerifyResponseDTO?
}

class VidaVerifyResponseDTO {
    let transactionId: String?
    let partnerTrxId: String?
    let groupId: String?
    let errors: [VIDAFailureDetails]?
    let warnings: [VIDAFailureDetails]?
    let attemptedTransactionIds: VidaVerificationTransactionIds?
    let imageFaceMatchVerificationResult: VIDAVerificationResult?
    let imageLivenessVerificationResult: VIDAVerificationResult?
    let imageQualityResult: VIDAImageQualityResultContainer?
    let card: VIDACard?
    let idVerificationResult: VIDAIDVerificationResultContainer?
    let ocrResult: VIDAOcrResultContainer?
    let duplicateCheckResult: VIDADuplicateCheckResult?
}
```

{% endcode %}

#### 9.3 Image Quality

{% code expandable="true" %}

```kotlin
class VIDAImageQualityResultContainer {
    let front: VIDAImageQualityResult?
    let back: VIDAImageQualityResult?
}

class VIDAImageQualityResult {
    let blurriness: VIDAScoreThreshold?
    let lowLight: VIDAScoreThreshold?
    let overExposure: VIDAScoreThreshold?
    let cardDimension: VIDACardDimension?
}

class VIDACardDimension {
    let cardCoordinates: VIDACardCoordinates
    let cardWidth: Int
    let cardHeight: Int
}

class VIDACardCoordinates {
    let x1: Int
    let x2: Int
    let y1: Int
    let y2: Int
}



```

{% endcode %}

#### 9.4 Card Metadata

{% code expandable="true" %}

```kotlin
class VIDACard {
    let country: String
    let type: String
    let isoAlpha3CountryCode: String
    let isoAlpha2CountryCode: String
}
```

{% endcode %}

#### 9.5 ID Verification (Spoof / Landmark / Forgery / Material)

{% code expandable="true" %}

```kotlin
class VIDAIDVerificationResultContainer {
    let front: VIDAIDVerificationResult?
    let back: VIDAIDVerificationResult?
}
class VIDAIDVerificationResult {
    let spoofingResult: VIDASpoofingResult?
    var landmarkResult: VIDALandmarkResult?
    let forgeryResult: VIDAForgeryResult?
    let materialCheckResult: VIDAMaterialCheckResult?
}
class VIDASpoofingResult {
    let message: String
    let code: Int
    let recapScore: VIDAScoreThreshold?
    let blackWhite: VIDAScoreThreshold?
    let colorPrint: VIDAScoreThreshold?
    let screenshot: VIDAScoreThreshold?
}
class VIDALandmarkResult {
    let code: Int
    let message: String
    let threshold: NSNumber?
    let containerResult: [VIDAContainerResult]?
    let landmarkTags: [VIDALandmarkTag]?
    let landmarkVerification: [VIDALandmarkVerification]?
}
class VIDAContainerResult {
    let position: VIDAPosition?
    let name: String
    let score: Double
}
class VIDALandmarkTag {
    let name: String
    let value: String
}
class VIDALandmarkVerification {
    let name: String
    let status: String
}
class VIDAForgeryResult {
    let code: Int
    let message: String
    let summary: VIDAScoreThreshold?
}
class VIDAMaterialCheckResult {
    let code: Int
    let message: String
    let summary: VIDAScoreThreshold?
}

```

{% endcode %}

#### 9.6 OCR

```kotlin
class VIDAOcrResultContainer {
    let front: VIDAOcrResult?
    let back: VIDAOcrResult?
}
class VIDAOcrResult {
    let data: VIDAOcrData
}
class VIDAOcrData {
    let idNumber: VIDADataValue?
    let extendedIdNumber: VIDADataValue?
    let personalIdNumber: VIDADataValue?
    let countryOfOrigin: VIDADataValue?
    let militaryId: VIDADataValue?
    let militaryRank: VIDADataValue?
    let militaryDivision: VIDADataValue?
    let name: VIDADataValue?
    let address: VIDADataValue?
    let dob: VIDADataValue?
    let gender: VIDADataValue?
    let religion: VIDADataValue?
    let province: VIDADataValue?
    let city: VIDADataValue?
    let placeOfBirth: VIDADataValue?
    let bloodType: VIDADataValue?
    let neighborhoodAssociationGroup: VIDADataValue?
    let village: VIDADataValue?
    let subDistrict: VIDADataValue?
    let maritalStatus: VIDADataValue?
    let occupation: VIDADataValue?
    let nationality: VIDADataValue?
    let dateOfExpiry: VIDADataValue?
    let dateOfIssue: VIDADataValue?
    let citizenship: VIDADataValue?
    let issuerName: VIDADataValue?
    let issuerCountry: VIDADataValue?
    let issuingAuthority: VIDADataValue?
    let validUntil: VIDADataValue?
    let portraitImage: String?           // base64
}
```

#### 9.7 Duplicate Check

```kotlin
class VIDADuplicateCheckResult {
    let docReferences: [VIDADocReference]
    let idNumberReferences: [VIDADocReference]
}
class VIDADocReference {
    let documentId: String
    let matchScore: Double
}
```

#### 9.8 Shared Primitives

```kotlin
class VIDAScoreThreshold {
    let score: Double
    let threshold: Double
}
class VIDADataValue {
    let value: String
    let score: NSNumber?      // OCR confidence
    let threshold: NSNumber?
}
class VIDAVerificationResult {
    let data: VIDAVerificationData
}
class VIDAVerificationData {
    let code: Int
    let message: String
    let score: Double
}
class VIDAFailureDetails {
    let code: Int
    let message: String
    let operations: [String]
}
class VIDAPosition {
    let x: Int
    let y: Int
    let width: Int
    let height: Int
}
class VidaVerificationTransactionIds {
    let failedTransactionIds: [String]
    let successTransactionIds: [String]
}
```

{% endstep %}
{% endstepper %}

***

## Framework Version

To get the current framework version:

```kotlin
let version = vidaKYC.getFrameworkVersion()
print("VIDA KYC SDK Version: \(version)")
```
