> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.vlenseg.com/llms.txt.
> For full documentation content, see https://docs.vlenseg.com/llms-full.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.vlenseg.com/_mcp/server.

# Flutter SDK

The Vlens Flutter SDK (`vlens`) embeds the full identity verification experience — national ID scanning, liveness detection, and face matching — directly into your mobile app with a single method call.

vlens · v0.1.9

API 21+, Dart SDK ≥ 3.6

iOS 13+, Dart SDK ≥ 3.6

***

## Installation

Add the SDK to your `pubspec.yaml`:

```yaml
dependencies:
  vlens: ^0.1.9
```

Then fetch dependencies:

```bash
flutter pub get
```

***

## Android setup

For **Android 13+**, add the following attribute to the `<application>` tag in `android/app/src/main/AndroidManifest.xml`:

```xml
<application
  android:enableOnBackInvokedCallback="false"
  ...>
```

Omitting this attribute on Android 13+ causes back navigation to behave incorrectly inside the SDK screens.

***

## Quick start

Import the package and call `VLensManager().init()` with a configured `SdkConfig`:

```dart
import 'package:vlens/vlens.dart';

VLensManager().init(context, sdkConfig);
```

That one call launches the full verification UI. The SDK handles camera permissions, ID scanning, liveness detection, and result delivery through your callbacks.

***

## Configuration

### `EnvironmentConfig`

Connects the SDK to your Vlens tenant:

```dart
EnvironmentConfig(
  apiBaseUrl: "https://api.vlenseg.com",
  accessToken: "USER_ACCESS_TOKEN",   // from registration/login
  refreshToken: "USER_REFRESH_TOKEN",
  apiKey: "YOUR_API_KEY",
  tenancyName: "YOUR_TENANT",
)
```

| Parameter      | Description                            |
| -------------- | -------------------------------------- |
| `apiBaseUrl`   | Vlens API base URL                     |
| `accessToken`  | User JWT from registration or login    |
| `refreshToken` | Token used to refresh the access token |
| `apiKey`       | Your tenant API key                    |
| `tenancyName`  | Your tenant name                       |

### `ColorsConfig`

Customise the SDK UI to match your brand — supports separate light and dark themes:

```dart
colors: ColorsConfig(
  light: ColorConfig(
    accent: "#4E5A78",
    primary: "#397374",
    secondary: "#FF4081",
    background: "#FEFEFE",
    dark: "#000000",
    light: "#FFFFFF",
  ),
  dark: ColorConfig(
    accent: "#FFC107",
    primary: "#2196F3",
    secondary: "#FF4081",
    background: "#000000",
    dark: "#FFFFFF",
    light: "#000000",
  ),
),
```

### `SdkConfig` — all parameters

| Parameter               | Type                       | Default | Description                                        |
| ----------------------- | -------------------------- | ------- | -------------------------------------------------- |
| `transactionId`         | `String`                   | —       | Transaction ID to use or resume                    |
| `env`                   | `EnvironmentConfig`        | —       | API credentials and endpoint                       |
| `isLivenessOnly`        | `bool`                     | `false` | Skip ID scanning — liveness only                   |
| `isNationalIdOnly`      | `bool`                     | `false` | Skip liveness — ID scan only                       |
| `getExtractedData`      | `bool`                     | `false` | Return OCR-extracted fields in `onSuccess`         |
| `defaultLocale`         | `String`                   | `"en"`  | UI language — `"en"` or `"ar"`                     |
| `logoPath`              | `String`                   | —       | Asset path to your logo image                      |
| `colors`                | `ColorsConfig`             | —       | Light and dark theme colours                       |
| `detectionRetryCounter` | `int`                      | `5`     | Number of liveness retries before failure          |
| `disableAutoCapture`    | `bool`                     | `false` | Require manual capture instead of auto-capture     |
| `enableSounds`          | `bool`                     | `false` | Play audio feedback during scanning                |
| `errorMessages`         | `List<ApiError>`           | `[]`    | Override default error messages                    |
| `onSuccess`             | `Function(ExtractData?)`   | —       | Called when verification succeeds                  |
| `onFailure`             | `Function(String, String)` | —       | Called with `(errorCode, errorMessage)` on failure |

***

## Verification modes

Runs the complete flow: ID front → ID back → liveness.

```dart
final sdkConfig = SdkConfig(
  transactionId: transactionId,
  isLivenessOnly: false,
  isNationalIdOnly: false,
  getExtractedData: true,
  env: EnvironmentConfig(
    apiBaseUrl: "https://api.vlenseg.com",
    accessToken: userAccessToken,
    refreshToken: userRefreshToken,
    apiKey: apiKey,
    tenancyName: tenantName,
  ),
  defaultLocale: "ar",
  logoPath: "assets/images/logo.png",
  enableSounds: true,
  colors: ColorsConfig(
    light: ColorConfig(
      primary: "#397374",
      accent: "#4E5A78",
      background: "#FEFEFE",
      dark: "#000000",
      light: "#FFFFFF",
      secondary: "#FF4081",
    ),
    dark: ColorConfig(
      primary: "#2196F3",
      accent: "#FFC107",
      background: "#000000",
      dark: "#FFFFFF",
      light: "#000000",
      secondary: "#FF4081",
    ),
  ),
  onSuccess: (extractedData) {
    print("Verified: ${extractedData?.idFrontData?.name}");
  },
  onFailure: (errorCode, errorMsg) {
    print("Failed [$errorCode]: $errorMsg");
  },
);

VLensManager().init(context, sdkConfig);
```

Skip ID scanning — only run the liveness check.

```dart
final sdkConfig = SdkConfig(
  transactionId: transactionId,
  isLivenessOnly: true,
  getExtractedData: true,
  env: EnvironmentConfig(
    apiBaseUrl: "https://api.vlenseg.com",
    accessToken: userAccessToken,
    refreshToken: userRefreshToken,
    apiKey: apiKey,
    tenancyName: tenantName,
  ),
  defaultLocale: "ar",
  detectionRetryCounter: 5,
  onSuccess: (extractedData) {
    print("Liveness passed");
  },
  onFailure: (errorCode, errorMsg) {
    print("Liveness failed [$errorCode]: $errorMsg");
  },
);

VLensManager().init(context, sdkConfig);
```

Skip liveness — only scan the national ID front and back.

```dart
final sdkConfig = SdkConfig(
  transactionId: transactionId,
  isNationalIdOnly: true,
  getExtractedData: true,
  env: EnvironmentConfig(
    apiBaseUrl: "https://api.vlenseg.com",
    accessToken: userAccessToken,
    refreshToken: userRefreshToken,
    apiKey: apiKey,
    tenancyName: tenantName,
  ),
  defaultLocale: "en",
  onSuccess: (extractedData) {
    final front = extractedData?.idFrontData;
    print("Name: ${front?.name}  ID: ${front?.idNumber}");
  },
  onFailure: (errorCode, errorMsg) {
    print("Failed [$errorCode]: $errorMsg");
  },
);

VLensManager().init(context, sdkConfig);
```

***

## Handling results

### `onSuccess` — `ExtractData`

When verification succeeds, `onSuccess` is called with an `ExtractData` object (if `getExtractedData: true`):

```dart
onSuccess: (ExtractData? extractedData) {
  // User profile
  final user = extractedData?.user;
  print(user?.fullName);
  print(user?.phoneNumber);
  print(user?.emailAddress);
  print(user?.idNumber);

  // ID front data
  final front = extractedData?.idFrontData;
  print(front?.name);           // Arabic full name
  print(front?.name_english);   // Transliterated name
  print(front?.idNumber);
  print(front?.dateOfBirth);
  print(front?.gender);
  print(front?.govern);         // Governorate

  // ID back data
  final back = extractedData?.idBackData;
  print(back?.maritalStatus);
  print(back?.job);
  print(back?.religion);
  print(back?.idExpiry);

  // Verification status
  print(extractedData?.isDigitalIdentityVerified);
  print(extractedData?.isVerificationProcessCompleted);
},
```

### `onFailure`

Called with `(errorCode, errorMessage)` when verification fails or the user cancels:

```dart
onFailure: (String errorCode, String errorMsg) {
  // Show error to user or log for debugging
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(content: Text(errorMsg)),
  );
},
```

### Custom error messages

Override specific error messages to match your app's tone or language:

```dart
errorMessages: [
  ApiError(
    errorCode: 101,
    errorMessageEn: "Network error. Please check your connection.",
    errorMessageAr: "خطأ في الشبكة. يرجى التحقق من الاتصال.",
  ),
],
```

***

## Relation to the REST API

The SDK wraps the same REST endpoints documented in the [Digital Identity guide](/digital-identity):

| SDK action    | REST endpoint                                                  |
| ------------- | -------------------------------------------------------------- |
| Full flow     | `verify/id/front` → `verify/id/back` → `verify/liveness/multi` |
| Liveness only | `verify/liveness/multi`                                        |
| ID scan only  | `verify/id/front` → `verify/id/back`                           |

The `transactionId` in `SdkConfig` maps to `transaction_id` in the REST API — pass the same value to link SDK results with server-side records.

***

## Latest version

**v0.1.9** — UI improvements: primary color applied to ID frames and scanning GIFs, sticky buttons on ID review screen, improved status indicator messages during camera capture, enhanced localisation.

See all versions on [pub.dev/packages/vlens/versions](https://pub.dev/packages/vlens/versions).