Docs contentsYaliyomo ya nyaraka

Quick start: Flutter

Add the digid plugin, start it with your licence, open the ready-made flow and send the document to your backend.

The digid Flutter plugin runs on Android and iOS. It ships the engine and the ready-made screens: intro, card camera (front, then the back if you ask for it), selfie, fingerprints and result.

1. Add the plugin

Add digid to your app's pubspec.yaml. Customers get the package and its install line from the customer portal: see Get the SDK.

The plugin makes no network calls and declares no permissions. Your app asks for the camera:

  • Android: <uses-permission android:name="android.permission.CAMERA" /> in AndroidManifest.xml.
  • iOS: an NSCameraUsageDescription string in Info.plist.

If the user refuses the camera, the flow says so and offers to open the app's settings.

2. Start the engine with your licence

Create the engine once, at start-up. Loading takes a moment and runs off the UI isolate.

import 'package:digid/digid.dart';

const licence = 'digidlic1.…'; // your licence key, or fetch it from your backend

final engine = await DigidFlow.createEngine(licence: licence);

The licence is checked on the device, against your app's package name or bundle id. Without a valid licence the engine runs in evaluation mode. See Licences and renewal.

3. Open the flow

final result = await DigidFlow.start(
  context,
  engine: engine,
  licence: licence,
  config: DigidFlowConfig.fromJson({
    'flow': {'steps': ['card', 'selfie'], 'require_back': 'optional'},
    'screens': {'result': {'download': false}},
  }),
  onStepChanged: (stage) => debugPrint('digid: ${stage.wire}'),
  onError: (error) => debugPrint('digid: $error'),
);

start returns null when the user leaves the flow. To embed the flow in your own page instead of pushing it, use the DigidFlowView widget with the same arguments. Every config key is in the config reference.

For fingerprints, add 'fingerprints' to the steps and pass a fingerprint engine: see Fingerprints for NIDA.

4. Read the result

if (result != null) {
  final overall = result.kyc?.overall;   // pass, review or fail
  final evaluation = result.evaluation;  // true without a valid licence
  final document = result.payload;       // the digid.kyc/1 document, as JSON text
}
  • result.kyc is the engine's result (KycResult), typed.
  • result.payload is the digid.kyc/1 document. It is null only if it could not be built, which is reported through onError.

5. Send the document to your backend

Send result.payload as it is, over your own authenticated connection. Do not parse and re-serialise it first: that can change the text and fail the tamper check on your server.

import 'package:http/http.dart' as http;

await http.post(
  Uri.parse('https://api.example.co.tz/kyc'),
  headers: {'content-type': 'application/json', 'authorization': 'Bearer $sessionToken'},
  body: result.payload,
);

Then check it on the server: Verify on your backend.

6. Report usage

Under a licence the engine counts completed verifications on the phone: counts only, nothing about the person. Your app sends the daily reports when it is online. Pay-as-you-go licences also renew from the phone.

engine.usageSender = (report) async {
  final r = await http.post(Uri.parse('https://digid.co.tz/api/v1/usage'),
      headers: {'content-type': 'application/json'}, body: jsonEncode({'report': report}));
  return r.statusCode == 200;
};
await engine.setUsageStore(myStore); // keeps the counts across restarts
await engine.online();               // call when the app is online, e.g. from a connectivity listener

See Licences and renewal for the store, renewal and the "no report, no renewal" rule.

Next