Android SDK
The Kora IDV Android SDK provides a complete verification UI — document capture, selfie, and liveness detection — built with Jetpack Compose.
Requirements
- Android API 24+ (Android 7.0)
- Kotlin 2.0.0+
- Jetpack Compose BOM 2024.02.00+
Installation
Gradle (Kotlin DSL)
Add the JitPack repository and dependency:
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
maven { url = uri("https://jitpack.io") }
}
}
// build.gradle.kts (app module)
dependencies {
implementation("com.github.badedokun:koraidv-koraidv-android:v1.5.0")
}
Gradle Version Catalog
# libs.versions.toml
[versions]
koraidv = "v1.5.0"
[libraries]
koraidv = { module = "com.github.badedokun:koraidv-koraidv-android", version.ref = "koraidv" }
// build.gradle.kts
dependencies {
implementation(libs.koraidv)
}
Quick start
1. Configure the SDK
import com.koraidv.sdk.KoraIDV
import com.koraidv.sdk.Configuration
import com.koraidv.sdk.Environment
// In your Application class or Activity
KoraIDV.configure(
Configuration(
apiKey = "kora_sandbox_xxxxx",
tenantId = "your-tenant-uuid",
environment = Environment.SANDBOX
)
)
2. Register for verification results
import com.koraidv.sdk.VerificationContract
import com.koraidv.sdk.VerificationRequest
import com.koraidv.sdk.VerificationResult
class VerifyActivity : ComponentActivity() {
private val verificationLauncher = registerForActivityResult(
VerificationContract()
) { result: VerificationResult ->
when (result) {
is VerificationResult.Success -> {
val status = result.verification.status
val riskScore = result.verification.riskScore // Int? 0–100
val imagePersisted = result.verification.imagePersisted
// Handle success
}
is VerificationResult.Failure -> {
val error = result.error
// Handle error
}
is VerificationResult.Cancelled -> {
// User cancelled
}
}
}
}
3. Launch verification
The SDK creates the verification on your behalf — pass an externalId (your own user identifier) and a tier:
import com.koraidv.sdk.VerificationRequest
import com.koraidv.sdk.VerificationTier
verificationLauncher.launch(
VerificationRequest(
externalId = "user-${userId}",
tier = VerificationTier.STANDARD
)
)
VerificationTier accepts: BASIC, STANDARD, ENHANCED. (See tier table for what each includes.)
Verification tiers
| Tier | Includes |
|---|---|
BASIC | Document OCR + basic authenticity |
STANDARD | + Face match + active liveness |
ENHANCED | + Anti-spoof + risk signals + compliance screening (sanctions / PEP / adverse media) |
Resume an existing verification
If the user closed the app mid-flow and you have the verificationId from the success or webhook payload, resume rather than start fresh:
private val resumeLauncher = registerForActivityResult(
KoraIDV.ResumeVerificationContract()
) { result ->
// Handle result the same way as a fresh start
}
resumeLauncher.launch(existingVerificationId)
Configuration options
| Parameter | Type | Default | Description |
|---|---|---|---|
apiKey | String | Required | Your API key (kora_sandbox_… for sandbox, kora_live_… for production) |
tenantId | String | Required | Your tenant UUID |
environment | Environment | SANDBOX | SANDBOX or PRODUCTION (auto-detected from API key prefix; explicit setting overrides) |
baseUrl | String? | null | Override base URL (for on-premise deployments) |
theme | KoraTheme? | Defaults | Custom theme colors and styling |
timeout | Long | 120000 | Network request timeout in milliseconds |
debugLogging | Boolean | false | Verbose logs in debug builds |
Theme customization
import com.koraidv.sdk.KoraTheme
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
KoraIDV.configure(
KoraIDVConfig(
apiKey = "test_your_api_key",
tenantId = "your-tenant-uuid",
theme = KoraTheme(
primaryColor = Color(0xFF2563EB),
backgroundColor = Color.White,
textColor = Color(0xFF1F2937),
errorColor = Color(0xFFDC2626),
cornerRadius = 12.dp,
buttonHeight = 48.dp
)
)
)
Error handling
The SDK provides typed errors with recovery suggestions:
is VerificationResult.Failure -> {
when (result.error) {
is KoraException.NetworkError -> {
// Check internet connection
showRetryDialog(result.error.recoverySuggestion)
}
is KoraException.CameraAccessDenied -> {
// Request camera permission
requestCameraPermission()
}
is KoraException.SessionExpired -> {
// Create a new verification on your server
createNewVerification()
}
is KoraException.UserCancelled -> {
// User backed out
}
}
}
| Error | Description | Recovery |
|---|---|---|
NetworkError | Network request failed | Check connection, retry |
CameraAccessDenied | Camera permission denied | Request permission again |
SessionExpired | Verification session timed out | Create a new verification |
UserCancelled | User dismissed the verification | Prompt to try again |
Permissions
Add to your AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
The SDK requests camera permission at runtime if not already granted.
ProGuard rules
The SDK ships a consumer-rules.pro that's applied automatically — you don't need to add anything to your own proguard-rules.pro for the SDK itself. (It already covers the SDK's models, API interfaces, public types, and the optional OpenCV imports.)
OpenCV (optional dependency for document dewarping)
The SDK includes a DocumentDewarper that detects the document quadrilateral in a captured photo and warps it to a frame-filling crop. This is an optional enhancement — OpenCV is NOT bundled in the SDK because it adds ~50 MB per ABI and most consumers don't need it.
Behaviour without OpenCV:
- The SDK builds cleanly (the bundled
consumer-rules.prosilences R8 warnings onorg.opencv.*). - At runtime,
DocumentDewarper.dewarp()callsOpenCVLoader.initLocal()inside a try/catch. If OpenCV isn't on the classpath, the call returnsnulland the SDK falls back to the original capture. No crash.
If you want dewarping enabled, add OpenCV to your app's build.gradle.kts:
dependencies {
implementation("org.opencv:opencv:4.10.0")
}
That's it — the SDK detects OpenCV's presence at runtime and starts dewarping automatically.
Flutter bridge
If your Android host is part of a Flutter app:
// In your FlutterActivity
class MainActivity : FlutterActivity() {
private val CHANNEL = "com.yourapp/koraidv"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"startVerification" -> {
val verificationId = call.argument<String>("verificationId")!!
verificationLauncher.launch(
VerificationRequest(verificationId = verificationId)
)
result.success(null)
}
else -> result.notImplemented()
}
}
}
}