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:1.10.15")
}
Gradle Version Catalog
# libs.versions.toml
[versions]
koraidv = "1.10.15"
[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_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_… for sandbox, kora_… 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 | 600 | Network request timeout in seconds (default: 600) |
debugLogging | Boolean | false | Verbose logs in debug builds |
Theme customization
import com.koraidv.sdk.KoraTheme
import androidx.compose.ui.unit.dp
KoraIDV.configure(
Configuration(
apiKey = "kora_your_api_key",
tenantId = "your-tenant-uuid",
theme = KoraTheme(
primaryColor = 0xFF2563EB,
backgroundColor = 0xFFFFFFFF,
textColor = 0xFF1F2937,
errorColor = 0xFFDC2626,
cornerRadius = 12.dp,
buttonHeight = 48.dp
)
)
)
Customizing text & copy
All user-facing text in the SDK — including the intro/consent screen ("Verify Your Identity") — is exposed as Android string resources. To rebrand any of it, declare a string with the same resource name in your own app's res/values/strings.xml. Your app's resources override the SDK's automatically (standard Android resource merging) — no SDK change or fork required.
For example, to reword the consent screen your users see first:
<!-- app/src/main/res/values/strings.xml -->
<resources>
<string name="koraidv_consent_title">Verify your identity with Acme Bank</string>
<string name="koraidv_consent_description">To keep your account secure and meet regulatory requirements, we need to confirm it\'s really you.</string>
<string name="koraidv_consent_item_id_title">Government-issued ID</string>
<string name="koraidv_consent_item_id_subtitle">Your passport, or the front & back of your ID card</string>
<string name="koraidv_consent_item_selfie_subtitle">A quick selfie to match your ID</string>
<string name="koraidv_consent_item_liveness_subtitle">A short video to confirm you\'re present</string>
<string name="koraidv_consent_button">Continue</string>
</resources>
Every SDK string uses the koraidv_ prefix, so overrides never collide with your own strings. Common consent-screen keys:
| Key | Default |
|---|---|
koraidv_consent_title | Verify Your Identity |
koraidv_consent_description | We need to verify your identity to comply with regulations and keep your account secure. |
koraidv_consent_item_id_title / _subtitle | Government-issued ID / Photo of your passport or front & back of your ID |
koraidv_consent_item_selfie_title / _subtitle | Selfie photo / A quick selfie to match your ID |
koraidv_consent_item_liveness_title / _subtitle | Liveness check / Quick video to confirm it's really you |
koraidv_consent_item_eyewear_title / _subtitle | Remove sunglasses / Your eyes must be clearly visible… |
koraidv_consent_button | Get started |
koraidv_consent_privacy | By continuing, you agree to our Privacy Policy… |
Result-screen text (koraidv_result_success_title, koraidv_result_failed_subtitle, etc.) is overridable the same way.
Localization. Provide translations by adding the same keys under a locale-qualified folder, e.g. res/values-fr/strings.xml; the SDK ships English and French and picks up your locale variants automatically. The verification language follows Configuration.locale.
To drop the Remove sunglasses card entirely (rather than editing its text), set showEyewearGuidance = false in your Configuration — that's a config flag, not a string override.
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")!!
resumeLauncher.launch(verificationId)
result.success(null)
}
else -> result.notImplemented()
}
}
}
}