Custom screens on the engine
Build your own camera screens: open a session, push frames, render each step update, and finish with the result.
Every digid SDK exposes the engine under the ready-made screens. Use it when you want your own camera UI, or on native Android and iOS, where the engine is what the SDK provides. The engine API is the same everywhere; only the names follow each language.
The engine and the session
- Create the engine once per app process. It loads the models, which takes a moment: do it off the main thread.
- Apply your licence to it (see Licences and renewal).
- Open a session for each verification attempt, with the flow you want.
- Push camera frames into the session, one at a time, in order. Each push returns a step update.
- Render the update: the step, the guidance line, the overlay.
- When the update carries a result, the attempt is done. Close the session.
| Flutter | Web | Android | iOS | |
|---|---|---|---|---|
| Engine | Digid.create() |
Digid.create({ models }) |
Digid.create(context) |
NidaKyc(modelDirectory:) |
| Licence | applyLicence(token) |
applyLicence(token) |
applyLicence(token) |
applyLicence(_:) |
| Session | newSession(FlowKind.cardOnly()) |
newSession({ kind: "card_only", require_back: false }) |
newSession(Flow.CardOnly()) |
newSession(.cardOnly()) |
| Push a frame | session.pushFrame(info, bytes) |
session.pushFrame(info, buffer) |
NidaFrameAnalyzer or session.pushFrame(...) |
NidaCaptureAdapter or session.pushPixelBuffer(...) |
| Guidance text | guidanceText(g, Lang.sw) |
guidanceText(g, "sw") |
Digid.guidanceText(g, Lang.SW) |
NidaKyc.text(for: g, lang: .sw) |
| Finish | session.finish() |
session.finish() |
session.finish() / finishJson() |
session.finish() / finishJSON() |
Flows
| Flow | JSON kind |
Steps |
|---|---|---|
| Card only | card_only |
scan_front, then scan_back if require_back is true |
| Card then selfie | card_then_selfie |
scan_front, scan_back (if asked), then selfie |
Both take require_back (default false). A session reads either a NIDA card or a Tanzanian driving licence; you do not choose in advance.
Frames
A frame is raw pixels plus a small description (FrameInfo): width, height, row_stride (bytes per row, 0 for tightly packed), format, rotation_deg (the clockwise rotation that makes the image upright: 0, 90, 180 or 270), mirrored (true for a mirrored front-camera preview) and timestamp_ms.
format |
Typical source |
|---|---|
nv21 |
Android CameraX (the analyzer converts for you) |
i420 |
Planar YUV, for example Flutter's camera plugin on Android |
bgra8 |
iOS AVCaptureVideoDataOutput, Flutter's camera plugin on iOS |
rgba8 |
A web canvas, an Android Bitmap |
rgb8, gray8 |
Other sources |
Push one frame at a time and drop frames while one is in flight: CameraX's "keep only latest" strategy and AVFoundation's alwaysDiscardsLateVideoFrames do this for you. On the web, CameraSource and scanLoop handle the camera and the pacing.
The step update
Each push returns a StepUpdate:
| Field | Meaning |
|---|---|
step |
The current step: scan_front, scan_back, selfie or done |
guidance |
What to tell the person right now, as a code (see Guidance codes) |
overlay |
Shapes you may draw: card_quad (the card's four corners) and faces (rectangles), in the frame's own coordinates, before rotation |
progress |
0 to 1, progress of the current step |
step_done |
The step just finished |
result |
The result, once the whole flow is done; otherwise null |
Show the guidance with the SDK's text function rather than your own strings for each code. It covers every code, including the selfie step's prompts, in English and Swahili, and stays right when new codes are added.
Switching cameras
The card steps use the back camera. When step becomes selfie, switch to the front camera and push its frames with mirrored: true. The same session continues.
Timeouts
Each step has step_timeout_s (default 30 seconds). If a step cannot finish in time, the flow carries on with what it has: a back that was not read is skipped and flagged with the back_read check, and the result goes to review rather than pass.
Still photos
To read a card from a single photo (an upload instead of the camera), call readCardImage with the image. It returns the result directly, with the same fields and checks.
Finishing
- When an update carries
result, the flow is complete. You can also callfinish()at any time to end the attempt and get the best result so far. finish()returns the typed result;finishJson()(Android) andfinishJSON()(iOS) return the same result as JSON text, identical on every platform.- On Flutter and Web, build the
digid.kyc/1document from the result for your backend:DigidPayload.build(kyc: result)in Dart,engine.buildPayload(result)on the web. - Close the session when you are done with it.
The evaluation cap
In evaluation mode (no valid licence) a session stops after 50 completed sessions in one app run and returns the guidance licence_required. Restart the app to keep testing, or apply a licence.
Errors
A licence that is valid but does not include a feature the flow needs refuses the session with a "feature not licensed" error naming the feature. Evaluation mode never refuses. See Error codes.