KYC SDK
Lets a customer complete identity verification inside your page. Two ways to use it: we render the screen, or you take only the data layer and build your own interface.
<script src="https://cdn.lunixi.com/lunixi-loader.min.js"></script>// Renders the whole guided flow into a DOM target
const handle = await Lunixi.kyc.mount('#kyc-container', {
externalCustomerId: 'cus_8f2a9c',
});
// To remove it later
// handle.unmount();The heavy UI (React plus the flow screens) is downloaded on first mount; before that it is not in your bundle.
How the session is established
On start-up the SDK calls POST /api/v1/kyc/sdk/init and receives a signed session. Every later call uses it.
No secret key is present in the browser. Authentication uses a publishable key plus an Origin match; the browser sets Origin, and code on the page cannot forge it. → Overview
Flow steps
| Step | Method |
|---|---|
| Select jurisdiction | setJurisdiction(code) |
| Select primary document type | setPrimaryDocumentType(type) |
| Submit profile fields | submitProfileData({ fields }) |
| Record consent | submitConsent({ consentType, noticeLocale }) |
| Upload a document | uploadDocument({ file, documentType, side, metadata }) |
| Upload liveness video | uploadLivenessVideo({ chunkSource, nonceId, challengeSequence }) |
| Submit for verification | submitVerification() |
| Watch the outcome | watchStatus({ onStatusChange }) |
| Request human review | requestManualReview({ reasonCode, reasonDetail }) |
For two-sided documents, front and back are uploaded separately via side.
Environment preflight
Before a session starts you can measure whether the device and surroundings are suitable: light, noise, connection and the granted camera resolution.
const preflight = await Lunixi.kyc.runEnvironmentPreflight({ facingMode: 'user' });This is a measurement, not a gate. The preflight never blocks the flow and releases the camera stream it opens — the server owns the decision. Use the result to show the user a hint like "increase the lighting"; do not rule someone out on your own.
Attach the result to the session with recordEnvironmentPreflight(result), read it back with getEnvironmentPreflight().
Watching status
await client.watchStatus({
intervalMs: 3000,
onStatusChange: (status) => render(status),
});timeoutMs and signal bound how long it runs; terminalStatuses decides which statuses stop it.
Live video verification
When a flow escalates to video verification with a human operator:
| Task | Method |
|---|---|
| Get access details | getLiveVerificationAccess({ forceRefresh }) |
| Join the room | joinLiveVerification({ deviceFingerprintRef }) |
| Leave the room | leaveLiveVerification({ deviceFingerprintRef }) |
| Open the session | openLiveVerificationSession(options) |
Configuration
| Field | What it is for |
|---|---|
externalCustomerId | Your own customer reference |
linkedObjectType / linkedObjectId | Ties the verification to your own record |
evidenceContext / evidencePurpose | Why the evidence was collected — written into the audit trail |
identitySessionBootstrapUrl | If you want to mint the identity session from your own endpoint |
apiBaseUrl | To talk to a base other than the default |
allowedOrigin | The origin binding of the session token |
Things to know
The SDK is not fail-open. init(), upload and submit calls throw on failure — they never silently return "verified". Wrap them in try/catch and decide for yourself what your flow does when verification cannot complete.
The liveness-video endpoints are session-scoped — the real sessionId is baked into the path by the server. If the signed session does not carry those endpoints, uploadLivenessVideo fails closed rather than guessing a URL.
Related
- Web SDK Overview — loader, modes, authentication models
- Identity Web SDK — device and behavioural telemetry