Quick start: Web
Add @digid/sdk to your site, mount the ready-made flow with your licence and send the document to your backend.
@digid/sdk runs the digid engine in the browser, inside a Web Worker, with no uploads. @digid/sdk/ui adds the ready-made screens: intro, camera or photo upload, turn-over, selfie and result.
1. Add the package and host its files
Install @digid/sdk from the package your account gives you: see Get the SDK. Then serve these files from your own origin:
- the package's
dist/(your bundler resolves the worker next to it; Vite and webpack 5 handle this), - the engine's
.wasmfile, served asapplication/wasm, - the model pack folder, copied as it is.
The page needs HTTPS (the camera needs a secure context). A content security policy needs only 'wasm-unsafe-eval' beyond the usual:
default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; worker-src 'self'; connect-src 'self'; img-src 'self' blob:; style-src 'self'
The SDK fetches only its own files and the models, from your origin. It refuses models from another origin.
2. Mount the flow with your licence
import { mountFlow } from "@digid/sdk/ui";
const flow = mountFlow(document.getElementById("kyc"), {
models: "/models/", // the model pack on your origin
licence: "digidlic1.…", // your licence key; without it, evaluation mode
config: {
flow: { steps: ["card", "selfie"], requireBack: "optional" },
screens: { result: { download: false } },
},
onComplete: ({ result, payload }) => sendToBackend(payload),
onCancel: ({ step, reason }) => console.log("left at", step, reason),
onError: (error) => console.error(error),
});
The licence is checked in the browser against the page's origin (location.origin). Local origins such as localhost need a sandbox licence; see Licences and renewal.
The handle has start(), cancel(), setLanguage("en" | "sw" | "auto") and destroy(). With screens.intro.show set to false, the flow starts as soon as it is mounted. Every config key, in camelCase or snake_case, is in the config reference.
3. Read the result
onComplete receives two things:
result: the engine's result object, withoverall(pass,revieworfail),evaluation, the card fields and the checks.payload: thedigid.kyc/1document, as compact JSON text.
With the result screen on, onComplete fires when the user taps its button; with it off, as soon as the result is ready.
4. Send the document to your backend
Send the text as it is. Parsing and re-serialising it can change it and fail the tamper check on your server.
async function sendToBackend(payload) {
const res = await fetch("/api/kyc", {
method: "POST",
headers: { "content-type": "application/json" },
credentials: "same-origin",
body: payload,
});
if (!res.ok) throw new Error(`KYC upload failed: ${res.status}`);
}
Then check it on the server: Verify on your backend.
5. Report usage
Under a licence the engine counts completed verifications in the page: counts only. Create the engine yourself to report them, and share it with the flow:
import { Digid, loadModels } from "@digid/sdk";
const engine = await Digid.create({ models: await loadModels("/models/") });
await engine.applyLicence("digidlic1.…");
engine.usageSender = (report) =>
fetch("https://digid.co.tz/api/v1/usage", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ report }),
}).then((r) => r.ok);
await engine.setUsageStore({
load: () => localStorage.getItem("digid-usage"),
save: (state) => localStorage.setItem("digid-usage", state),
});
const flow = mountFlow(element, { nida: engine, onComplete: ({ payload }) => sendToBackend(payload) });
await engine.online(); // sends what is pending
The stored state holds counts, an anonymous counter id and the licence key: no personal data. See Licences and renewal.
Limits on the web
- No fingerprint capture in the browser:
"fingerprints"inflow.stepsis skipped with a warning. - The download is large the first time: the engine and card models are needed for the card, and the face models load only when a selfie starts. Use
preload: "card"(the default),"all"or"none"to choose what loads on mount.
Next
- Drop-in screens and config: theme the flow with config or CSS custom properties.
- Going live: the checklist before production.