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

# Android (Kotlin)

> Official Kotlin SDK for the Verilock Identity API.

## Requirements

| Requirement       | Minimum Version          |
| ----------------- | ------------------------ |
| Android           | minSdk 24 (Android 7.0+) |
| Kotlin            | 1.9+                     |
| Kotlin Coroutines | 1.7+                     |
| AGP               | 8.0+                     |

## Installation

Add the Verilock SDK to your module-level `build.gradle.kts`:

```kotlin build.gradle.kts theme={null}
dependencies {
    implementation("io.verilock:verilock-sdk:1.0.0")
}
```

Make sure you have Maven Central in your project-level settings:

```kotlin settings.gradle.kts theme={null}
dependencyResolutionManagement {
    repositories {
        mavenCentral()
    }
}
```

## Configuration

Create a `Verilock` client with your API key. All API calls are made through this instance.

```kotlin theme={null}
import io.verilock.sdk.Verilock

val verilock = Verilock(apiKey = "qi_live_...")
```

You can customise the client with optional parameters:

```kotlin theme={null}
val verilock = Verilock(
    apiKey = "qi_live_...",
    baseUrl = "https://verilock.io/api/v1",  // default
    timeout = 30_000,                      // milliseconds, default
    maxRetries = 2,                        // retries on 429/5xx, default
)
```

<Warning>
  **Keep your API key secure.** Never embed production keys in client-side code or commit them to version control. All API calls should originate from your backend or a secure context.
</Warning>

## Quick Start

Create a KYC session, upload a document and selfie, then submit for verification. All methods are `suspend` functions.

```kotlin theme={null}
import io.verilock.sdk.*

val verilock = Verilock(apiKey = "qi_live_...")

// 1. Create a session
val session = verilock.sessions.create(
    CreateSessionParams(
        applicant_email = "john@example.com",
        redirect_url = "https://example.com/callback",
    )
)
println(session.sessionUrl) // Redirect user here, or upload docs directly

// 2. Upload document (front)
verilock.sessions.uploadDocument(
    UploadDocumentParams(
        sessionId = session.id,
        fileData = frontImageBytes,
        side = DocumentSide.FRONT,
        documentType = DocumentType.PASSPORT,
    )
)

// 3. Upload selfie
verilock.sessions.uploadSelfie(
    UploadSelfieParams(
        sessionId = session.id,
        fileData = selfieBytes,
    )
)

// 4. Submit for verification
val result = verilock.sessions.submit(session.id)
```

## Coroutine Integration

All SDK methods are `suspend` functions. Call them from a coroutine scope such as `viewModelScope` or `lifecycleScope`.

```kotlin theme={null}
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import io.verilock.sdk.*

class VerificationViewModel : ViewModel() {

    private val verilock = Verilock(apiKey = "qi_live_...")

    fun startVerification(email: String) {
        viewModelScope.launch {
            try {
                val session = verilock.sessions.create(
                    CreateSessionParams(
                        applicant_email = email,
                        redirect_url = "https://example.com/callback",
                    )
                )
                // Navigate to session URL or upload docs
            } catch (e: VerilockException) {
                // Handle error
            }
        }
    }
}
```

## KYC Sessions

The `sessions` resource manages the full verification lifecycle.

```kotlin theme={null}
// Create a session
val session = verilock.sessions.create(
    CreateSessionParams(
        applicant_email = "jane@example.com",
        redirect_url = "https://example.com/done",
    )
)

// List sessions with pagination
val list = verilock.sessions.list(
    ListSessionsParams(page = 1, limit = 20)
)

// Retrieve a session by ID
val details = verilock.sessions.retrieve("sess_abc123")
println(details.decision) // "approved", "declined", or "review"

// Upload address proof
verilock.sessions.uploadAddressProof(
    UploadAddressProofParams(
        sessionId = "sess_abc123",
        fileData = proofBytes,
        documentType = AddressDocumentType.UTILITY_BILL,
    )
)
```

## AML Screening

Screen individuals against global sanctions, PEP, and watchlists.

```kotlin theme={null}
val screening = verilock.aml.screen(
    ScreenPersonParams(name = "John Doe")
)
println(screening.risk)    // risk classification
println(screening.matches) // matched watchlist entries
```

## Transaction Monitoring

Screen transactions for suspicious activity.

```kotlin theme={null}
val tx = verilock.transactions.screen(
    ScreenTransactionParams(
        transaction_ref = "TX-001",
        sender_name = "Alice",
        receiver_name = "Bob",
        amount = 5000.0,
        currency = "USD",
    )
)
println(tx.risk)
println(tx.flags)
```

## Premium Features

The SDK provides access to premium verification services through dedicated resource properties.

```kotlin theme={null}
// Biometric face authentication
val biometricResult = verilock.biometric.verify(params)

// Government database validation
val dbResult = verilock.database.validate(params)

// 1:N face duplicate detection
val searchResult = verilock.faceSearch.search(params)

// Crypto wallet compliance screening
val walletResult = verilock.wallet.screen(params)

// Reusable KYC credentials
val credential = verilock.credentials.create(params)

// Age verification from selfie
val ageResult = verilock.ageVerify.check(params)
```

<Info>
  Premium features require an active subscription. See the [Premium Features](/premium-features) docs for details.
</Info>

## Error Handling

All methods are `suspend` functions that throw `VerilockException` subclasses. Use `try/catch` to handle errors.

```kotlin theme={null}
try {
    val session = verilock.sessions.retrieve("sess_invalid")
} catch (e: AuthenticationException) {
    println("Auth failed: ${e.message}")
} catch (e: InsufficientBalanceException) {
    println("Need ${e.required}, have ${e.balance}: ${e.message}")
} catch (e: NotFoundException) {
    println("Not found: ${e.message}")
} catch (e: ValidationException) {
    println("Invalid input: ${e.message}")
    e.errors.forEach { (field, messages) ->
        println("  $field: ${messages.joinToString()}")
    }
} catch (e: RateLimitException) {
    println("Slow down: ${e.message}, retry in ${e.retryAfter}s")
} catch (e: VerilockException) {
    // Catch-all for other Verilock errors
    println("Error ${e.statusCode}: ${e.message} (${e.code})")
}
```

### Exception Hierarchy

| Exception                      | HTTP Status | Description                          |
| ------------------------------ | ----------- | ------------------------------------ |
| `AuthenticationException`      | 401         | Invalid or missing API key           |
| `InsufficientBalanceException` | 402         | Account balance too low              |
| `NotFoundException`            | 404         | Resource does not exist              |
| `ValidationException`          | 422         | Request parameters failed validation |
| `RateLimitException`           | 429         | Too many requests                    |
| `VerilockException`            | \*          | Base class for all SDK errors        |

All exceptions extend `VerilockException`, which provides `code`, `statusCode`, and `body` properties.

<Tip>
  The SDK automatically retries requests on `429` and `5xx` errors up to `maxRetries` times (default: 2) with exponential backoff. You only need to handle errors that persist after retries.
</Tip>
