Flutter SDK
The Flutter SDK opens the full verification flow as a modal sheet via MyazaKYC.show(), with on-device native liveness (Apple Vision on iOS, Google ML Kit on Android). It uses a publishable (pk_) key and detects the environment automatically from the key prefix (pk_test_* → sandbox, pk_live_* → production). For shared concepts — supported countries, branding, results, and errors — see Client SDKs.
Feature availability. This SDK (
2.0.x) covers the core capture flow documented below. The newer web-SDK features — workflow embedding (workflowId), the capture add-ons (contact OTP, proof of address, questionnaire), business (KYB) verification, and countries beyond NG/GH/KE/ZA/CI — are not in this release yet. See Feature availability. Until parity lands, run those flows via a hosted workflow link or the web SDK.
Install
Add the dependency to your pubspec.yaml, then run flutter pub get:
dependencies:
myaza_kyc_sdk_flutter: ^2.0.0Requirements
| Requirement | Minimum |
|---|---|
| Flutter | 3.27 (Dart 3.6) |
| iOS deployment target | 13.0 |
Android minSdkVersion | 21 (Android 5.0) · compileSdk 34 |
Face detection runs on-device (Apple Vision on iOS, Google ML Kit on Android — an Android-only Gradle dependency, so there's no cross-platform ML Kit iOS pod and the SDK still builds on Apple-Silicon iOS simulators). Add the camera permission on both platforms (there is no microphone permission — voice guidance is text-to-speech output only):
<!-- iOS — ios/Runner/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>We use the camera to photograph your ID and capture a live selfie.</string><!-- Android — android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />Usage
MyazaKYC.show() opens the full flow as a modal bottom sheet (a full-screen page on Android). Note that context is a named parameter, and the callbacks are passed to show() alongside config — not inside it.
import 'package:flutter/material.dart';
import 'package:myaza_kyc_sdk_flutter/myaza_kyc_sdk_flutter.dart';
void startKYC(BuildContext context) {
MyazaKYC.show(
context: context,
config: MyazaKYCConfig(
apiKey: 'pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
country: Country.NG,
idTypes: const [IdType.bvn, IdType.driversLicense, IdType.passport],
userData: const UserData(firstName: 'Jane', lastName: 'Doe'),
enableSelfie: true,
enableDocumentCapture: true,
enableLiveness: true,
appearance: const MyazaKYCAppearance(
primaryColor: Color(0xFF5645F5),
companyName: 'Myaza',
logo: 'default',
theme: MyazaThemeMode.light,
),
consent: const KYCConsentContent(
title: 'Welcome, {firstName}',
description: "A quick check to confirm it's really you.",
),
success: const KYCSuccessContent(
title: "You're all set, {firstName}!",
description: "We'll email you once your verification is reviewed.",
),
metadata: const {'requestId': 'order_1001', 'userId': 'user_42'},
),
onSubmit: (submission) {
// The verification was created; submission.status is always 'pending'.
// The final result arrives via webhook to your backend (or fetch it with a
// secret-key GET /verifications/:id call — never from the client).
debugPrint('Submitted: ${submission.verificationId}');
},
onError: (error) {
// Technical errors only (network / 401 / 402 / upload).
debugPrint('Error: ${error.code} — ${error.message}');
},
onClose: () => debugPrint('KYC closed'),
);
}Config (MyazaKYCConfig)
| Field | Type | Default | Description |
|---|---|---|---|
apiKey | String | — | Required. Sent as Authorization: Bearer. The environment is derived from the key prefix (pk_test_* → sandbox, pk_live_* → production); an unrecognized prefix throws. |
country | Country | — | Required. Country whose ID types are offered. |
idTypes | List<IdType>? | all for country | Subset of ID types to offer; null shows all for country. |
userData | UserData? | — | Pre-fills the user's details. |
enableSelfie | bool | true | Capture a selfie during liveness. |
enableDocumentCapture | bool | true | Enable the document-scan step for document IDs. |
allowDocumentUpload | bool | true | Allow picking a document photo from the device gallery instead of the camera. false hides the "upload instead" option — except on the camera-permission-denied screen, where it stays as an escape hatch. |
enableLiveness | bool | true | Run the liveness challenge step. The server can still disable it per ID type. |
voiceGuidance | VoiceGuidanceConfig | enabled (en-US) | Spoken liveness instructions (accessibility, TTS output — no microphone). VoiceGuidanceConfig.off mutes it; VoiceGuidanceConfig(language: 'fr-FR') sets the voice language. |
showThemeToggle | bool | true | Show a light/dark toggle in the header. Set false to hide it — the flow then stays on appearance.theme and the user can't switch it. |
disableClose | bool | false | Hide the close (X) button and block all user dismissal (swipe-down drag, Android back, barrier tap). The flow can then only be closed programmatically by popping the route MyazaKYC.show() returns (its Future completes on close). The terminal "Submitted" step is non-dismissible regardless. |
appearance | MyazaKYCAppearance? | brand defaults | Brand & theme the flow — colors, logo, light/dark. See Branding & theming. |
consent | KYCConsentContent? | built-in copy | Override the consent/welcome screen title and description. See Consent screen copy. |
success | KYCSuccessContent? | built-in copy | Override the success/submitted screen title and description. See Success screen copy. |
metadata | Map<String, dynamic>? | — | Forwarded with the verify request (include your requestId). |
livenessConfig | LivenessConfig? | 2 challenges, 8s each | Tune the liveness challenge sequence (see below). |
UserData accepts firstName, lastName, dateOfBirth, gender, address, and phoneNumber (all optional).
Callbacks
Passed to MyazaKYC.show() alongside config:
| Callback | Type | Description |
|---|---|---|
onSubmit | void Function(KYCSubmission) | Called when the server accepts the verification. status is always 'pending'. |
onError | void Function(KYCError) | Called for technical errors only — receives a typed KYCError (code, message, optional details). Verification outcomes don't come through here. See Errors. |
onClose | void Function() | Called when the user closes the flow. |
Enums
| Enum | Values |
|---|---|
Country | NG, GH, KE, ZA, CI |
IdType | bvn, nin, vnin, passport, driversLicense, pvc, ghanaCard, voters, ssnit, nationalId, cni, residenceCard |
MyazaThemeMode | light, dark |
Liveness configuration
LivenessConfig tunes the active-liveness step. Defaults match the web SDK.
| Field | Type | Default | Description |
|---|---|---|---|
challengeCount | int | 2 | Number of gesture challenges drawn from the pool. |
challengePool | List<ChallengeConfig>? | kDefaultChallengePool | The set of challenges to draw from. |
timeoutPerChallenge | int | 8 | Seconds allowed per challenge before it fails. |
enableAvatar | bool | true | Show the animated avatar that demonstrates each gesture. |
The default pool covers four LivenessChallenge gestures: nod, turn, blink, and smile.