npm.io
0.3.2 • Published 3d ago

@drukverify/ekyc-sdk-js

Licence
MIT
Version
0.3.2
Deps
0
Size
219 kB
Vulns
0
Weekly
0

@drukverify/ekyc-sdk-js

Universal JavaScript SDK for eKYC — face verification, document OCR, liveness detection, and fraud analysis. Works in both browser and Node.js.

Zero runtime dependencies — uses native fetch and FormData.

Installation

npm install @drukverify/ekyc-sdk-js

Quick Start

Node.js (server-side, secret key)
import { EkycClient } from '@drukverify/ekyc-sdk-js';
import { readFileSync } from 'node:fs';

const client = new EkycClient({
  baseUrl: 'https://api.drukverify.com',
  apiKey: process.env.DV_SECRET_KEY, // dv_sk_live_… — server-side only
});

const image = readFileSync('./cid-front.jpg');
const ocr = await client.ocr.scanDocument(image, { type: 'cid' });
console.log(ocr.fields.full_name, ocr.fields.date_of_birth);
Browser (session token)

Never embed a secret key in browser code. Your backend mints a short-lived session token via POST /v1/sessions (with the secret key) and hands it to the page:

import { EkycClient } from '@drukverify/ekyc-sdk-js';

const { token } = await fetch('/your-backend/session').then(r => r.json());
const client = new EkycClient({
  baseUrl: 'https://api.drukverify.com',
  apiKey: token, // dv_tok_…
});

const file = document.querySelector('input[type=file]').files[0];
const fraud = await client.fraud.detect(file, { documentType: 'cid' });
console.log(fraud.is_fraudulent, fraud.overall_score);

Configuration

const client = new EkycClient({
  baseUrl: 'https://api.drukverify.com', // required, no trailing slash
  apiKey: token,                          // dv_tok_… (browser) or dv_sk_… (server)
  version: '2026-05-12',                  // Drukverify-Version header (default shown)
  timeout: 30000,                         // ms
  headers: {},                            // extra headers
});

API Reference

Document OCR
const r = await client.ocr.scanDocument(image, {
  backImage,            // optional back side
  type: 'cid',          // optional hint: 'cid' | 'passport' (others auto-detect)
  customerRef: 'u-123', // optional
});
// r.document_type, r.fields (per-type shape), r.ocr_id

await client.ocr.get(id);      // GET /v1/ocr/:id
await client.ocr.list();       // GET /v1/ocr
await client.ocr.delete(id);   // DELETE /v1/ocr/:id
Fraud Detection
const r = await client.fraud.detect(image, { documentType: 'cid' });
// r.is_fraudulent, r.overall_score, r.signals.{fake_document,photo_substitution,tampering,copy_or_screen}

await client.fraud.get(fcId);  // GET /v1/fraud/checks/:id
Liveness
// Passive (1 frame)
const r = await client.liveness.check(selfie);

// Burst (3–5 frames)
const r2 = await client.liveness.check([f1, f2, f3], { mode: 'burst' });

// Challenge (server-chosen action)
const ch = await client.liveness.createChallenge();  // { action, challenge_token, expires_at }
// …show ch.action to the user, capture ≥2 frames while they perform it…
const r3 = await client.liveness.check(frames, {
  mode: 'challenge',
  challengeToken: ch.challenge_token, // one-shot, ~120s
});
// r3.is_live, r3.score, r3.reason

await client.liveness.get(lcId);
Face Verification
// 1:1 — document portrait vs selfie
const r = await client.verify(documentImage, selfieImage);
// r.match, r.similarity

// 1:N gallery
await client.verification.registerFace(image, 'customer-ref');
await client.verification.searchFace(image, { limit: 5, minSimilarity: 0.4 });
await client.verification.detectDuplicate(image);
await client.verification.listRegistrations();
await client.verification.deleteRegistration(id);

Branding & Theming

The SDK imposes no UI. All screens, flows, layouts, fonts, and result rendering are your application's own HTML/CSS — the SDK is an API client plus two optional camera components. Everything below concerns only those two components.

Theme the built-in capture components
const capture = new FaceCapture(container, {
  theme: {
    accentColor: '#e30613',        // guide outline + button (your brand color)
    buttonTextColor: '#fff',
    maskColor: 'rgba(10,20,40,.6)', // dimmed area around the guide
    guideLineWidth: 4,
  },
  labels: { captureButton: 'Take selfie' }, // any language, e.g. Dzongkha
});
Full CSS takeover

Set buttonClassName (and countdownClassName for FaceCapture) and the SDK applies no inline styles at all — the elements are yours to style:

new DocumentCapture(container, {
  theme: { buttonClassName: 'bank-btn bank-btn--capture' },
  labels: { captureButton: 'Scan document' },
});
Headless mode

Render your own controls entirely — the component only manages the camera, guide overlay, and best-frame selection:

const capture = new FaceCapture(container, { showCaptureButton: false });
capture.onCapture(handleBlob);
await capture.start();
// your own button:
myButton.onclick = () => capture.captureWithCountdown();

And of course you can skip the capture components completely: every API method accepts any Blob/File, so a fully custom getUserMedia UI works unchanged.

Image Input Types

All image parameters accept any of the following:

Type Example
File From <input type="file">
Blob From canvas, camera, etc.
Buffer Node.js fs.readFileSync()
Uint8Array Raw bytes
ArrayBuffer From fetch().arrayBuffer()
string (base64) "/9j/4AAQ..."
string (data URL) "data:image/jpeg;base64,..."

Camera Capture (Browser)

The SDK includes vanilla JS camera capture components — no React/Vue required.

import { DocumentCapture, FaceCapture } from '@drukverify/ekyc-sdk-js/capture';

// Document capture with card-shaped guide
const docCapture = new DocumentCapture(containerElement, {
  facingMode: 'environment',  // back camera
  guideColor: '#00ff88',
});
docCapture.onCapture((blob) => {
  // Best-quality frame as JPEG Blob
  client.ocr.scanDocument(blob);
});
await docCapture.start();

// Face capture with oval guide + countdown
const faceCapture = new FaceCapture(containerElement, {
  facingMode: 'user',    // front camera
  countdown: 3,          // 3-second countdown before capture
});
faceCapture.onCapture((blob) => {
  client.liveness.check(blob);
});
await faceCapture.start();

// Clean up
docCapture.destroy();
faceCapture.destroy();
Capture Options

DocumentCapture:

Option Type Default Description
facingMode 'user' | 'environment' 'environment' Camera selection
width number 1280 Preferred video width
height number 720 Preferred video height
guideColor string '#00ff88' Overlay guide color
bestFrameCount number 5 Frames to evaluate for best quality

FaceCapture:

Option Type Default Description
facingMode 'user' | 'environment' 'user' Camera selection
width number 640 Preferred video width
height number 480 Preferred video height
guideColor string '#00ff88' Overlay guide color
bestFrameCount number 5 Frames to evaluate for best quality
countdown number 3 Seconds before auto-capture (0 = manual)

Image Utilities

import { resizeImage, toBlob } from '@drukverify/ekyc-sdk-js';

// Resize image (browser only — uses canvas)
const resized = await resizeImage(file, 1024, 768, 0.85, 'image/jpeg');

// Convert any input to Blob
const { blob, filename } = await toBlob(base64String);

Error Handling

import { EkycError } from '@drukverify/ekyc-sdk-js';

try {
  await client.verify(doc, selfie);
} catch (err) {
  if (err instanceof EkycError) {
    console.error(err.message);  // Human-readable error
    console.error(err.status);   // HTTP status code (0 for timeout)
    console.error(err.body);     // Raw response body
  }
}

TypeScript Types

All response types are exported:

import type {
  // Verification
  VerifyFaceResult, DetectFacesResult, Face,
  RegisterFaceResult, SearchFaceResult, FaceMatch,
  // OCR
  DocumentOcrResult, PassportOcrResult, MrzData,
  // Liveness
  LivenessResult, DeepfakeResult,
  // Fraud
  FraudAnalysisResult, FakeDocumentResult,
  PhotoSubstitutionResult, TamperingResult,
  CopyScreenResult, SecurityFeaturesResult,
  // Batch
  BatchSubmitResult, BatchStatusResult, BatchResultsResponse,
  // Config
  EkycConfig,
  // Image
  ImageInput,
} from '@drukverify/ekyc-sdk-js';

License

MIT

Keywords