Skip to content

Web SDK Integration ​

Setup, initialization and scanning for the eKYC Web SDK. Executing bundle.js creates the global object window.ekyc.

Prerequisites ​

WhatDescription
Assets folderSomewhere to serve the /ekyc assets folder from.
HTTPSRequired for camera access.
WebView permissionsOn iOS WebViews, enable inline media playback — allowsInlineMediaPlayback in both Flutter and React Native.
jsQRRequired for QR code functionality. Load it before the SDK bundle.

HTML Setup ​

The container element with id cake-ekyc-sdk-container is required and must exist before initialization.

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>eKYC Integration</title>
    <style>
      #cake-ekyc-sdk-container {
        width: 100%;
        height: 100vh;
        position: relative;
      }
    </style>
  </head>
  <body>
    <!-- Required: SDK container element with specific ID -->
    <div class="overlay" id="cake-ekyc-sdk-container"></div>

    <!-- Required: eKYC SDK bundle -->
    <script src="/ekyc/bundle.js"></script>

    <script>
      // SDK initialization code goes here
    </script>
  </body>
</html>

Initialize ​

typescript
type SDKConfigParams = {
  resourcePath?: string             // Optional path to SDK resources
  baseUrl: string                   // Required: Base URL for API requests
  token: string                     // Required: Authentication token
  headers?: Record<string, string>  // Optional: Additional HTTP headers
}

Parameters:

ParamTypeRequiredDefaultDescription
baseUrlstringYes—Base URL for API requests.
tokenstringYes—Authentication token.
resourcePathstringNo—Path to SDK resources.
headersRecord<string, string>No—Additional HTTP headers.
javascript
const sdk = await window.ekyc.initialize('cake-ekyc-sdk-container', {
  baseUrl: '<BASE_URL>',
  token: '<SDK_TOKEN>',
  resourcePath: '/path/to/resources',
  headers: {
    'Custom-Header': 'value'
  }
})

With error handling ​

javascript
async function initializeSDK() {
  try {
    const container = document.getElementById('cake-ekyc-sdk-container');
    if (!container) {
      throw new Error('SDK container element not found');
    }

    if (!window.ekyc) {
      throw new Error('eKYC SDK not loaded. Ensure bundle.js is included.');
    }

    const sdk = await window.ekyc.initialize('cake-ekyc-sdk-container', {
      baseUrl: '<BASE_URL>',
      token: await fetch('/your-backend/ekyc-token').then((r) => r.text()), // fetched at runtime, never bundled
      resourcePath: '/ekyc/resources',
      headers: {
        'X-Client-Version': '1.0.0',
        'X-Platform': 'web',
        'X-User-Agent': navigator.userAgent
      }
    });

    return sdk;
  } catch (error) {
    console.error('SDK initialization failed:', error);
    throw error;
  }
}

WARNING

Fetch token from your backend at runtime — never hardcode it in the page or commit it to source. The token authorizes calls against your tenant.

Scan ​

typescript
scanStart(
  types: ('face' | 'front' | 'back' | 'qrcode')[],
  opts?: ScanOptions
): Promise<{
  nid?: { front?: NIDScanResult, back?: NIDScanResult }
  face?: FaceScanResult
  qrcode?: QRCodeScanResult
}>

Parameters:

ParamTypeRequiredDefaultDescription
typesstring[]Yes—Which scans to run: face, front, back, qrcode. Order is respected.
optsScanOptionsNo—Options, mainly for face authentication.

ScanOptions ​

ParamTypeRequiredDefaultDescription
frontImageIdstringNo—Image ID from the front scan, used when scanning the back.
faceauthClientIdstringNo—Client ID for face authentication.
faceauthRefIdstringNo—Reference ID for face authentication.
isNTBbooleanNo—New-to-Bank customer flag.
currentZoomnumberNo—Current zoom level.
timeoutDurationnumberNo—Timeout duration in milliseconds.
javascript
// Scan front and back of NID card
const result1 = await window.ekyc.scanStart(['front', 'back'])

// Scan face for NTB customer
const result2 = await window.ekyc.scanStart(['face'], {
  isNTB: true,
  faceauthClientId: 'client-123',
  faceauthRefId: 'ref-456'
})

// Scan QR code
const result3 = await window.ekyc.scanStart(['qrcode'])

// Combined scan
const result4 = await window.ekyc.scanStart(['front', 'back', 'face', 'qrcode'], {
  isNTB: false,
  faceauthClientId: 'client-123',
  faceauthRefId: 'ref-456'
})

Only the requested scan types appear in the response; everything else is undefined.

Scan Status ​

typescript
interface Status {
  frontCompleted: boolean
  backCompleted: boolean
  faceCompleted: boolean
  qrcodeCompleted: boolean
  timestamp?: string

  frontData?: any
  backData?: any
  faceData?: any
  qrcodeData?: any
}
javascript
const status = window.ekyc.getScanStatus()
console.log('Front scan completed:', status.frontCompleted)

Response Shapes ​

NIDScanResult ​

FieldTypeDescription
frontSideImageobjectFront image: id, label, bitmap, response.
backSideImageobjectBack image, same shape.
sanityResultobjectCard sanity verdict, score and detected card box.
cardInfoobjectOCR, MRZ and QR extraction with confidence scores.

sanityResult.data.card_sanity carries verdict, score and info. cardInfo.data.card_information is an array of CardInformation.

CardInformation ​

FieldTypeDescription
fieldstringField name.
valuestringExtracted value.
confidence_scorenumberOverall confidence.
confidence_verdictstringText verdict.
digit_confidence_scoresnumber[]Per-character confidence.

FaceScanResult ​

FieldTypeDescription
facesFaceData[]Captured faces, each with image and gesture (left, right, portrait).
sanityResultSanityResult[]Portrait sanity verdict and score per image.
livenessResultLivenessResultis_live, score, per-image results and main_image_id.

QRCodeScanResult ​

FieldTypeDescription
rawstringRaw QR code data.
imageobjectProcessed image: id, label, bitmap, response.

Converting bitmaps ​

bitmap is an ImageData object with two helpers attached:

javascript
const blob   = await bitmap.toBlob('image/jpeg')
const base64 = bitmap.toBase64('image/jpeg')

Error Handling ​

Scan responses keep the same shape on failure and put detail in the error array. Responses may also carry sdkError:

typescript
sdkError?: { code: string; message: string } | {}
// {}             -> no SDK-side error
// {code,message} -> the SDK detected a failure you should handle

sdkError appears on ImageResponse, the face SanityResult and LivenessResult, the NID sanityResult and cardInfo, and the QR image.response.

WARNING

A successful-looking response can still contain warnings in its error array, and a populated sdkError means the SDK itself rejected the result. Check both — don't treat a resolved promise as a pass.

SDK error codes ​

FieldTypeDescription
60000NID_SANITY_FAILEDNID sanity check failed.
60001NID_TAMPERING_FAILEDNID tampering detection failed.
60002FACE_SANITY_FAILEDFace sanity check failed.
60003FACE_LIVENESS_FAILEDFace liveness check failed.

QR code error codes ​

FieldTypeDescription
DOP-675_001Scan timeout"Hết thời gian quét mã. Vui lòng thử lại."
DOP-675_002Scan error"Không thể quét được mã QR, vui lòng thử lại!"

Dynamic error codes also arrive from the API in the error array — see Error Codes.

Common issues ​

WhatDescription
SDK not loadingCheck the script path and that it loads before use.
Camera accessEnsure HTTPS and that camera permissions are granted.
Container not foundVerify the container element exists in the DOM.
Network issuesCheck the internet connection and API endpoints.
typescript
if (typeof window.ekyc === 'undefined') {
    console.error('eKYC SDK not loaded');
}

navigator.mediaDevices.getUserMedia({ video: true })
    .then(stream => {
        console.log('Camera access granted');
        stream.getTracks().forEach(track => track.stop());
    })
    .catch(error => {
        console.error('Camera access denied:', error);
    });

Best Practices ​

  • Initialize once and reuse the instance.
  • Use getScanStatus() to monitor progress.
  • For NID cards, scan the front first, then the back using frontImageId.
  • Wrap every scan in try/catch.
  • Call terminate() when done to release the camera and clean up.

Next Steps ​

Developers