Flutter SDK
verify_ai_flutter provides a Dart VerifyAIClient, a high-level
VerifyAI wrapper, and a ScannerOptions builder for the embedded
camera UI.
Install
flutter pub add verify_ai_flutterPlatform setup
Add camera permission to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera is used for photo verification</string>Add camera permission to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />Android minSdkVersion 21 or higher is required (Flutter camera
plugin baseline).
Quick start
Use the high-level wrapper when you want a one-shot scanner flow:
import 'package:flutter/material.dart';
import 'package:verify_ai_flutter/verify_ai_flutter.dart';
final verifyAI = VerifyAI(apiKey: 'vai_your_api_key');
Future<void> handleVerify(BuildContext context) async {
final result = await verifyAI.presentScanner(
context,
policy: 'scooter_parking',
options: const ScannerOptions(
guidanceText: 'Center the scooter in the frame',
processingMessage: 'Checking parking compliance...',
failureMessage: 'Parking issue detected',
retryMessage: 'Try again. {remaining} attempts left.',
terminalResultDisplayDuration: Duration(seconds: 3),
terminalActionLabel: 'Continue',
),
);
if (result == null) return; // user dismissed
if (result.isCompliant) {
print('Verified: \${result.verificationId}');
} else {
print('Issues: \${result.violationReasons}');
}
}presentScanner() returns null only if the user dismisses the screen
before a terminal result is produced. It uses multipart uploads for
live camera captures and does not persist raw image bytes to the
offline queue. If full offline replay matters, capture the image
yourself and call verify() with a base64-encoded payload instead.
Direct API access
Use VerifyAIClient when you want full control over capture and
request flow:
import 'package:verify_ai_flutter/verify_ai_flutter.dart';
final client = VerifyAIClient(
const VerifyAIConfig(apiKey: 'vai_your_api_key'),
);
final result = await client.verify(
const VerificationRequest(
image: base64ImageData,
policy: 'scooter_parking',
metadata: {'device_id': 'dev_123'},
),
);For raw camera bytes, use verifyMultipart():
final result = await client.verifyMultipart(
imageBytes: bytes,
policy: 'scooter_parking',
metadata: const {'device_id': 'dev_123'},
);Policy-aware scanner copy
For scooter, bike, and forest parking policies, presentScanner()
applies policy-aware default copy and guide overlays. Override any
copy with ScannerOptions:
| Option | Description |
| ------------------------------- | -------------------------------------------- |
| guidanceText | Top-of-screen instruction. |
| processingMessage | Shown while the API call is in flight. |
| successMessage | Shown on a compliant result. |
| failureMessage | Shown on a non-compliant result. |
| retryMessage | Shown between retries; supports {remaining}.|
| exhaustedMessage | Shown after maxAttempts retries. |
| terminalActionLabel | Button label on the result screen. |
| terminalResultDisplayDuration | How long to hold the result before dismissing.|
On-device inference
The SDK ships hooks for tflite_flutter, but on-device inference is
currently disabled on iOS pending a fix for the upstream crash (see
pubspec.yaml). When you need it, set
VerifyAIConfig(onDeviceEnabled: true) and we'll route eligible
verifications through the on-device pipeline.
Versioning
The current published version is 2.4.x (kept in sync with the React
Native SDK). The Flutter SDK follows semver and is shipped from the
same release process. Check your installed version against
pubspec.lock.