> ## Documentation Index
> Fetch the complete documentation index at: https://doc.youverify.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Integrate Youverify Android SDK into Your Mobile App

> Embed real-time liveness detection and document capture in your Android application using the Youverify Android SDK.

The Youverify Android SDK lets you add anti-deepfake liveness detection directly to your Android application using Jetpack Compose. Users perform a brief head-movement task that proves a live person — not a photo, video, or deepfake — is present. Before launching the SDK you must generate two server-side tokens (a session ID and a liveness token) to authenticate the session securely.

## Current version

The latest Android Liveness SDK version is **0.0.12**.

## Prerequisites

* Android minimum SDK: API level 24 (Android 7.0)
* Jetpack Compose enabled in your project
* `CAMERA` permission declared in your `AndroidManifest.xml`

## Step 1 — Add the dependency

Add the Youverify Liveness SDK to your app module's `build.gradle.kts`:

```kotlin theme={null}
dependencies {
    implementation("co.youverify:liveness-sdk-android:0.0.12")
}
```

Also add the ABI filter configuration to support the required native architectures:

```kotlin theme={null}
android {
    defaultConfig {
        ndk {
            abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86"))
        }
    }
}
```

## Step 2 — Declare the camera permission

Add the following to your `AndroidManifest.xml`:

```xml theme={null}
<uses-permission android:name="android.permission.CAMERA" />
```

Request the permission at runtime before launching the SDK if your app targets API level 23 or higher.

## Step 3 — Generate tokens server-side

Before initializing the SDK you need two tokens generated by your backend. Neither token should be generated in your Android app.

**Generate session ID** — call `POST /v2/api/sdk/session-id`:

```kotlin theme={null}
// In your backend or LivenessSessionRepository
val bodyJson = JSONObject().apply {
    put("publicMerchantID", publicMerchantId)
    put("metadata", JSONObject())
}.toString()

val request = Request.Builder()
    .url("https://api.youverify.co/v2/api/sdk/session-id")
    .addHeader("token", apiToken)
    .post(bodyJson.toRequestBody("application/json".toMediaType()))
    .build()
// Response contains: { "data": { "sessionId": "..." } }
```

**Generate liveness token** — call `POST /v2/api/sdk/liveness-token`:

```kotlin theme={null}
val bodyJson = JSONObject().apply {
    put("publicMerchantID", publicMerchantId)
    put("deviceCorrelationId", deviceCorrelationId)
}.toString()

val request = Request.Builder()
    .url("https://api.youverify.co/v2/api/sdk/liveness-token")
    .addHeader("token", apiToken)
    .post(bodyJson.toRequestBody("application/json".toMediaType()))
    .build()
// Response contains: { "data": { "authToken": "..." } }
```

<Warning>
  Never embed your API secret key (`apiToken`) in your Android app. Make these calls from your server and deliver only the resulting `sessionId` and `authToken` to the app.
</Warning>

## Step 4 — Initialize and launch the SDK

Once you have the `sessionId` and `sessionToken` from your backend, initialize the SDK in a Composable:

```kotlin theme={null}
@Composable
fun LivenessComponent(
    publicKey: String,
    sessionId: String,
    sessionToken: String
) {
    val livenessConfig = YVLivenessConfig(
        publicKey = publicKey,
        sessionId = sessionId,
        sessionToken = sessionToken,
        sandboxEnvironment = false,   // set to true for testing
        user = SDKUser(
            firstName = "John",
            lastName = "Doe"
        ),
        onSuccess = { data ->
            println("Liveness passed: ${data?.passed}")
            // Notify your backend with the session result
        },
        onFailure = { data ->
            when (data?.error?.key) {
                "invalid_or_expired_session" -> {
                    // Session expired — refresh tokens and retry
                }
                "session_token_error" -> {
                    // Token error — refresh tokens and retry
                }
            }
        },
        onClose = {
            println("User closed the liveness flow")
        }
    )

    val livenessController = remember { YVLivenessSDKController(livenessConfig) }

    YVLivenessSDK(livenessController)

    // Trigger a specific liveness task
    LaunchedEffect(Unit) {
        livenessController.start(tasks = listOf(
            MotionTaskOptions()
        ))
    }
}
```

## Available liveness tasks

The SDK supports four task types. Pass them to `livenessController.start(tasks = listOf(...))`:

| Task class | Description |
| - | - |
| `CTCTaskOptions` | Complete the Circle — user traces a circle with head movement |
| `MotionTaskOptions` | Motions — random sequence of nods, blinks, and mouth opening |
| `BlinkTaskOptions` | Blink — user blinks a set number of times |
| `YesOrNoTaskOptions` | Yes or No — user answers questions by tilting their head |

## Callback data

Both `onSuccess` and `onFailure` receive a `LivenessData` object:

<ResponseField name="data.passed" type="boolean">
  `true` if the liveness check passed.
</ResponseField>

<ResponseField name="data.faceImage" type="string">
  Base64-encoded face image captured during the check.
</ResponseField>

<ResponseField name="data.livenessClip" type="string">
  Video clip of the user performing the liveness task.
</ResponseField>

<ResponseField name="data.error" type="object">
  Present only in failure cases. Contains `key` (e.g. `eyes_closed`, `image_capture_failed`, `invalid_or_expired_session`) and `message`.
</ResponseField>

## Configuration options

<ParamField body="publicKey" type="string">
  Your Youverify public merchant key. Safe to embed in your app.
</ParamField>

<ParamField body="sessionId" type="string" required>
  Session ID generated server-side via `POST /v2/api/sdk/session-id`.
</ParamField>

<ParamField body="sessionToken" type="string" required>
  Liveness auth token generated server-side via `POST /v2/api/sdk/liveness-token`.
</ParamField>

<ParamField body="sandboxEnvironment" type="boolean" default="true">
  Set to `false` for production. Defaults to `true` (sandbox mode).
</ParamField>

<ParamField body="user" type="SDKUser">
  User details for the liveness session. `firstName` is required; `lastName` and `email` are optional.
</ParamField>

<ParamField body="allowAudio" type="boolean" default="false">
  Set to `true` to narrate task instructions to the user via audio.
</ParamField>

## Supported document types

When using the Document Capture SDK for Android alongside the Liveness SDK, the following document types are supported for capture: passports, national identity cards, driver's licences, and residence permits. For a full list of supported countries and document types, see the [SDKs overview](/sdks/overview).

<Note>
  Session tokens expire after a short period. If you receive an `invalid_or_expired_session` error, generate fresh `sessionId` and `sessionToken` values from your backend and re-initialize the SDK.
</Note>
