Skip to main content

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

TierIncludes
BASICDocument 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

ParameterTypeDefaultDescription
apiKeyStringRequiredYour API key (kora_… for sandbox, kora_… for production)
tenantIdStringRequiredYour tenant UUID
environmentEnvironmentSANDBOXSANDBOX or PRODUCTION (auto-detected from API key prefix; explicit setting overrides)
baseUrlString?nullOverride base URL (for on-premise deployments)
themeKoraTheme?DefaultsCustom theme colors and styling
timeoutLong600Network request timeout in seconds (default: 600)
debugLoggingBooleanfalseVerbose 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 &amp; 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:

KeyDefault
koraidv_consent_titleVerify Your Identity
koraidv_consent_descriptionWe need to verify your identity to comply with regulations and keep your account secure.
koraidv_consent_item_id_title / _subtitleGovernment-issued ID / Photo of your passport or front & back of your ID
koraidv_consent_item_selfie_title / _subtitleSelfie photo / A quick selfie to match your ID
koraidv_consent_item_liveness_title / _subtitleLiveness check / Quick video to confirm it's really you
koraidv_consent_item_eyewear_title / _subtitleRemove sunglasses / Your eyes must be clearly visible…
koraidv_consent_buttonGet started
koraidv_consent_privacyBy 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.

Removing a card instead of rewording it

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
}
}
}
ErrorDescriptionRecovery
NetworkErrorNetwork request failedCheck connection, retry
CameraAccessDeniedCamera permission deniedRequest permission again
SessionExpiredVerification session timed outCreate a new verification
UserCancelledUser dismissed the verificationPrompt 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.pro silences R8 warnings on org.opencv.*).
  • At runtime, DocumentDewarper.dewarp() calls OpenCVLoader.initLocal() inside a try/catch. If OpenCV isn't on the classpath, the call returns null and 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()
}
}
}
}