Flutter SDK
Build with

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
Build with

Add the dependency to your pubspec.yaml, then run flutter pub get:

yaml
dependencies:
  myaza_kyc_sdk_flutter: ^2.0.0

Requirements
Build with

RequirementMinimum
Flutter3.27 (Dart 3.6)
iOS deployment target13.0
Android minSdkVersion21 (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):

xml
<!-- iOS  ios/Runner/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>We use the camera to photograph your ID and capture a live selfie.</string>
xml
<!-- Android  android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />

Usage
Build with

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.

dart
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)
Build with

FieldTypeDefaultDescription
apiKeyStringRequired. Sent as Authorization: Bearer. The environment is derived from the key prefix (pk_test_* → sandbox, pk_live_* → production); an unrecognized prefix throws.
countryCountryRequired. Country whose ID types are offered.
idTypesList<IdType>?all for countrySubset of ID types to offer; null shows all for country.
userDataUserData?Pre-fills the user's details.
enableSelfiebooltrueCapture a selfie during liveness.
enableDocumentCapturebooltrueEnable the document-scan step for document IDs.
allowDocumentUploadbooltrueAllow 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.
enableLivenessbooltrueRun the liveness challenge step. The server can still disable it per ID type.
voiceGuidanceVoiceGuidanceConfigenabled (en-US)Spoken liveness instructions (accessibility, TTS output — no microphone). VoiceGuidanceConfig.off mutes it; VoiceGuidanceConfig(language: 'fr-FR') sets the voice language.
showThemeTogglebooltrueShow 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.
disableCloseboolfalseHide 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.
appearanceMyazaKYCAppearance?brand defaultsBrand & theme the flow — colors, logo, light/dark. See Branding & theming.
consentKYCConsentContent?built-in copyOverride the consent/welcome screen title and description. See Consent screen copy.
successKYCSuccessContent?built-in copyOverride the success/submitted screen title and description. See Success screen copy.
metadataMap<String, dynamic>?Forwarded with the verify request (include your requestId).
livenessConfigLivenessConfig?2 challenges, 8s eachTune the liveness challenge sequence (see below).

UserData accepts firstName, lastName, dateOfBirth, gender, address, and phoneNumber (all optional).

Callbacks
Build with

Passed to MyazaKYC.show() alongside config:

CallbackTypeDescription
onSubmitvoid Function(KYCSubmission)Called when the server accepts the verification. status is always 'pending'.
onErrorvoid Function(KYCError)Called for technical errors only — receives a typed KYCError (code, message, optional details). Verification outcomes don't come through here. See Errors.
onClosevoid Function()Called when the user closes the flow.

Enums
Build with

EnumValues
CountryNG, GH, KE, ZA, CI
IdTypebvn, nin, vnin, passport, driversLicense, pvc, ghanaCard, voters, ssnit, nationalId, cni, residenceCard
MyazaThemeModelight, dark

Liveness configuration
Build with

LivenessConfig tunes the active-liveness step. Defaults match the web SDK.

FieldTypeDefaultDescription
challengeCountint2Number of gesture challenges drawn from the pool.
challengePoolList<ChallengeConfig>?kDefaultChallengePoolThe set of challenges to draw from.
timeoutPerChallengeint8Seconds allowed per challenge before it fails.
enableAvatarbooltrueShow the animated avatar that demonstrates each gesture.

The default pool covers four LivenessChallenge gestures: nod, turn, blink, and smile.