Skip to main content

Flutter SDK

The Kora IDV Flutter SDK is a thin Dart wrapper that delegates to the native iOS and Android SDKs via platform channels. All camera capture, ML inference, and verification UI happens natively for performance and access to platform features (CameraX, AVFoundation, ML Kit, NFC).

Requirements

  • Flutter 3.10+ (Dart 3.0+)
  • iOS 14.0+ deployment target
  • Android minSdk 24+

Installation

Add to your pubspec.yaml:

dependencies:
koraidv_flutter:
git:
url: https://github.com/badedokun/koraidv-flutter.git
ref: v1.5.0

Then run:

flutter pub get

iOS setup

cd ios && pod install

Add to ios/Runner/Info.plist:

<key>NSCameraUsageDescription</key>
<string>We need your camera to verify your identity.</string>

If you're using NFC passport reading:

<key>NFCReaderUsageDescription</key>
<string>We use NFC to verify the chip in your passport.</string>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A0000002471001</string>
</array>

Android setup

Add to android/app/src/main/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" />

Ensure your android/app/build.gradle has minSdkVersion 24 or higher.

Quick start

import 'package:koraidv_flutter/koraidv_flutter.dart';

Future<void> verify() async {
// Configure once on app start
final kora = KoraIDV();
await kora.configure(KoraIDVConfiguration(
apiKey: 'kora_sandbox_xxxxx',
tenantId: 'your-tenant-uuid',
environment: Environment.sandbox,
));

// Launch verification — pass your own external user ID and a tier
final result = await kora.startVerification(
externalId: 'user-${userId}',
tier: VerificationTier.standard,
);

switch (result) {
case VerificationFlowSuccess(:final verification):
print('Status: ${verification.status}');
print('Risk score: ${verification.riskScore}');
case VerificationFlowCancelled():
print('User cancelled');
}
}

Resume an existing verification

final result = await kora.resumeVerification(
verificationId: existingVerificationId,
);

Configuration

class KoraIDVConfiguration {
final String apiKey;
final String tenantId;
final Environment environment; // .sandbox or .production (auto-detected)
final String? baseUrl; // override for on-prem
final LivenessMode livenessMode; // .active or .passive
final KoraTheme? theme;
final Duration timeout; // default 120s
final bool debugLogging;
}
await kora.configure(KoraIDVConfiguration(
apiKey: 'kora_live_xxxxx',
tenantId: 'your-tenant-uuid',
environment: Environment.production,
livenessMode: LivenessMode.active,
theme: KoraTheme(
primaryColor: 0xFF0D9488,
backgroundColor: 0xFFFFFFFF,
cornerRadius: 12,
),
));

Verification tiers

TierIncludes
VerificationTier.basicDocument OCR + basic authenticity
VerificationTier.standard+ Face match + active liveness
VerificationTier.enhanced+ Anti-spoof + risk signals + compliance screening (sanctions / PEP / adverse media)

Error handling

try {
await kora.startVerification(
externalId: externalId,
tier: VerificationTier.standard,
);
} on KoraError catch (err) {
switch (err.code) {
case KoraErrorCode.networkError:
// Retry with user prompt
break;
case KoraErrorCode.cameraAccessDenied:
// Prompt for permission
break;
case KoraErrorCode.sessionExpired:
// Start a fresh verification
break;
case KoraErrorCode.notConfigured:
// configure() was never called
break;
}
}

Result shape

class Verification {
final String id;
final String externalId;
final VerificationStatus status; // autoApproved, manualReview, autoRejected, inProgress
final VerificationScores? scores; // per-feature breakdown
final double? riskScore; // overall 0–100
final DocumentVerification document;
final FaceVerification face;
final LivenessVerification liveness;
final bool imagePersisted;
final List<RiskSignal> riskSignals;
final DateTime createdAt;
final DateTime? completedAt;
}

ProGuard / R8 (Android)

If you ship a release build with R8 enabled, add to android/app/proguard-rules.pro:

-keep class com.koraidv.sdk.** { *; }
-keepclassmembers class com.koraidv.sdk.** { *; }

Common issues

IssueFix
MissingPluginExceptionThe plugin isn't registered. Run flutter clean && flutter pub get && cd ios && pod install.
Camera permission silently fails on iOSConfirm NSCameraUsageDescription is in Info.plist.
Black camera preview on AndroidVerify the runtime permission was granted; the SDK requests it on first launch.
configure() called twice warningsConfigure once during app startup, not in build() methods.

Next steps