# 1️⃣ Getting started

In this short guide, you will learn how to integrate the Keyless Document SDK in your Android or iOS mobile application. You will learn how to read the document machine readable zone - MRZ - and how to scan the NFC tag of the document.

### Prerequisites

Make sure you have both required API keys, and the list of productions hosts from your Keyless contact:

* `YOUR_CLOUDSMITH_TOKEN` to download the SDK from cloudsmith repository
* `KEYLESS_API_KEY` to configure the mobile SDK
* `KEYLESS_HOSTS` a list of node URLs. Urls in `KEYLESS_HOSTS` must NOT contain any trailing slashes `/`.

Review the Keyless SDK requirements:

{% tabs %}
{% tab title="Android" %}
The Keyless SDK uses

* [Android 6.0](https://developer.android.com/about/versions/marshmallow) (API level 23) and above
* [Kotlin 1.9.25](https://github.com/JetBrains/kotlin/releases/tag/v1.9.25)
* [Gradle 8.7](https://docs.gradle.org/8.7/release-notes.html)
* [Android Gradle Plugin 8.3.0](https://developer.android.com/build/releases/past-releases/agp-8-3-0-release-notes)
* [AndroidX](https://developer.android.com/jetpack/androidx/)
  {% endtab %}

{% tab title="iOS" %}
The Keyless SDK uses

* [iOS 13](https://developer.apple.com/documentation/ios-ipados-release-notes/ios-13-release-notes)
* [Swift 5.1](https://www.swift.org/swift-evolution/#?version=5.1)
* [Cocoapods 1.15.2](https://github.com/CocoaPods/CocoaPods/releases/tag/1.15.2)

Set up a physical iOS device for running your app and enable the following permissions:

* Enable Camera permissions: add the `Privacy - Camera Usage Description` key in your project’s `Info.plist` by adding the following (in XCode under Project > Info):

  ```swift
  <key>NSCameraUsageDescription</key>
  <string>Keyless needs access to your camera to enroll and authenticate you. Keyless cannot be used without your camera. Please allow camera permissions.</string>
  ```
* Enable background processing: necessary to synchronize Keyless data. You can find a comprehensive guide in the [apple documentation](https://developer.apple.com/documentation/UIKit/using-background-tasks-to-update-your-app). In a nutshell here is what you need to do: enable the `Background processing` mode under `Signing & Capabilities/Background Modes`. Then, add the following in your project’s `Info.plit` (in XCode, under the key `Permitted background task scheduler identifiers`):

  ```xml
  <key>NSCameraUsageDescription</key>
  <key>BGTaskSchedulerPermittedIdentifiers</key>
  <array>
      <string>YOUR APP IDENTIFIER</string>
  </array>
  ```

{% endtab %}

{% tab title="Flutter" %}
The Keyless SDK uses

* [Flutter 3.0](https://docs.flutter.dev/release/release-notes/release-notes-3.0.0) or higher
* [Dart 3.0](https://dart.dev/guides/whats-new#dart-3) or higher
* All requirements from both Android and iOS platforms

Set up the required permissions as described in the Android and iOS tabs.
{% endtab %}
{% endtabs %}

### Installation

{% tabs %}
{% tab title="Android - Gradle" %}

1. To allow Keyless to handle the result of [registerForActivityResult](https://developer.android.com/training/basics/intents/result#register), you must call Keyless from an Activity implementing [ActivityResultCaller](https://developer.android.com/reference/androidx/activity/result/ActivityResultCaller).

   Extend any androidX activity that implements the interface for you, for example let your Activity extend the generic [ComponentActivity](https://developer.android.com/reference/androidx/activity/ComponentActivity) or the more widespread [AppCompatActivity](https://developer.android.com/reference/androidx/appcompat/app/AppCompatActivity).
2. If you use Proguard, add the following rules to your Proguard configuration file:

   ```
   # Keyless Proguard
   -keep class io.keyless.documentsdk.** {*;}
   -keepclassmembers class io.keyless.documentsdk.** {*;}
   ```
3. In the the `repositories` section of the `settings.gradle` file of your Android application, add the following snippet, replacing `YOUR_CLOUDSMITH_TOKEN` with the CloudSmith token provided to you by Keyless.

   ```kotlin
   dependencyResolutionManagement {
       repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
       repositories {
           google()
           mavenCentral()
           maven {
               url "https://dl.cloudsmith.io/YOUR_CLOUDSMITH_TOKEN/keyless/partners/maven/"
           }
       }
   }
   ```
4. In the `dependencies` block of your project `build.gradle` file, typically `app/build.gradle`, add:

   ```kotlin
   dependencies {
   // ...

   implementation 'io.keyless:keyless-document-sdk:+'
   }
   ```
5. In the `android` block of your project `build.gradle` file, typically `app/build.gradle`, make sure you have the following options:

   ```kotlin
   android {
       // ...

       compileOptions {
           sourceCompatibility JavaVersion.VERSION_1_8
           targetCompatibility JavaVersion.VERSION_1_8
       }

       // add the following only if you're using Kotlin
       kotlinOptions {
           jvmTarget = "1.8"
       }
   }
   ```

{% endtab %}

{% tab title="iOS - Cocoapods" %}

1. Create a Podfile if you don’t already have one

   ```bash
   $ cd your-project-directory
   $ pod init
   ```
2. Set up Cocoapods to use your Cloudsmith credentials, by running the following commands, replacing `YOUR_CLOUDSMITH_TOKEN` with the Cloudsmith token provided you by Keyless.

   ```bash
   git config --global credential.helper store
   echo "https://token:YOUR_CLOUDSMITH_TOKEN@dl.cloudsmith.io" >> ~/.git-credentials
   ```
3. Add the KeylessSDK pod to your `Podfile`

   ```ruby
   # This is the Keyless repository for partners
   source 'https://dl.cloudsmith.io/basic/keyless/partners/cocoapods/index.git'

   target 'MyApp' do
       use_frameworks!

       # Add the Keyless pod
       pod 'KeylessDocumentSDK'
   end
   ```
4. Add the following at the bottom of you `Podfile`

   ```ruby
   post_install do |installer|
   installer.pods_project.targets.each do |target|
       target.build_configurations.each do |config|
       config.build_settings['ENABLE_BITCODE'] = 'NO'
       end
   end
   end
   ```
5. Install the pods. If `pod` prompts you for authentication insert the string `token` as your username and then fill in `YOUR_CLOUDSMITH_TOKEN` as the password.

   ```bash
   $ pod install

   Analyzing dependencies
   Cloning spec repo `cloudsmith-basic-keyless-partners-cocoapods-index` from `https://dl.cloudsmith.io/basic/keyless/partners/cocoapods/index.git`
   Username for 'https://dl.cloudsmith.io': token
   Password for 'https://dl.cloudsmith.io': YOUR_CLOUDSMITH_TOKEN
   ```

{% endtab %}

{% tab title="Flutter" %}

1. Add the Keyless SDK repository

   ```bash
   echo '${CLOUDSMITH_TOKEN}' | dart pub token add https://dart.cloudsmith.io/keyless/flutter/
   ```
2. Add the Keyless SDK dependency to your `pubspec.yaml`:

   ```bash
   dart pub add keyless_flutter_document_sdk:PACKAGE_VERSION --hosted-url https://dart.cloudsmith.io/keyless/flutter/
   ```
3. Follow the installation steps in both the Android and iOS tabs to set up the native SDKs in their respective platforms.
4. Run flutter pub get to download the dependencies:

   ```bash
   flutter pub get
   ```

You also need to bridge the native SDKs that are used by the flutter SDK. You can do that in the `android` and `ios` sections of your flutter project.

#### Android

Add the following line in the root `build.gradle`:

```groovy
allprojects {
    repositories {
        google()
        mavenCentral()
        maven {
            setUrl("https://dl.cloudsmith.io/YOUR_CLOUDSMITH_TOKEN/keyless/partners/maven/")
        }
    }
}  
```

Where `YOUR_CLOUDSMITH_TOKEN` should be replaced with the cloudsmith token provided by the Keyless integration support team.

Then, open your `Android.manifest` file and add the following lines inside the `<application>` tag.

{% hint style="info" %}
If you also use the [Keyless Mobile SDK](https://docs.keyless.io/consumer/mobile-sdk-guide/getting-started), you need to add the `documentsdk.KeylessDocumentInitializer` in the same provider tag .
{% endhint %}

```
        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false"
            tools:node="merge">
 
            <meta-data
                android:name="io.keyless.documentsdk.KeylessDocumentInitializer"
                android:value="androidx.startup" />

             <!-- ONLY if you also use the Keyless Mobile SDK -->
             <meta-data
                android:name="io.keyless.fluttersdk.KeylessInitializer"
                android:value="androidx.startup" />

        </provider>
```

Make sure your `settings.gradle` (or `settings.gradle.kts`) includes **Kotlin Android plugin version 1.9.0**. This version is mandatory for compatibility across all modules.

Your plugin block should look like this:

```groovy
pluginManagement {
    plugins {
        id "dev.flutter.flutter-plugin-loader" version "1.0.0"
        id "com.android.application" version "8.7.0" apply false
        id "org.jetbrains.kotlin.android" version "1.9.0" apply false // ✅ Required version
    }
}
```

In your `app/build.gradle`, make sure to exclude the following resource to prevent build conflicts caused by Java 9+ multi-release JARs:

```groovy
android {
    packaging {
        resources {
            excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
        }
    }
}
```

You **must use** NDK version `27.0.12077973`:

```groovy
android {
    ndkVersion = "27.0.12077973"
}
```

The minimum supported SDK version is **23**:

```groovy
defaultConfig {
    minSdk = 23
}
```

***

Example of app/build.gradle

```groovy
android {
    namespace = "namespace_id"
    compileSdk = flutter.compileSdkVersion
    ndkVersion = "27.0.12077973" // ✅ Required NDK version

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_11.toString()
    }

    defaultConfig {
        applicationId = "application.id"
        minSdk = 23 // ✅ Minimum supported SDK version
        targetSdk = flutter.targetSdkVersion
        versionCode = flutter.versionCode
        versionName = flutter.versionName
    }

    packaging {
        resources {
            excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF" // ✅ Prevents Java 
        }
    }
}
```

#### iOS

Make sure to target at least iOS 15 in your project.

Open your `PodFile` and add the following line:

```bash
source 'https://dl.cloudsmith.io/YOUR_CLOUDSMITH_TOKEN/keyless/partners/cocoapods/index.git'
```

Where `YOUR_CLOUDSMITH_TOKEN` should be replaced with the cloudsmith token provided by the Keyless integration support team.

**To enable NFC-based document scanning functionality in an iOS app, the following is required:**

Enable the NFC Tag Reading Capability in Xcode:

Go to your target → Signing & Capabilities → click "+" → select Near Field Communication Tag Reading

Then, navigate to your `Info.plist` file, typically located in a folder called with your project name (e.g. `Runner`).

Add the following permissions declaration to this file (if not present already):

```xml
<key>NFCReaderUsageDescription</key>
<string>We need NFC access to read your document.</string>
<!-- Note: You can change the string value for NFCReaderUsageDescription according to your application -->
<key>NSCameraUsageDescription</key>
<string>This app uses the camera to scan the data</string>
<!-- Note: You can change the  string value for NSCameraUsageDescription according to your application -->
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>A0000002471001</string>
    <string>A0000002472001</string>
    <string>00000000000000</string>
</array>
```

{% endtab %}
{% endtabs %}

## Initialization

There is some initialization to do before you can use the Keyless Document SDK.

{% tabs %}
{% tab title="Android" %}

1. Initialize the Keyless Document SDK in your `Application` class:

   ```kotlin
   // MainApplication
   override fun onCreate() {
       super.onCreate()
       // Initialize Keyless
       KeylessDocument.initialize(application = this) 
   }
   ```
2. Add your application to the Manifest

   ```xml
   <application
       ...
       android:name=".MainApplication"
       ...
   </application>
   ```
3. Configure the Keyless Document SDK:

   ```kotlin
   // MainActivity
   override fun onCreate() {
       super.onCreate()
       KeylessDocument.configure(
           KeylessDocument.Config(
               apiKey = KEYLESS_API_KEY,
               hostURl = KEYLESS_HOST,
           ),
       )
   }
   ```

{% endtab %}

{% tab title="iOS" %}

1. Create an instance object of `KeylessDocument` initializing it with the api key and host you received from your Keyless contact.

   ```swift
   KeylessDocument.configure(
           configuration: .init(
               host: KEYLESS_HOST,
               apiKey: KEYLESS_API_KEY
           )
       )
   ```

{% endtab %}

{% tab title="Flutter" %}

1. Import the required packages:

   ```dart
   import 'package:keyless_flutter_document_sdk/keyless_document.dart';
   ```
2. Configure the Keyless SDK in your app's initialization code:

   ```dart
   final keylessDocumentConfig = KeylessDocumentConfig(
       apiKey: KEYLESS_API_KEY,
       host: KEYLESS_HOST,
   );

   try {
       await KeylessDocument.instance.configure(keylessDocumentConfig);
       print("Keyless Document SDK configured successfully");
   } catch (error) {
       print("Failed to configure Keyless Document SDK: $error");
   }
   ```

   **🎨 Optional: UI Customization**

   The SDK allows customization of the UI to better match your app’s branding or UX requirements.\
   You can define colors and override default texts for various UI components.

   Example:

   ```dart
   final keylessDocumentConfig = KeylessDocumentConfig(
       apiKey: KEYLESS_API_KEY,
       host: KEYLESS_HOST,
       logsConfiguration: LogsConfiguration(
           enabled: true,
           logLevel: document_sdk.LogLevel.debug,
       ),
       uiCustomization: UICustomization(
           primaryColor: 0xFF0B3EE3,
           rangeFinderOverlayColor: 0xFFFFD966,
           documentDetailsTitle: "Enter Document Details",
           documentNumberFieldHint: "e.g., 123456789",
           confirmButtonText: "Continue",
           nfcInfoText: "Hold your phone near the document"
       ),
   );
   ```

   UICustomization supports the following fields:

   | Category     | Parameter                         | Description                                                   |
   | ------------ | --------------------------------- | ------------------------------------------------------------- |
   | Colors       | `primaryColor`                    | A primary shown most frequently across screens and components |
   |              | `onPrimaryColor`                  | Color shown on top of the primary color                       |
   |              | `accentColor`                     | Accent color                                                  |
   |              | `rangeFinderOverlayColor`         | MRZ Rectangle color during document scanning                  |
   | MRZ / Manual | `mrzGoToManualInputButton`        | Text for switching to manual input                            |
   | Input        | `documentDetailsTitle`            | Title on manual input screen                                  |
   |              | `documentNumberFieldTitle`        | Label for document number field                               |
   |              | `documentNumberFieldHint`         | Placeholder/hint for document number                          |
   |              | `birthDayFieldTitle`              | Label for date of birth field                                 |
   |              | `expiryDateFieldTitle`            | Label for expiry date field                                   |
   |              | `cancelButtonText`                | Text for cancel button                                        |
   |              | `confirmButtonText`               | Text for confirm/continue button                              |
   | Android only | `documentNumberFieldErrorMessage` | Error message if document number is invalid (Android)         |
   |              | `birthDayFieldErrorMessage`       | Error message for birthday field (Android)                    |
   |              | `expiryDateFieldErrorMessage`     | Error message for expiry date (Android)                       |
   | NFC          | `nfcInfoText`                     | Instruction text shown before starting NFC scan               |
   | iOS only     | `nfcConnectionLost`               | Text shown when NFC connection is lost (iOS only)             |
   | Theme        | `sdkTheme`                        | Theme to use (`light`, `dark`, or system default)             |

   > 💡 All fields are optional. If not set, the SDK will fall back to default values.
3. Make sure to set up the required permissions in both Android and iOS platforms as described in their respective tabs.
   {% endtab %}
   {% endtabs %}
