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
minSdk24+
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
| Tier | Includes |
|---|---|
VerificationTier.basic | Document 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
| Issue | Fix |
|---|---|
MissingPluginException | The plugin isn't registered. Run flutter clean && flutter pub get && cd ios && pod install. |
| Camera permission silently fails on iOS | Confirm NSCameraUsageDescription is in Info.plist. |
| Black camera preview on Android | Verify the runtime permission was granted; the SDK requests it on first launch. |
configure() called twice warnings | Configure once during app startup, not in build() methods. |
Next steps
- Sandbox testing — deterministic test fixtures
- Webhooks — server-side delivery of verification events
- Server integration — verifying API key + tenant context on your backend
- Image retrieval — accessing persisted images for compliance