> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-sdk/android/getting-started-with-the-sdk-1.md).

# Legacy Getting Started with the SDK

{% hint style="warning" %}
Version 7.14.0 brings an optional, faster way to initialize the SDK with fewer lines of code. Along with this code update, we launched a brand-new, easier-to-read documentation page. To adopt this new setup, [check out the updated guide](/caf-sdk/android/installation-guide.md).
{% endhint %}

## About CafSDK

This technical documentation covers the **implementation of CafSDK for Android**, detailing the configuration, initialization, execution of capture flows, and advanced customizations.

Currently, CafSDK integrates multiple modules: **Face Liveness (FL)**, **Document Detector (DD)** executed sequentially with a unified configuration interface. Recent releases include enhanced security features, improved performance, better error handling, enhanced upload customization.

### What is Face Liveness

It is the module that validates the authenticity of a face captured by a camera, ensuring that the image corresponds to a real person.

**Technical characteristics:**

* `caffaceliveness` is the shared base. You must declare **at least one** **`caffaceliveness-providers-*`** artifact for the liveness providers your product uses (**iProov**, **PayFace**, **FaceTec**, …). **`caffaceliveness-ui`** is **optional** and adds **Caf’s Face Liveness UI** plus **customization** hooks; omit it if your app owns the whole interface.
* URL configuration for authentication (`authBaseUrl`) and liveness verification (`livenessBaseUrl`).
* Reverse proxy endpoints and security certificates (optional).
* Flags to enable screen capture and debug mode.
* Support for multiple liveness providers when you declare the corresponding dependencies.

### What is Document Detector

It is the module that enables the capture and processing of documents (e.g., ID card, social security card, passport, etc.).

**Technical characteristics:**

* Configuration of a step-by-step flow defined by `DocumentDetectorStep` for document capture.
* Operational parameters, such as timeout, manual capture flags, and other settings.
* Possibility of using the camera for framing validations, or document file upload.

***

## Get started with the SDK

### Add the dependency

For your Android project to utilize CafSDK, it is necessary to correctly configure the Maven repositories and declare the SDK dependencies in your project. This step ensures that the artifacts (libraries) are downloaded and integrated during the build.

### Requirements for adding

The minimum requirements for all CafSDK modules include:

| Requirement                                    | Version |
| ---------------------------------------------- | ------- |
| Android SDK API - minimum version (minSdk)     | 26      |
| Android SDK API - compile version (compileSDK) | 36      |
| Kotlin                                         | 1.9.10  |
| Gradle                                         | 8.4     |
| Android Gradle Plugin (AGP)                    | 8.3.2   |

{% hint style="warning" %}
`versionName` and `versionCode` are mandatory for the correct functioning of the SDK.
{% endhint %}

**Module-Specific Requirements**

* Supports **iProov**, **PayFace**, and **FaceTec 2D** as explicit liveness provider dependencies (see [Step 2 - Include the CafSDK dependency](#step-2-include-the-cafsdk-dependency))
* Powered by TensorFlow Lite for document processing
* Supports multiple document types and capture flows
* Includes advanced quality validation algorithms
* Enhanced upload customization features
* Improved retry mechanism with better user feedback
* Enhanced security features
* Improved instance management to prevent crashes

### Step-by-step to add

### Step 1 - Add the Maven repository

In this step, you need to inform Gradle where to locate the CafSDK artifacts and additional dependencies that may be used (such as those related to Caf Face Liveness, DocumentDetector or FingerPrintJS).

To do this, configure the project's settings.gradle.kts file (usually located at the root level), including the following repositories:

* **Caf Repository:** where the CafSDK artifacts are hosted.
* **iProov Repository:** required only if you include the **iProov** liveness provider (`caffaceliveness-providers-iproov-lite` or `caffaceliveness-providers-iproov-full`).
* **FingerPrintJS Repository:** internal dependency of the modules.
* **JitPack:** for dependencies hosted via JitPack (Github).
* **Fortface Repository:** required only if you include the **PayFace** liveness provider (`caffaceliveness-providers-payface`).

**Configuration example:**

```kotlin
repositories {
    // Caf Repository
    maven { url = uri("https://repo.combateafraude.com/android/release") }
    
    // iProov Repository
    maven { url = uri("https://raw.githubusercontent.com/iProov/android/master/maven/") }
    
    // FingerPrintJS Repository
    maven { setUrl("https://maven.fpregistry.io/releases") }
    
    // JitPack
    maven { setUrl("https://jitpack.io") }

    // Fortface Repository - required to use the PayFace provider
    maven {
        url = uri("https://cdn-fortface-sdk.fortface.com.br")
        credentials(HttpHeaderCredentials::class) {
            name = "X-Sdk"
            value = "CAF"
        }
        authentication {
            create<HttpHeaderAuthentication>("header")
        }
    }
    
}
```

#### More details

* **Flexibility:** this configuration allows the project to download all necessary dependencies from different sources, ensuring compatibility and updated versions.
* **Maintenance:** if there are updates to the repositories or changes in the publication structure, simply update this section to reflect the new URLs.
* **Context:** the inclusion of repositories is done only once at the project level, ensuring that all modules can access the necessary artifacts.

### Step 2 - Include the CafSDK dependency <a href="#step-2-include-the-cafsdk-dependency" id="step-2-include-the-cafsdk-dependency"></a>

After configuring the repositories, it is necessary to declare the specific CafSDK dependencies in the build.gradle.kts file of your application module. This step declares which SDK modules will be used, allowing Gradle to manage versions and resolve dependencies correctly.

**Declaration of dependencies example:**

```kotlin
dependencies {
    implementation(platform("io.caf.sdk:caf-sdk-bom:7.19.0"))

    // Face Liveness — base module (required when using Face Liveness)
    implementation("io.caf.sdk:caffaceliveness")
    // Optional caffaceliveness-ui: Caf’s Face Liveness screens + UI customization APIs; omit for a fully custom UI
    implementation("io.caf.sdk:caffaceliveness-ui")

    // caffaceliveness-providers-* — required: at least one provider artifact for your integration
    implementation("io.caf.sdk:caffaceliveness-providers-iproov-lite")   // iProov + Protobuf JavaLite
    // implementation("io.caf.sdk:caffaceliveness-providers-iproov-full") // iProov + Protobuf Java (full)
    // implementation("io.caf.sdk:caffaceliveness-providers-payface")
    // implementation("io.caf.sdk:caffaceliveness-providers-facetec")

    // Document Detector
    implementation("io.caf.sdk:document-detector") // or "io.caf.sdk:document-detector-ui" for Caf’s UI
}
```

**iProov and Protobuf**

* Use `caffaceliveness-providers-iproov-lite` when your app standardizes on **Protobuf JavaLite** (typical default for smaller footprint).
* Use `caffaceliveness-providers-iproov-full` when you must use **Protobuf Java** (full) alongside iProov.

You can combine **multiple providers** in the same app by declaring more than one `caffaceliveness-providers-*` dependency, if your integration requires it.

{% hint style="warning" %}
If your project uses the Payface provider (caffaceliveness-providers-payface), you must use the lite version of iProov: implementation("io.caf.sdk:caffaceliveness-providers-iproov-lite") This is because Payface is built using Protobuf JavaLite. Mixing it with the "full" version of iProov will cause dependency conflicts during the build process.
{% endhint %}

**Important**

**Caf BoM (Bill of Materials)**

Using the BoM helps centralize the version management of all CafSDK modules. Thus, all SDK-related dependencies will use the same defined version, avoiding conflicts and facilitating updates.

**Capture Modules**

* **Caf Face Liveness:** always declare **`caffaceliveness`** (shared base) and **at least one** **`caffaceliveness-providers-*`** module for the providers your integration uses. **`caffaceliveness`** and a provider dependency are both **mandatory**; the base does not bundle vendor SDKs by default. **`caffaceliveness-ui`** is **optional**: it adds **Caf’s Face Liveness UI** and **customization** hooks; omit it for a fully custom or headless flow.
* **Caf Document Detector:** choose the standard module or the one with Caf’s UI (`document-detector-ui`), according to your UX needs.

### Known Issues

#### Duplicate Class Conflicts with TensorFlow Lite or LiteRT

If your application uses other SDKs that include TensorFlow Lite or LiteRT dependencies (such as ML Kit, Firebase ML, or other ML-based SDKs), you may encounter `duplicate class` errors during compilation.

**Solution:**

Exclude the conflicting dependencies from the Document Detector module by adding the following configuration to your `build.gradle.kts`:

```kotlin
dependencies {
    implementation(platform("io.caf.sdk:caf-sdk-bom:7.0.0"))
    implementation("io.caf.sdk:document-detector") {
        exclude(group = "com.google.ai.edge.litert", module = "litert-support")
        exclude(group = "com.google.ai.edge.litert", module = "litert")
    }
}
```

**Note:** This solution is recommended when you're using other SDKs that already provide these dependencies in your project.

**Version Verification**

Always check the latest version of CafSDK on the [release notes](#release-notes) to ensure you are using the most up-to-date and compatible versions.

**Current Module Versions**

The following are the current versions of the standalone modules:

| Module | Current Version | Description               |
| ------ | --------------- | ------------------------- |
| CafSDK | 7.10.0          | Unified validation module |

This configuration ensures that your project is prepared to integrate CafSDK, ensuring that all necessary artifacts are located and incorporated during the build. If there are any changes to the repositories or new dependencies are introduced, update the settings.

***

## How to initialize the SDK

### Permissions

For the modules to operate correctly, some permissions need to be declared in the **AndroidManifest.xml** file, check:

**For Face Liveness**

| Permission                    | Description                                                                             | Necessity |
| ----------------------------- | --------------------------------------------------------------------------------------- | --------- |
| `android.permission.CAMERA`   | Allows access to the camera to capture images and perform face verification (liveness). | Mandatory |
| `android.permission.INTERNET` | Allows communication with authentication and verification services (HTTPS/WSS).         | Mandatory |

**For Document Detector**

| Permission                                 | Description                                                                 | Necessity        |
| ------------------------------------------ | --------------------------------------------------------------------------- | ---------------- |
| `android.permission.CAMERA`                | Allows access to the camera to capture document images.                     | Only for capture |
| `android.permission.INTERNET`              | Allows captured images to be sent to servers for processing and validation. | Mandatory        |
| `android.permission.READ_EXTERNAL_STORAGE` | Allows access to stored files and images for processing, if necessary.      | Only for upload  |

### Configurations

It is necessary to configure the SDK so that it understands the execution flow and the specific parameters of each module. The initialization process is divided into two parts: global configuration and module-specific configuration.

**Global configuration**

In this step, you create an object of type `CafSdkConfiguration`, which serves as a central container for all capture flow configurations.

1. **Module presentation order (presentationOrder):**

* Define the sequence in which the modules will be executed. This order is crucial to ensure that the capture flow follows the business logic defined by your project.
* For example, if the flow requires the document to be captured before liveness verification, the order should place the **Document Detector** module before **Face Liveness**.
* Important: depending on the implementation, there may be variations in names, such as `CafModuleType.FACE_LIVENESS` or `CafModuleType.FACE_LIVENESS_UI`, which indicate whether a version without an interface or a version with an interface will be used.

2. **Security module (enableSecurityModule):**

* Enables or disables the security module. Optional, default is `true`.

**Code example for creating the global configuration:**

```kotlin
val sdkConfiguration = CafSdkConfiguration(
    presentationOrder = listOf(
        CafModuleType.FACE_LIVENESS,     // or CafModuleType.FACE_LIVENESS_UI
        CafModuleType.DOCUMENT_DETECTOR, // or CafModuleType.DOCUMENT_DETECTOR
    ),
    enableSecurityModule = true,        // Optional, default is true
    waitForAllServices = true            // Optional, default is true
)
```

**Module-specific configuration**

After defining the global configurations, it is necessary to configure the modules individually. This specific configuration allows adjusting specific operational parameters, ensuring they behave according to the requirements of your capture flow.

**Document Detector configuration**

The **Document Detector module** is responsible for capturing and processing documents. Its configuration involves several parameters.

**Mandatory parameter:**

* **Capture flow (flow):**
  * Defines a list of steps ([`DocumentDetectorStep`](#documentdetectorstep)) that specifies which document will be captured.
  * This flow can be customized according to the types of documents to be validated by the application.

**Operational parameters:**

* `useAdb`, `useDebug`, and `useDeveloperMode` are flags that activate specific modes for testing and development, allowing greater flexibility during the integration phase.
* `manualCaptureEnabled` and `manualCaptureTime` control whether manual capture is allowed and, if so, define the time limit (in seconds) for the user to perform the action manually.
* `requestTimeout` defines the maximum time (in seconds) that the system will wait for a server response.
* `showPopup` determines whether a confirmation or instruction pop-up will be displayed to the user after document capture.

**Code example for Document Detector configuration:**

```kotlin
sdkConfiguration.setDocumentDetectorConfig(
    CafDocumentDetectorConfig(
        flow = listOf(DocumentDetectorStep(Document.RG_FRONT), DocumentDetectorStep(Document.RG_BACK)),
        useAdb = true,
        useDebug = true,
        useDeveloperMode = true,
        manualCaptureEnabled = true,
        manualCaptureTime = 45,
        requestTimeout = 60,
        showPopup = true
    )
)
```

**Face Liveness Configuration**

The Face Liveness module configuration is essential to ensure the security and reliability of the facial verification process, as it has the function of validating whether the captured face belongs to a real person. The main parameters are:

* **Loading (Loading Screen):**
  * The `loading` flag defines whether a loading screen should be displayed while the module performs processing. This improves the user experience by informing them that the process is in progress.
* **Reverse Proxy Config**
  * `authBaseUrl` and `livenessBaseUrl` are optional endpoints for the authentication and liveness verification services, respectively.
  * Once configured, these values must be configured with valid URLs, where `authBaseUrl` usually uses the HTTPS protocol for security, and `livenessBaseUrl` uses WSS (Secure WebSocket).
  * **Certificates:**
    * When assigning values to service URLs, it is also necessary to provide the `certificates` list and ensure secure communications with trusted servers (when using reverse proxy).
* **Additional Options:**
  * `screenCaptureEnabled` enables or disables the ability to capture the screen during the verification process.
  * `debugModeEnabled` allows logs and additional information to be available during execution, facilitating debugging.
  * `executeFaceAuth` sets whether to execute face authentication.
  * `maxRetryAttempts` sets the maximum number of retry attempts for face liveness validation. If set to -1, it allows unlimited retries.

**Code example for Face Liveness configuration:**

```kotlin
sdkConfiguration.setFaceLivenessConfig(
    CafFaceLivenessConfig(
        loading = true,                                                             // Displays loading screen during processing
        reverseProxyConfig = CafReverseProxyConfig(
            authBaseUrl = "https://my.proxy.io/v1/faces/",                          // Optional, endpoint for authentication
            livenessBaseUrl = "wss://my.proxy.io/ws/",                              // Optional, endpoint for liveness check
            certificates = listOf("4d69f16113bed7d62ca56feb68d32a0fcb7293d3960=")   // Optional, only used with reverse proxy
        )
        screenCaptureEnabled = true,                                                // Allows screen capture if necessary
        debugModeEnabled = true,                                                    // Enable debug mode for detailed logs
        executeFaceAuth = false,                                                    // Sets whether to execute face authentication.
        maxRetryAttempts = 3                                                        // Sets the number of times the retry screen will appear.
    )
)
```

These initial configurations are fundamental to ensure that the SDK operates as expected. Each parameter was designed to offer flexibility and security, allowing the capture flow to be adapted to the specific needs of your application.

Upon completing these configurations, the SDK will be ready to be initialized and executed, ensuring robust and efficient integration with the modules.

***

## Initializing the Builder

The Builder initialization is the step where the CafSDK capture flow is configured for execution. Using the CafSdkProvider.Builder class, you configure the essential parameters that define the behavior of the flow and prepare the SDK to be started.

**Essential parameters**

* **mobileToken**: token that authenticates the request and ensures that only authorized clients start the flow.
* **personId**: unique user identifier for which the flow will be executed.
* **environment**: defines the execution environment, for example, CafEnvironment.PROD for production. This enables switching between development, homologation, and production environments.
* **configuration**: the previously configured CafSdkConfiguration object, which contains both the execution order of the modules and the specific configurations.
* **callback**: a unified callback, where all events generated by the modules (such as loading, success, error, and cancellation) are handled centrally.

**Detailed code example:**

```kotlin
val sdkBuilder = CafSdkProvider.Builder(
    mobileToken = "mobile-token",        // Authentication token
    personId = "person-id",              // User identifier
    environment = CafEnvironment.PROD,   // Production environment
    configuration = sdkConfiguration,    // Global configuration with module order and parameters
    callback = ::callbackEvent           // Return of SDK events
).build()
```

### Unified Callback

The unified callback is one of the pillars of CafSDK, responsible for notifying the application about the state of each step of the capture flow. It centralizes the events triggered by the modules and allows the developer to implement response logics, log records, and error handling.

**Callback event types:**

* **Log:** captures log messages with different levels (DEBUG, USAGE, INFO). These messages help identify the internal behavior of the flow.
* **Loading:** indicates the start of module processing. Useful for displaying visual progress indicators.
* **Loaded:** confirms that a certain action has been performed. Useful for hiding visual progress indicators.
* **Success:** upon successful completion, each module triggers an event containing a [CafUnifiedResponse](#cafunifiedresponse) object.
* **Failure:** if an failure occurs during execution, this event is triggered with a descriptive message and type of the failure.
* **Error:** if a problem occurs during execution, this event is triggered with the error message, allowing the application to handle the error.
* **Cancelled:** indicates that the user or system interrupted the flow, enabling recovery actions or notifications.

**Code examples:**

```kotlin
private fun callbackEvent(event: CafUnifiedEvent): Unit = when(event) {
        is CafUnifiedEvent.Log -> {
            // Informative logs, useful for debugging and monitoring
            log("[LOG] ${event.level}: ${event.message}")
        }
        is CafUnifiedEvent.Loading -> {
            // Indicates some execution has been started internally (may display a loading screen)
            log("[LOADING]")
        }
        is CafUnifiedEvent.Loaded -> {
            // Indicates internal execution has been completed (may hide a loading screen)
            log("[LOADED]")
        }
        is CafUnifiedEvent.Success -> {
            // When the module is successfully completed, the callback receives the name of the module and the results
            event.response.forEach {
                log("[SUCCESS] moduleName: ${it.moduleName}")
                log("[SUCCESS] signedResponse: ${it.signedResponse}")
            }
        }
        is CafUnifiedEvent.Failure -> {
            // Captures failures that occur during execution and allows fault handling logic to be implemented
            log("[FAILURE] ${event.response}")
            log("[FAILURE] ${event.type}")
            log("[FAILURE] ${event.description}")
        }
        is CafUnifiedEvent.Error -> {
            // Captures errors that occur during execution and allows fault handling logic to be implemented
            log("[ERROR] ${event.response}")
            log("[ERROR] ${event.type}")
            log("[ERROR] ${event.description}")
        }
        is CafUnifiedEvent.Cancelled -> {
            // Informs that the operation was canceled by the user or due to an execution failure
            log("[CANCELLED]")
        }
    }
```

**Session event handling**

The builder's callback returns a set of events defined by the `CafUnifiedEvent` enumeration. These events include:

* `Loading`: Indicates a sdk loading request
* `Loaded`: Indicates a sdk loading finished request
* `Success(responses: List<CafUnifiedResponse>)`: Final results (when `waitForAllServices=true`)
* `Failure(response: String, type: CafFailureType, description: String)`: Module-specific failures
* `Error(response: String, type: CafErrorType, description: String)`: Critical execution errors
* `Cancelled`: User-initiated cancellation
* `Log(level: CafLogLevel, message: String)`: Debugging information

### Error Types Breakdown

### Failure Types (CafFailureType)

|      Enum Case      | Trigger Condition          | GPA |  LA |
| :-----------------: | -------------------------- | :-: | :-: |
|      `UNKNOWN`      | Generic failure            |  ✅  |  ❌  |
| `TOO_MUCH_MOVEMENT` | Excessive head motion      |  ✅  |  ❌  |
|     `TOO_BRIGHT`    | Over-illumination          |  ✅  |  ❌  |
|      `TOO_DARK`     | Low light conditions       |  ✅  |  ❌  |
|  `MISALIGNED_FACE`  | Face alignment failure     |  ✅  |  ❌  |
|    `FACE_TOO_FAR`   | Face too distant           |  ✅  |  ❌  |
|   `FACE_TOO_CLOSE`  | Face too close             |  ✅  |  ❌  |
|     `SUNGLASSES`    | Eye-obscuring eyewear      |  ✅  |  ❌  |
|   `OBSCURED_FACE`   | Partial face obstruction   |  ✅  |  ✅  |
|    `EYES_CLOSED`    | Closed eyes during capture |  ✅  |  ✅  |
|   `MULTIPLE_FACES`  | Multiple faces detected    |  ✅️ |  ✅️ |
|  `BACKGROUND_ISSUE` | Unsuitable background      |  ❌  |  ✅  |
|    `DEVICE_ISSUE`   | Incompatible device        |  ❌  |  ✅  |
|      `EYEWEAR`      | Eyewear detected           |  ❌  |  ✅  |
|   `FACE_NOT_FOUND`  | Face detection failure     |  ❌  |  ✅  |
|   `FRAMES_BLURRY`   | Blurry frames detected     |  ❌  |  ✅  |
|    `MOTION_ISSUE`   | Device motion error        |  ❌  |  ✅  |
|  `LIGHTING_ISSUES`  | Poor lighting conditions   |  ❌  |  ✅  |
|      `REJECTED`     | Transaction rejected       |  ❌  |  ✅  |
|    `SYSTEM_ERROR`   | Internal system error      |  ❌  |  ✅  |
|      `TIMEOUT`      | Session timeout            |  ❌  |  ✅  |
|   `USER_NOT_FOUND`  | User lookup failure        |  ❌  |  ✅  |
|   `DEVICE_RESTART`  | Device state error         |  ❌  |  ✅  |
|  `PROCESSING_FAULT` | Processing error           |  ❌  |  ✅  |

Key: ✅ = supported, ❌ = not supported

```kotlin
when (result) {
    is Failure -> {
        when (result.type) {
            FailureType.EYES_CLOSED -> showAlert("Keep eyes open")
            FailureType.MULTIPLE_FACES -> showAlert("Only one face allowed")
        // Handle other cases
        }
    }
}
```

***

### Error Types (CafErrorType)

| Enum Case               | Trigger Condition                                       |
| ----------------------- | ------------------------------------------------------- |
| GENERIC\_ERROR          | A generic error occurs                                  |
| UNKNOWN                 | Unclassified error                                      |
| SEQUENCE\_INVALID       | When the sequence list in the CafSDK run is empty       |
| CAMERA\_PERMISSION      | Camera access denied                                    |
| NETWORK\_EXCEPTION      | Network connectivity issues                             |
| SERVER\_EXCEPTION       | Backend processing failure                              |
| TOKEN\_EXCEPTION        | Invalid/expired token                                   |
| LIVENESS\_EXCEPTION     | When a liveness problems occurs                         |
| UNSUPPORTED\_DEVICE     | Unsupported device specs                                |
| FINGERPRINT\_EXCEPTION  | When a device's fingerprint has a problem               |
| CANCELLATION            | When user cancell the execution                         |
| LIBRARY\_EXCEPTION      | Low-level framework error                               |
| STORAGE\_EXCEPTION      | There is no space on the user device's internal storage |
| PERMISSION\_EXCEPTION   | Missing system permissions                              |
| PROXY\_EXCEPTION        | When a problem occurs while using the configured proxy  |
| SECURITY\_EXCEPTION     | When the SDK cannot be started due to a security reason |
| AVAILABILITY\_EXCEPTION | The SDK is not yet available for use.                   |
| INVALID\_EXCEPTION      | When the token is invalid                               |
| FACE\_AUTHENTICATION    | When a face authentication problem occurs               |

```kotlin
when (result) {
    is Error -> {
        when (result.type) {
            CafErrorType.CAMERA_PERMISSION -> requestCameraAccess()
            CafErrorType.NETWORK_EXCEPTION -> showRetryButton()
            CafErrorType.SERVER_EXCEPTION -> showAlert("Received invalid response from server")
        // Handle other cases
        }
    }
}
```

### Security Returns <a href="#security-returns" id="security-returns"></a>

We are constantly taking actions to make the product more secure, mitigating many attacks observed in the capture processes and reducing as many identity fraud attempts as possible. The errors described here are returned in the `message` field of the `SecurityReason` class.

**Disabling security checks**

* **Errors 300–400:** You can disable these checks individually via the SDK Builder per-check methods (e.g. `.setUseDeveloperMode(bool use)` for 300, `.setUseAdb(bool use)` for 400). No change to the global security module is required.
* **Errors 500–699:** These checks are enforced inside the security module. To disable them you must set `enableSecurityModule = false` in `CafSdkConfiguration`. Where a per-check builder method exists, use it as well: `.setUseDebug(bool use)` for 500, `.checkAppSignature(use: Boolean)` for 600. For 601, 602, and 699 there is no per-check method; disabling the security module via `enableSecurityModule = false` is required.

#### Error 300 <a href="#error-300" id="error-300"></a>

Represents the blocking of devices with developer mode active.

Developer mode allows users to access advanced settings, such as debugging apps via USB. By default, the SDKs block devices in developer mode.

To disable this validation, use the `.setUseDeveloperMode(bool use)` method in the SDK Builder.

#### Error 400 <a href="#error-400" id="error-400"></a>

Represents the blocking of devices with Android Debug Bridge (ADB) enabled.

ADB allows users to install and debug apps and access a Unix shell. By default, the SDKs block devices with ADB enabled.

To disable this validation, use the `.setUseAdb(bool use)` method in the SDK Builder.

#### Error 500 <a href="#error-500" id="error-500"></a>

Represents the blocking of devices with debug mode enabled.

Debug mode allows users to debug applications via USB, enabling them to bypass SDK flows. By default, the SDKs block devices in debug mode.

To disable this validation, use the `.setUseDebug(bool use)` method in the SDK Builder and set `enableSecurityModule = false` in CafSdkConfiguration.

#### Error 600 <a href="#error-600" id="error-600"></a>

Represents the blocking of devices with fraudulent app signatures or tampering tools detected.

Signature verification blocks reverse engineering attacks and all other malicious attacks that can be done after this process in which the app has its original signature changed. Because of this, SDKs perform this blocking by default.

If you want to disable this validation, use the `.checkAppSignature(use: Boolean)` method in the SDK Builder and set `enableSecurityModule = false` in CafSdkConfiguration.

#### Error 601 <a href="#error-601" id="error-601"></a>

Represents the blocking of rooted devices or devices with root management frameworks.

Root access bypasses Android's security sandbox and allows full control of the device and application environment.

To disable this validation, set `enableSecurityModule = false` in CafSdkConfiguration.

#### Error 602 <a href="#error-602" id="error-602"></a>

Represents a security validation error.

Returned when the security validation process fails unexpectedly or a security detector fails to execute.

To avoid this error in development or if detectors are failing, disable the security module in CafSdkConfiguration with `enableSecurityModule = false`.

#### Error 699 <a href="#error-699" id="error-699"></a>

Represents an unknown or uncatalogued security error.

This code is used when the security module detects a condition that does not match any of the defined categories (500, 600, 601, 602).

To avoid this error in development, you can disable the security module in CafSdkConfiguration with `enableSecurityModule = false`.

### **Session Pre-loading (Optional)**

The `loadSession()` method allows you to pre-load the user session before starting the SDK flow. This improves the Face Liveness SDK opening time by preparing the session and camera initialization in advance, resulting in faster SDK startup when `start()` is called.

**When to use:**

* When you want to optimize the user experience by reducing the initial loading time
* When you have the opportunity to pre-load the session before the user actually needs to start the flow
* Particularly useful for Face Liveness module initialization

**Code example:**

```kotlin
val sdkBuilder = CafSdkProvider.Builder(
    mobileToken = "mobile-token",
    personId = "person-id",
    environment = CafEnvironment.PROD,
    configuration = sdkConfiguration,
    callback = ::callbackEvent
).build()

// Pre-load the session (optional)
sdkBuilder.loadSession(this)

// Later, when ready to start the flow
sdkBuilder.start(this)
```

**Important notes:**

* This method is optional and can be called after `build()` but before `start()`
* The context parameter should be a valid application context
* Pre-loading the session helps reduce the initial loading time when `start()` is eventually called
* This is particularly beneficial for Face Liveness module initialization

### **Configured Flow Start**

After building the `sdkBuilder` object with all configurations and the callback defined, the capture flow is started by calling the `start()` method. This method receives the context (application context is recommended) and initiates the sequential execution of the configured modules.

**Code to start the flow:**

```kotlin
sdkBuilder.start(this)
```

### Process details

* **Context:** the parameter passed to `start()` must be a valid context (e.g., the current `application` instance), allowing the SDK to display the capture screens and manage UI transitions.
* **Sequential Execution:** the SDK starts the modules in the order defined in `presentationOrder`. Each module is executed sequentially and, upon completion, triggers the next, ensuring that the flow follows the established logic.
* **Callback Integration:** during execution, the SDK uses the unified callback to send the corresponding events (loading, loaded, success, etc.), allowing the application to react in real-time according to the flow state.

### Complete a session

The completion or conclusion of a session in CafSDK occurs when all configured modules have been executed, or when an error/cancellation occurs in the flow.

**Complete session definition**

* **Complete Execution:** the session is considered complete when each module in the capture flow triggers a `Success` event, indicating that all operations were successfully performed.
* **Flow Interruption:** if an error occurs or if the user cancels the process at any point, the session is interrupted, and the `Error` or `Cancelled` event is triggered, allowing the application to take the necessary measures.

**Completion events**

* **Success:**
  * Returns results after all modules complete when `waitForAllServices` is enabled otherwise each module that ends successfully sends a `CafUnifiedEvent.Success` event, which includes:
    * `moduleName:` identifies the module that completed the operation (e.g., `"documentDetector"` or `"faceLiveness"`).
    * `signedResponse:` a JWT Token containing the result data obtained by the module's execution. This data may include information relevant to the process, such as captured images or validation results.
* **Failure:**
  * If a module fails to complete its operation, it triggers a `CafUnifiedEvent.Failure` event, which includes:
    * `response:` a JWT Token containing the result data obtained by the module's execution. This data may include information relevant to the process, such as captured images or validation results.
    * `type:` the type of failure.
    * `description:` a descriptive message explaining the failure, allowing for appropriate error handling or user notifications.
* **Error:**
  * If the flow is interrupted due to a failure or cancellation:
    * **Error:** a `CafUnifiedEvent.Error` event is triggered with a descriptive message of the problem, allowing the implementation of recovery logic or user notifications.
      * `response:` a JWT Token containing the result data obtained by the module's execution. This data may include information relevant to the process, such as captured images or validation results.
      * `type:` the type of error.
      * `description:` a descriptive message explaining the failure, allowing for appropriate error handling or user notifications.
* **Cancelled:**
  * If the process is canceled (e.g., by the user), the `CafUnifiedEvent.Cancelled` event is triggered, allowing resource cleanup or the display of informative messages.

These steps ensure that you have a complete and technical view of the CafSDK flow initialization and completion process, allowing for simplified integration and the implementation of appropriate strategies for handling each step of the capture flow.

{% hint style="info" %}
These steps ensure that you have a complete and technical view of the CafSDK flow initialization and completion process, allowing for simplified integration and the implementation of appropriate strategies for handling each step of the capture flow.
{% endhint %}

***

## Advanced flow customization

Learn how to customize and adjust the CafSDK capture flow to meet specific business and user experience requirements.

**Execution order**

* The order in which the modules will be executed is defined in the `presentationOrder` field of the `CafSdkConfiguration` object.
* This sequence is fundamental, as it directly impacts the flow logic. For example, if the process requires the document to be captured before facial verification, the order must reflect this priority.

### Specific configuration

To customize the modules individually, use the `setDocumentDetectorConfig` and `setFaceLivenessConfig` methods. They allow you to adjust critical parameters, such as:

* **Capture time:** defines the timeout for the user to perform manual capture.
* **Timeout:** establishes the maximum waiting limit for a service response.
* **Debug flags:** enable or disable debug modes to facilitate problem identification during development.
* **Layout and other parameters:** allow configuring visual and operational elements specific to each module.

**Visual customization**

With the `CafColorConfiguration` object, it is possible to align the visual identity of the capture flow with your application's brand. This customization ensures that visual elements (buttons, backgrounds, and indicators) maintain consistency with the application's design.

**Logging and monitoring**

The unified callback implements different log levels (DEBUG, USAGE, INFO), which enables a detailed view of each step of the flow. These logs are essential for integrating with monitoring tools, adjusting performance, or identifying problems in real time.

## Example of a implementation

```kotlin
    private fun startCaf() {
        val sdkConfiguration = CafSdkConfiguration(
            presentationOrder = listOf(CafModuleType.FACE_LIVENESS, CafModuleType.DOCUMENT_DETECTOR),
            colorConfig = CafColorConfiguration(primaryColor = "#0000FF", secondaryColor = "#00FF00"),
            enableSecurityModule = true,
            waitForAllServices = true // Optional, default is true
        ).apply {
            setDocumentDetectorConfig(
                CafDocumentDetectorConfig(
                    flow = listOf(DocumentDetectorStep(Document.RG_FRONT), DocumentDetectorStep(Document.RG_BACK)),
                    useAdb = true,
                    useDebug = true,
                    useDeveloperMode = true,
                    manualCaptureEnabled = true,
                    manualCaptureTime = 45,
                    requestTimeout = 60,
                    showPopup = true,
                    instructionsEnabled = true
                )
            )
            setFaceLivenessConfig(
                CafFaceLivenessConfig(
                    loading = true,
                    debugModeEnabled = true
                )
            )
        }
        CafSdkProvider.Builder(
            mobileToken = MOBILE_TOKEN,
            personId = PERSON_ID,
            environment = CafEnvironment.PROD,
            configuration = sdkConfiguration,
            callback = ::callbackEvent
        )
            .build()
            .start(requireContext().applicationContext)
    }

    private fun callbackEvent(event: CafUnifiedEvent): Unit = when (event) {
        is CafUnifiedEvent.Log -> {
            // Informative logs, useful for debugging and monitoring
            log("[LOG] ${event.level}: ${event.message}")
        }

        is CafUnifiedEvent.Loading -> {
            // Indicates some execution has been started internally (may display a loading screen)
            log("[LOADING]")
        }

        is CafUnifiedEvent.Loaded -> {
            // Indicates internal execution has been completed (may hide a loading screen)
            log("[LOADED]")
        }

        is CafUnifiedEvent.Success -> {
            // When the module is successfully completed, the callback receives the name of the module and the results
            event.response.forEach {
                log("[SUCCESS] moduleName: ${it.moduleName}")
                log("[SUCCESS] signedResponse: ${it.signedResponse}")
            }
        }

        is CafUnifiedEvent.Failure -> {
            // Captures failures that occur during execution and allows fault handling logic to be implemented
            log("[FAILURE] ${event.response}")
            log("[FAILURE] ${event.type}")
            log("[FAILURE] ${event.description}")
        }

        is CafUnifiedEvent.Error -> {
            // Captures errors that occur during execution and allows fault handling logic to be implemented
            log("[ERROR] ${event.message}")
        }

        is CafUnifiedEvent.Cancelled -> {
            // Informs that the operation was canceled by the user or due to an execution failure
            log("[CANCELLED]")
        }
    }
```

***

## Face Liveness configuration

The integration of the **Caf Face Liveness** **(FL)** module is done through its configuration in the `CafSdkConfiguration` object. Once defined, the flow automatically executes the module in the corresponding position defined in the presentation order.

The Face Liveness configuration is done through the `CafFaceLivenessConfig` object, where the parameters that the SDK will use during its execution are informed. Check out the main configuration methods available:

| Method                    | Type                    | Description                                                                                                                                     |
| ------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `setLoading`              | Boolean                 | Enables or disables the loading screen. The default is: `false`.                                                                                |
| `setAuthBaseUrl`          | String                  | Define a URL do proxy Defines the reverse proxy URL for authentication. Must use the HTTPS protocol. Optional. Required only for reverse proxy. |
| `setLivenessBaseUrl`      | String                  | Defines the reverse proxy URL for Face Liveness verification. Must use the WSS protocol. Optional. Required only for reverse proxy.             |
| `setCertificates`         | List                    | Defines the Base64 (SHA-256) encoded certificates for the reverse proxy. Optional. Required only for WSS via proxy.                             |
| `setScreenCaptureEnabled` | Boolean                 | Enables or disables screen capture. The default is: `false`.                                                                                    |
| `setDebugModeEnabled`     | Boolean                 | Enables or disables log generation to assist with debugging during integration. The default is`false`.                                          |
| `setSdkType`              | CafFaceLivenessPlatform | Informs which platform is running the SDK. The default is `CafFaceLivenessPlatform.NATIVE_ANDROID`.                                             |
| `setExecuteFaceAuth`      | Boolean                 | Sets whether to execute face authentication.                                                                                                    |

**Example configuration for Face Liveness:**

```kotlin
sdkConfiguration.setFaceLivenessConfig(
    CafFaceLivenessConfig(
        loading = true,
        reverseProxyConfig = CafReverseProxyConfig(    
            authBaseUrl = "https://my.proxy.io/v1/faces/",                          // Optional, only used with reverse proxy
            livenessBaseUrl = "wss://my.proxy.io/ws/",                              // Optional, only used with reverse proxy
            certificates = listOf("4d69f16113bed7d62ca56feb68d32a0fcb7293d3960=")   // Optional, only used with reverse proxy
        ),
        screenCaptureEnabled = true,
        debugModeEnabled = true,
        executeFaceAuth = true
    )
)
```

### Results

After the successful execution, a `CafUnifiedEvent.Success` event is triggered, which contains:

* **moduleName**: the module identifier name (e.g., "faceLiveness").
* **signedResponse**: a JWT token with the verification data.

Then, this data is processed by the unified callback, allowing the user interface to be updated or the flow to continue as needed.

***

## Custom configurations - Face Liveness

Use custom configurations to direct requests through secure proxies and ensure that the correct protocols (WSS for Face Liveness and HTTPS for authentication) are used.

### Reverse proxy configuration (optional)

This advanced configuration allows you to direct Face Liveness module connections through a reverse proxy, using the WSS (Web Socket Secure) protocol. Follow the steps to configure correctly:

* **Proxy URL:** define your proxy to communicate with the desired endpoint. For example, you can use: `wss://us.rp.secure.iproov.me/ws` or another compatible URL.
* **Face Liveness URL Configuration:** use the `.setLivenessBaseUrl` method to configure the Face Liveness URL. Remember that the protocol must be WSS.
* **Certificate Definition:** use the `.setCertificates` method to define the necessary certificates. These certificates must be the Base64 encoded SHA256 hashes of the proxy certificates.

**Code example:**

```kotlin
sdkConfiguration.setFaceLivenessConfig(
    CafFaceLivenessConfig(
        livenessBaseUrl = "wss://my.proxy.io/ws/",
        certificates = listOf(
            "4d69f16113bed7d62ca56feb68d32a0fcb7293d3960=",
            "50f71c5dda30741ee4be1ac378e12539b0d1d511f99=",
            "9f85e26c1ae41f7ac97adc4099be7f2a40759510ab9="
        )
    )
)
```

### **Reverse Proxy for Authentication** (optional)

For authentication communication, it is necessary to configure the reverse proxy with an HTTPS URL. This configuration directs authentication requests to the appropriate environment.

* **Proxy URL:** define your proxy to communicate. For example, you can use: `https://api.public.caf.io/`.
* **Authentication URL Configuration:** use the `.setAuthBaseUrl` method to specify the authentication URL, ensuring the HTTPS protocol is used.

**Code example:**

```kotlin
sdkConfiguration.setFaceLivenessConfig(
    CafFaceLivenessConfig(
        authBaseUrl = "https://my.proxy.io/v1/faces/"
    )
)
```

> Note: in practice, both configurations (for authentication and Face Liveness) can be combined into a single instance of `CafFaceLivenessConfig`.

## **Configuration Structures**

When using the UI module (with the `-ui` suffix), you will be using Caf's proprietary screens, which have some customization possibilities. Check the details:

### Caf Face Liveness Instructions Screen

This structure allows you to customize the Face Liveness instruction screen.

| Property      | Type            | Description                                                                                                                                           | Default value |
| ------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `image`       | `String?`       | Image displayed in the screen header. The value can be a URL, the resource ID (in string format) or the resource name present in the drawable folder. | `null`        |
| `title`       | `String?`       | Screen title (e.g., "Instructions to Scan Face").                                                                                                     | `null`        |
| `description` | `String?`       | Brief descriptive text (e.g., "Follow the steps below").                                                                                              | `null`        |
| `steps`       | `List<String>?` | Ordered list of instructions (e.g., listOf ("Keep the phone steady"; "Good lighting")).                                                               | `null`        |
| `buttonText`  | `String?`       | Text for the confirmation button (e.g., "Start scanning").                                                                                            | `null`        |

### Caf Color Configuration

This structure allows you to customize the global colors of all interfaces. The colors follow the standard `RGB` or `ARGB`.

<table><thead><tr><th>Property</th><th>Type</th><th width="166">Description</th><th>Format</th></tr></thead><tbody><tr><td><code>primaryColor</code></td><td><code>String</code></td><td>Main color for buttons and highlights.</td><td>Hex code (eg, <code>#FF0000</code>)</td></tr><tr><td><code>secondaryColor</code></td><td><code>String</code></td><td>Secondary color for complementary elements.</td><td>Hex code</td></tr><tr><td><code>backgroundColor</code></td><td><code>String</code></td><td>Screen background color.</td><td>Hex code</td></tr><tr><td><code>contentColor</code></td><td><code>String</code></td><td>Color used for texts and icons.</td><td>Hex code</td></tr><tr><td><code>mediumColor</code></td><td><code>String</code></td><td>Neutral color for elements like progress bars.</td><td>Hex code</td></tr></tbody></table>

## **Code examples**

Check out the example on how to configure the Face Liveness module with instructions, reverse proxy (for authentication and verification), and interface customization.

```kotlin
val sdkConfiguration = CafSdkConfiguration(
      presentationOrder = listOf(...),
      colorConfig = CafColorConfiguration(
         primaryColor = "#FF0000",
         secondaryColor = "#00FF00",
         backgroundColor = "#FFFFFF",
         contentColor = "#000000",
         mediumColor = "#D1D1D1"
      ),
      enableSecurityModule = true
)
sdkConfiguration.setFaceLivenessConfig(
   CafFaceLivenessConfig(
        loading = true,
        reverseProxyConfig = CafReverseProxyConfig(
            authBaseUrl = "https://my.proxy.io/v1/faces/",
            livenessBaseUrl = "wss://my.proxy.io/ws/",
            certificates = listOf(
                "4d69f16113bed7d62ca56feb68d32a0fcb7293d3960=",
                "50f71c5dda30741ee4be1ac378e12539b0d1d511f99=",
                "9f85e26c1ae41f7ac97adc4099be7f2a40759510ab9="
            )
        ),
        screenCaptureEnabled = true,
        debugModeEnabled = true,
        maxRetryAttempts = 3
   )
)
sdkConfiguration.setCafFaceLivenessInstructionsScreen(
   CafFaceLivenessInstructionsScreen(
        image = R.drawable.scan_icon.toString()
        title = "Custom title",
        description = "Follow the steps below:",
        steps = listOf("Keep the phone steady", "Ensure good lighting"),
        buttonText = "Start scanning",
   )
)
```

***

## More information

**Certificate requirements**

* **Certificates:** they must be the Base64 encoded SHA-256 hashes of the SPKI (Subject Public Key Info) of the certificate.

### Protocol application

* **Face Liveness:** The URL for Face Liveness **must** use the `wss://` when using a reverse proxy.
* **Authentication:** The URL for authentication **must** use the `https://` when using a reverse proxy.

***

## Document Detector configuration

The Caf Document Detector (DD) module is configured similarly to Face Liveness, but with a focus on document capture and processing.

**Configuration and execution**

In `CafSdkConfiguration`, configure the specific Document Detector parameters, which determine the document capture behavior.

**Main parameters:**

* `flow`: a list of steps (`DocumentDetectorStep`) that defines which document and which angles or parts should be captured.
* `useAdb`, `useDebug`, and `useDeveloperMode`: flags that assist in development and execution in test environments.
* `manualCaptureEnabled` and `manualCaptureTime`: configure whether manual capture is allowed and what the timeout for the action is.
* `requestTimeout`: maximum time to wait for server responses or user actions.
* `showPopup`: determines whether a confirmation or instruction message will be presented to the user.
* `maxRetryAttempts`: defines the maximum number of attempts allowed before interrupting the process or displaying an error message to the user

**Configuration example for Document Detector:**

```kotlin
sdkConfiguration.setDocumentDetectorConfig(
    CafDocumentDetectorConfig(
        flow = listOf(DocumentDetectorStep(Document.RG_FRONT)),
        useAdb = true,
        useDebug = true,
        useDeveloperMode = true,
        manualCaptureEnabled = true,
        manualCaptureTime = 45,
        requestTimeout = 60,
        showPopup = true
    )
)
```

### Results

* Upon completing document capture and processing, the Document Detector module triggers a `CafUnifiedEvent.Success` event.
* This event includes the `moduleName` (e.g.,`"documentDetector"`) and a `result` containing the captured data.
* The unified callback can then use this information to proceed to the next step or to store the results as needed.

***

## Custom configurations - Document Detector

To configure the Caf Document Detector, use the `CafDocumentDetectorConfig` structure, which includes:

* Document capture flow steps.
* User interface (UI) layout customization.
* Feedback messages.
* Upload behavior.
* Proxy settings.

### Core configuration

Properties of `CafDocumentDetectorConfig`.

| Property                     | Type                         | Description                                                                                                                                                  |
| ---------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `flow`                       | `List<DocumentDetectorStep>` | Defines the document capture flow. See [DocumentDetectorStep](#documentdetectorstep)                                                                         |
| `layoutId`                   | `Int?`                       | Custom layout ID.                                                                                                                                            |
| `uploadSettings`             | `UploadSettings?`            | Settings for document upload. See [UploadSettings](#uploadsettings)                                                                                          |
| `manualCaptureEnabled`       | `Boolean?`                   | Enables or disables manual capture.                                                                                                                          |
| `manualCaptureTime`          | `Int?`                       | Timeout for manual capture (in seconds).                                                                                                                     |
| `requestTimeout`             | `Int?`                       | Timeout for requests (in seconds).                                                                                                                           |
| `showPopup`                  | `Boolean?`                   | Enables or disables popups before capture.                                                                                                                   |
| `proxySettings`              | `ProxySettings?`             | Proxy settings. See [ProxySettings](#proxysettings)                                                                                                          |
| `previewShow`                | `Boolean?`                   | Enables or disables the preview of the captured image.                                                                                                       |
| `instructionsEnabled`        | `Bool`                       | Enables instruction preview screen.                                                                                                                          |
| `ddCustomizations`           | `List<CafDDCustomization>?`  | List of UI string and asset customizations for Document Detector screens (e.g., upload popup, preview screen).                                               |
| `getUrlExpireTime`           | `String?`                    | Defines how long the image URL will remain active on the server until it expires. Accepts intervals such as `30m` (minutes), `24h` (hours), or `10d` (days). |
| `allowedPassportCountryList` | `List<CountryCodesList>?`    | List of allowed countries for passports. See [CountryCodesList](#countrycodeslist)                                                                           |
| `useDebug`                   | `Boolean?`                   | Allows the app to run in debug mode when `true`. **Not recommended for production**                                                                          |
| `useDeveloperMode`           | `Boolean?`                   | Enables developer mode when `true`. **Not recommended for production**                                                                                       |
| `useAdb`                     | `Boolean?`                   | Enables Android Debug Bridge (ADB) debugging mode when `true`. **Not recommended for production**                                                            |

### **DocumentDetectorStep**

To create a capture flow, you must create an array of **`DocumentDetectorStep`**, where each element represents a capture step. To build each `DocumentDetectorStep` object, you can use the following:

#### Constructor

| Property             | Type       | Description                                                            | Required | Default                         |
| -------------------- | ---------- | ---------------------------------------------------------------------- | -------- | ------------------------------- |
| `document`           | `Document` | Document type to capture (e.g., `.rgFront`).                           | Yes      |                                 |
| `stringStepLabel`    | `String?`  | Text shown at the bottom of the screen for this step.                  | No       | Document's default label        |
| `stringIllustration` | `String?`  | Image shown in the instruction popup for this step.                    | No       | Document's default illustration |
| `stringMessage`      | `String?`  | Custom message text for the instruction popup of this step.            | No       | Document's default message      |
| `okButtonTitle`      | `String?`  | Custom text for the 'OK' button in the instruction popup of this step. | No       | "OK"                            |

| Property                                | Description                                                                         |
| --------------------------------------- | ----------------------------------------------------------------------------------- |
| `document: Document`                    | Specifies the document to be captured in the step. Check the supported types below. |
| `setStepLabel(stepLabel: Int)`          | Sets the text displayed at the bottom of the layout.                                |
| `setIllustration(illustration: Int)`    | Sets the illustration displayed in the popup before capture.                        |
| `showStepLabel(showStepLabel: Boolean)` | Toggles the visibility of the text at the top of the layout.                        |

#### Supported Documents

| Document     | Description                                                                                                     |
| ------------ | --------------------------------------------------------------------------------------------------------------- |
| `RG_FRONT`   | Front side of the RG document, where the photo is located.                                                      |
| `RG_BACK`    | Back side of the RG document.                                                                                   |
| `RG_FULL`    | Open RG document, displaying both the front and back sides together.                                            |
| `CNH_FRONT`  | Front side of the CNH document, where the photo is located.                                                     |
| `CNH_BACK`   | Back side of the CNH document.                                                                                  |
| `CNH_FULL`   | Open CNH document, displaying both the front and back sides together.                                           |
| `CRLV`       | CRLV document.                                                                                                  |
| `RNE_FRONT`  | Front side of the RNE or RNM document.                                                                          |
| `RNE_BACK`   | Back side of the RNE or RNM document.                                                                           |
| `PASSPORT`   | Passport document, displaying the photo and personal data.                                                      |
| `CTPS_FRONT` | Front side of the CTPS document, where the photo is located.                                                    |
| `CTPS_BACK`  | Back side of the CTPS document.                                                                                 |
| `ANY`        | Allows submission of any type of document, including all those listed above or any other unclassified document. |

**Example:**

```kotlin
val detectorStep = DocumentDetectorStep(
        Document.RG_FRONT
        "Front of ID",
        "https://my.custom/image.jpg",
        "Please place the front of your ID card in the frame.",
        "Got it!"
    )
```

### **UploadSettings**

Configures the settings related to document upload.

| Property                                          | Description                                               |
| ------------------------------------------------- | --------------------------------------------------------- |
| `.setEnable(enable: Boolean)`                     | Enables or disables this feature.                         |
| `.setCompress(enable: Boolean)`                   | Enables or disables file compression before upload.       |
| `.setFileFormats(fileFormats: Array<FileFormat>)` | Specifies the accepted file formats for upload.           |
| `.setMaxFileSize(maxFileSize: Int)`               | Sets the maximum file size limit in KB.                   |
| `.setActivityLayout(activityLayout: Int)`         | Defines the background layout for document upload.        |
| `.setPopUpLayout(popUpLayout: Int)`               | Defines the popup layout for the document upload request. |

Currently, the supported file formats are:

| Type   | Value             |
| ------ | ----------------- |
| `PNG`  | `image/png`       |
| `JPG`  | `image/jpg`       |
| `JPEG` | `image/jpeg`      |
| `PDF`  | `application/pdf` |
| `HEIF` | `image/heif`      |

### **ProxySettings**

For the SDK to use a proxy when making requests, you must configure an instance of the **`ProxySettings`** class.

#### **Constructor Method**

| Property   | Type     | Description                                         |
| ---------- | -------- | --------------------------------------------------- |
| `hostname` | `String` | Sets the domain or IP address of the proxy service. |
| `port`     | `String` | Sets the port to be used.                           |

#### **Optional Methods**

**`setAuthentication(String user, String password)`**

Sets the authentication parameters for the proxy, if necessary.

| Property   | Description                             |
| ---------- | --------------------------------------- |
| `user`     | Username to be used for authentication. |
| `password` | Password to be used for authentication. |

**`setProxyCertificate(@RawRes Integer proxyCertificate)`**

If your proxy server uses a self-signed SSL certificate or one issued by a non-public Certification Authority (CA), add the CA certificate in `PEM` or `DER` format to the `res/raw/` directory (e.g., `res/raw/proxy_certificate`) and pass the file identifier as an argument (e.g., `R.raw.proxy_certificate`).

| Property           | Description                       |
| ------------------ | --------------------------------- |
| `proxyCertificate` | ID of the proxy certificate file. |

**`setMTLSConfig(@RawRes Integer clientCertificate, String password)`**

If your proxy server supports mTLS, save the client certificate in `PKCS12` format (`.p12`) to the `res/raw/` directory (e.g., `res/raw/client_certificate`) and pass the file identifier (e.g., `R.raw.client_certificate`) and the private key as arguments.

| Property            | Description                        |
| ------------------- | ---------------------------------- |
| `clientCertificate` | ID of the client certificate file. |
| `password`          | Private key to be used.            |

### UI String and Asset Customization (`CafDDCustomization`)

The `ddCustomizations` property in `CafDocumentDetectorConfig` allows you to provide an array of objects conforming to `CafDDCustomization` to override default texts and images on specific Document Detector screens.

#### `CafPreviewCustomization`

Customizes the document preview screen shown after a document image is captured (if `previewShow` is `true`).

| Property         | Type      | Description                                  | Default (Localized)               |
| ---------------- | --------- | -------------------------------------------- | --------------------------------- |
| `title`          | `String?` | Title text on the preview screen.            | "Is the photo good?"              |
| `message`        | `String?` | Subtitle/message text on the preview screen. | "Check if all info is legible..." |
| `okButton`       | `String?` | Text for the confirmation ("accept") button. | "Yes, it's good!"                 |
| `tryAgainButton` | `String?` | Text for the retry ("take again") button.    | "Take again"                      |

**Example:**

```kotlin
val previewCustom = CafDDCustomization.CafPreviewCustomization(
                        title: "Confirm Photo Quality",
                        message: "Ensure all details are clear and there are no reflections.",
                        okButton: "Confirm",
                        tryAgainButton: "Recapture"
                    )
// Add to CafDocumentDetectorConfig:
// ddCustomizations = listOf(previewCustom)
```

#### `CafDDUploadCustomization`

Customizes the popup shown when the user chooses to upload a document file.

| Property       | Type      | Description                              | Default (Localized)      |
| -------------- | --------- | ---------------------------------------- | ------------------------ |
| `image`        | `String?` | Image displayed at the top of the popup. | Default SDK illustration |
| `message`      | `String?` | Message text within the upload popup.    | "Select the file..."     |
| `uploadButton` | `String?` | Text for the "Upload" button.            | "Upload"                 |
| `cancelButton` | `String?` | Text for the "Cancel" button.            | "Cancel"                 |

**Example:**

```kotlin
val uploadCustom = CafDDCustomization.CafDDUploadCustomization(
                    message: "Please choose the document file you want to upload.",
                    uploadButton: "Choose File",
                    cancelButton: "Go Back"
                )
// Add to CafDocumentDetectorConfig:
// ddCustomizations = listOf(previewCustom, uploadCustom) // Can have multiple customizations
```

#### `CafMessageCustomization`

Customizes various in-flow messages displayed during the document capture process (e.g., sensor messages, AI feedback).

| Property                       | Description                                                                   |
| ------------------------------ | ----------------------------------------------------------------------------- |
| `waitMessage`                  | Message displayed when starting the camera.                                   |
| `fitTheDocumentMessage`        | Message prompting the user to fit the document within the frame.              |
| `holdItMessage`                | Message displayed during the capture process.                                 |
| `verifyingQualityMessage`      | Message displayed during the quality verification request.                    |
| `lowQualityDocumentMessage`    | Message displayed when document capture fails due to low quality.             |
| `uploadingImageMessage`        | Message displayed when saving the captured image to the server.               |
| `openDocumentWrongMessage`     | Message displayed if an open document is detected.                            |
| `unsupportedDocumentMessage`   | Message for unsupported documents.                                            |
| `documentNotFoundMessage`      | Message displayed when no document is detected.                               |
| `sensorLuminosityMessage`      | Message displayed when the brightness level is too low.                       |
| `sensorOrientationMessage`     | Message displayed when the orientation threshold is not met.                  |
| `sensorStabilityMessage`       | Message displayed when the device is not stable enough.                       |
| `popupDocumentSubtitleMessage` | Subtitle message displayed in the popup presenting the document illustration. |
| `positiveButtonMessage`        | Message displayed on the confirmation button.                                 |
| `aiScanDocumentMessage`        | Message prompting the user to scan a document.                                |
| `aiGetCloserMessage`           | Message prompting the user to get closer to the document.                     |
| `aiCentralizeMessage`          | Message prompting the user to center the document on the screen.              |
| `aiMoveAwayMessage`            | Message prompting the user to move away from the document.                    |
| `aiAlignMessage`               | Message prompting the user to align the document.                             |
| `aiTurnDocumentMessage`        | Message prompting the user to rotate the document 90 degrees.                 |
| `aiCapturedMessage`            | Message confirming that the document has been captured.                       |
| `wrongDocumentMessage`         | Message displayed when the document type is incorrect.                        |

**Example:**

```kotlin
val messageCustom = CafMessageCustomization(
    waitMessage: "Please wait...",
    fitTheDocumentMessage: "Align your document within the frame."
)
// Add to CafDocumentDetectorConfig:
// ddCustomizations = listOf(previewCustom, uploadCustom, messageCustom)
```

### **CountryCodesList**

Complete list of the official codes currently assigned according to [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3).

## Customizing Screens

When using the UI module (with the `-ui` suffix), you will be using CAF's proprietary screens. These screens offer customization options as described below.

### CafDocumentDetectorInstructionsScreen

This structure allows you to customize the instructions screen.

| Property      | Type            | Description                                                                                                                                           |
| ------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `image`       | `String?`       | Image displayed in the header of the screen. The value can be a URL, a resource ID (as a string), or the name of the resource in the drawable folder. |
| `title`       | `String?`       | Screen title (e.g., "Instructions for Scanning the Face").                                                                                            |
| `description` | `String?`       | Brief descriptive text (e.g., "Follow the steps below").                                                                                              |
| `steps`       | `List<String>?` | Ordered list of instructions (e.g., `listOf("Keep the phone steady", "Ensure good lighting")`).                                                       |
| `buttonText`  | `String?`       | Text for the confirmation button (e.g., "Start Scanning").                                                                                            |

### CafDocumentDetectorDocumentSelectionScreen

This structure allows you to customize the document selection screen.

| Property      | Type                      | Description                                                                                                                                 |
| ------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `documents`   | `List<CafDocument>`       | List of documents to be displayed. The value can be a URL, a resource ID (as a string), or the name of the resource in the drawable folder. |
| `title`       | `String?`                 | Screen title (e.g., "Select the Document").                                                                                                 |
| `description` | `String?`                 | Brief descriptive text (e.g., "Choose the document you want to submit").                                                                    |
| `groupLabels` | `CafDocumentGroupLabels?` | Configures document selection screen items (title/description) based on document groups.                                                    |

#### CafDocument

| Name        | Description                                                             |
| ----------- | ----------------------------------------------------------------------- |
| `RGFront`   | Front side of the RG document, where the photo is located.              |
| `RGBack`    | Back side of the RG document.                                           |
| `RGFull`    | Open RG document, displaying both the front and back sides together.    |
| `CnhFront`  | Front side of the CNH document, where the photo is located.             |
| `CnhBack`   | Back side of the CNH document.                                          |
| `CnhFull`   | Open CNH document, displaying both the front and back sides together.   |
| `Crlv`      | CRLV document.                                                          |
| `RneFront`  | Front side of the RNE or RNM document.                                  |
| `RneBack`   | Back side of the RNE or RNM document.                                   |
| `Passport`  | Passport document, displaying the photo and personal data.              |
| `CtpsFront` | Front side of the CTPS document, where the photo is located.            |
| `CtpsBack`  | Back side of the CTPS document.                                         |
| `Other`     | Allows submission of any other type of document that is not classified. |

### CafColorConfiguration

This structure allows you to customize the global colors of all interfaces. The colors follow the `RGB` or `ARGB` standard.

| Property                | Type     | Description                                    | Format                     |
| ----------------------- | -------- | ---------------------------------------------- | -------------------------- |
| `primaryColor`          | `String` | Primary color for buttons and highlights.      | Hex Code (e.g., `#FF0000`) |
| `secondaryColor`        | `String` | Secondary color for complementary elements.    | Hex Code                   |
| `backgroundColor`       | `String` | Background color of the screen.                | Hex Code                   |
| `contentColor`          | `String` | Color used for text and icons.                 | Hex Code                   |
| `mediumColor`           | `String` | Neutral color for elements like progress bars. | Hex Code                   |
| `dialogBackgroundColor` | `String` | Dialog and popup background color.             | Hex Code                   |
| `dialogBorderColor`     | `String` | Dialog and popup border color.                 | Hex Code                   |

## Code Examples

The following example demonstrates how to configure the DocumentDetector module with instructions and interface customization:

```kotlin
private fun isDarkMode() = 
    (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES

val colorConfigConfiguration = if (isDarkMode()) {
    CafColorConfiguration(
        primaryColor = "#00FF00",
        secondaryColor = "#FF0000",
        backgroundColor = "#000000",
        contentColor = "#FFFFFF",
        mediumColor = "#D1D1D1",
        dialogBackgroundColor: "#FFFFFF",
        dialogBorderColor: "#E5E5E7"
    )
} else {
    CafColorConfiguration(
        primaryColor = "#FF0000",
        secondaryColor = "#00FF00",
        backgroundColor = "#FFFFFF",
        contentColor = "#000000",
        mediumColor = "#D1D1D1",
        dialogBackgroundColor: "#FFFFFF",
        dialogBorderColor: "#E5E5E7"  
    )
}

val sdkConfiguration = CafSdkConfiguration(
    presentationOrder = listOf(...),
    colorConfig = colorConfigConfiguration,
    enableSecurityModule = true
)

sdkConfiguration.setDocumentDetectorConfig(
    CafDocumentDetectorConfig(
        flow = listOf(),        // When using UI, this can be empty because the list will be defined in CafDocumentDetectorDocumentSelectionScreen
        uploadSettings = false, // When using UI, this will be ignored as the user can select on the screen
        useDebug = true,
        useDeveloperMode = true,
        useAdb = true
    )
)

sdkConfiguration.setCafDocumentDetectorDocumentSelectionScreen(
    CafDocumentDetectorDocumentSelectionScreen(
        documents = listOf(CafDocument.RGFront(), CafDocument.RGBack(), CafDocument.CnhFront(), CafDocument.CnhBack()),
        title = "Custom title",
        description = "custom description",
        groupLabels = CafDocumentGroupLabels(
                            rg = CafDocumentLabel("Custom RG Title", "Custom RG Description")
                        )
    )
)

sdkConfiguration.setCafDocumentDetectorInstructionsScreen(
    CafDocumentDetectorInstructionsScreen(
        title = "Custom title",
        steps = listOf("Keep the phone steady", "Ensure good lighting"),
        buttonText = "Start"
    )
)
```

## CafUnifiedResponse

```kotlin
public class CafUnifiedResponse(
    public val moduleName: String,
    public val signedResponse: String,
)
```

| Property         | Type     | Description                                                 |
| ---------------- | -------- | ----------------------------------------------------------- |
| `moduleName`     | `String` | Name of the module issuing its result in the success event. |
| `signedResponse` | `String` | JWT containing the data obtained by the module's execution. |

***

## Additional resources

**ProGuard/R8 Rules**

Check out the code block with the ProGuard/R8 rules necessary for CafSDK and its dependencies to function correctly even after code obfuscation and optimization. These rules preserve essential information (such as signatures, annotations, and internal classes) and prevent critical classes from being removed or altered.

```proguard
# The Android pre-handler for exceptions is loaded reflectively (via ServiceLoader).
-keep class kotlinx.coroutines.experimental.android.AndroidExceptionPreHandler { *; }

### GSON ##################################################################
# Gson uses generic type information stored in a class file when working with fields.
# ProGuard removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
### END GSON ##################################################################

### Retrofit ##################################################################
# Preserve generic signatures, inner classes, and enclosing methods for Retrofit reflection.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retain runtime-visible annotations on methods and parameters.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
# Keep annotation default values.
-keepattributes AnnotationDefault
# Retain service method parameters for interfaces with Retrofit annotations.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}
# Suppress warnings for build tooling and certain JSR 305 annotations.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn javax.annotation.**
-dontwarn kotlin.Unit
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*
# Explicitly keep Retrofit interfaces to prevent nullification by R8.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface * extends <1>
# Preserve continuations used by Kotlin suspend functions.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
# For R8 full mode: keep generic return types for Retrofit methods.
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
# Preserve Retrofit Response class.
-keep,allowobfuscation,allowshrinking class retrofit2.Response
### END Retrofit ##############################################################

### OkHttp ####################################################################
# Suppress warnings for JSR 305 annotations.
-dontwarn javax.annotation.**
# Adapt resource filenames for internal public suffix database.
-adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz
# Suppress warnings for Animal Sniffer and platform-specific classes.
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**
-dontwarn org.openjsse.**
# Keep all OkHttp and Okio classes.
-keep class okhttp3.** { *; }
-dontwarn okhttp3.**
-keep class okio.** { *; }
-dontwarn okio.**
-dontwarn javax.annotation.Nullable
-dontwarn javax.annotation.ParametersAreNonnullByDefault
### END OkHttp ################################################################

### Kotlin Serialization ######################################################
# Keep Companion objects for serializable classes.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
    static <1>$Companion Companion;
}
# Keep serializer functions on companion objects.
-if @kotlinx.serialization.Serializable class ** {
    static **$* *;
}
-keepclassmembers class <2>$<3> {
    kotlinx.serialization.KSerializer serializer(...);
}
# Retain INSTANCE and serializer for serializable objects.
-if @kotlinx.serialization.Serializable class ** {
    public static ** INSTANCE;
}
-keepclassmembers class <1> {
    public static <1> INSTANCE;
    kotlinx.serialization.KSerializer serializer(...);
}
# Preserve Companion objects in kotlinx.serialization.json.
-keepclassmembers class kotlinx.serialization.json.** {
    *** Companion;
}
-keepclasseswithmembers class kotlinx.serialization.json.** {
    kotlinx.serialization.KSerializer serializer(...);
}
# Preserve serializer lookup for serializable classes (adjust package name as needed).
-keepclassmembers @kotlinx.serialization.Serializable class packeage.** {
    *** Companion;
    *** INSTANCE;
    kotlinx.serialization.KSerializer serializer(...);
}
### END Kotlin Serialization #################################################

### AutoValue ################################################################
-dontwarn com.google.auto.**
-dontwarn autovalue.shaded.com.**
-dontwarn sun.misc.Unsafe
-dontwarn javax.lang.model.element.Modifier
### END AutoValue ############################################################

### CAF - Combate a Fraude ######################################################
# Keep exceptions attributes.
-keepattributes Exceptions
# Preserve all classes, interfaces, and class members for CAF modules.
-keep class com.caf.facelivenessiproov.** { *; }
-keep class com.combateafraude.documentdetector.** { *; }
-keep class com.combateafraude.** { *; }
-keep interface com.combateafraude.** { *; }
-keep class io.caf.** { *; }
-keep interface io.caf.** { *; }
-keepclassmembers class com.combateafraude.** { *; }
# Suppress warnings for java.nio.file and certain OkHttp internal classes.
-dontwarn java.nio.file.*
-dontwarn com.squareup.okhttp.internal.Platform
# Keep fields in classes extending GeneratedMessageLite (for Tink usage).
-keepclassmembers class * extends com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite {
  <fields>;
}
# Preserve TensorFlow classes.
-keep class org.tensorflow.** { *; }
-keep class org.tensorflow.**$* { *; }
-dontwarn org.tensorflow.**
# Preserve IProov classes and Protobuf classes.
-keep public class com.iproov.sdk.IProov { public *; }
-keep class com.iproov.** { *; }
-keep class com.iproov.**$* { *; }
-keep class com.google.protobuf.** { *; }
-keep class com.google.protobuf.**$* { *; }
-dontwarn com.google.protobuf.**
# Suppress warnings for concurrent Flow classes.
-dontwarn java.util.concurrent.Flow*
# Preserve Kotlin and kotlinx classes.
-keep class kotlin.** { *; }
-keep class kotlinx.** { *; }
-dontwarn com.android.tools.lint.**
-dontwarn io.caf.sdk.common.jvmshared.lint.**
### END CAF - Combate a Fraude ##################################################
```

***

## Technical Support and Usage Tips

**Technical Support** If you have any questions or difficulties with the integration, contact Caf's technical support.

**Usage tips**

* **Run tests:** perform tests on real devices to validate requirements and flow performance.
* **Explore customizations:** use advanced customization options to tailor the flow to your project's needs.
* **Monitor performance:** integrate monitoring tools to track logs and the flow's performance in production.

***


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.caf.io/caf-sdk/android/getting-started-with-the-sdk-1.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
