{"_id":"@drukverify/ekyc-sdk-js","_rev":"5-81c2c2834c1ea4e3c98c94f32ffb085d","name":"@drukverify/ekyc-sdk-js","dist-tags":{"latest":"0.7.0"},"versions":{"0.3.2":{"name":"@drukverify/ekyc-sdk-js","version":"0.3.2","keywords":["ekyc","ocr","face-verification","liveness","document-ocr","kyc","identity-verification"],"author":{"url":"Cloud Bhutan","name":"Drukverify"},"license":"MIT","_id":"@drukverify/ekyc-sdk-js@0.3.2","maintainers":[{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"}],"homepage":"https://drukverify.com/docs/sdks/js/install","bugs":{"url":"https://github.com/DrukVerify/ekyc-sdk-js/issues"},"dist":{"shasum":"97f46234501c31470c5d64c575dabdbe953a2cbe","tarball":"https://registry.npmjs.org/@drukverify/ekyc-sdk-js/-/ekyc-sdk-js-0.3.2.tgz","fileCount":16,"integrity":"sha512-3UD+HmZL7dNQpUKuUh7yIara8FQxNUR1x64aaHeeOe0VZJRf3JUDXI5sry41VpX0FWXMAiTmQVlQbpTsrwyQ+Q==","signatures":[{"sig":"MEUCIDKFirIe3H/zWCfkRqTcHXEOcT6pn+XuibEdE1p5y50SAiEAmht6VJ9dh+xO0I6/o8EBR6xMbzRBahowGwndmSn7r2U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":224590},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./capture":{"types":"./dist/capture.d.ts","import":"./dist/capture.mjs","require":"./dist/capture.js"}},"gitHead":"a62e28a1cd78ae9f84dd12467efc67f04873c9f7","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"},"repository":{"url":"git+https://github.com/DrukVerify/ekyc-sdk-js.git","type":"git"},"_npmVersion":"10.9.8","description":"Universal JavaScript SDK for eKYC — face verification, document OCR, liveness detection, fraud analysis. Works in browser and Node.js.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.1.9","typescript":"^5.4.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk-js_0.3.2_1784299692366_0.5654371712061619","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@drukverify/ekyc-sdk-js","version":"0.4.0","keywords":["ekyc","ocr","face-verification","liveness","document-ocr","kyc","identity-verification"],"author":{"url":"Cloud Bhutan","name":"Drukverify"},"license":"MIT","_id":"@drukverify/ekyc-sdk-js@0.4.0","maintainers":[{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"}],"homepage":"https://drukverify.com/docs/sdks/js/install","bugs":{"url":"https://github.com/DrukVerify/ekyc-sdk-js/issues"},"dist":{"shasum":"7a042a46c5934e743f96eee733776c15826962ba","tarball":"https://registry.npmjs.org/@drukverify/ekyc-sdk-js/-/ekyc-sdk-js-0.4.0.tgz","fileCount":16,"integrity":"sha512-UN95YqLHEvZtv1QSrChIkoOOBmGc1N4UWlwFanz+LuuuMP2d0EmA2utmr3k4/vCyUBhw+q3D+4SfTEIxU299pQ==","signatures":[{"sig":"MEQCIDvIcuJPNf3IcCPlTHKNR7ePcpql5L1dekF9ug+ed6AsAiA3evk3eyCIfGENkyKMT3Onquw0PB7Kgyq0uk3li0ooSg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":283542},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./capture":{"types":"./dist/capture.d.ts","import":"./dist/capture.mjs","require":"./dist/capture.js"}},"gitHead":"16acd9f298b956a52f79963a3a88dfa31698cdff","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"},"repository":{"url":"git+https://github.com/DrukVerify/ekyc-sdk-js.git","type":"git"},"_npmVersion":"10.9.8","description":"Universal JavaScript SDK for eKYC — face verification, document OCR, liveness detection, fraud analysis. Works in browser and Node.js.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.1.9","typescript":"^5.4.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk-js_0.4.0_1786914480792_0.2853943320571053","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@drukverify/ekyc-sdk-js","version":"0.5.0","keywords":["ekyc","ocr","face-verification","liveness","document-ocr","kyc","identity-verification"],"author":{"url":"Cloud Bhutan","name":"Drukverify"},"license":"MIT","_id":"@drukverify/ekyc-sdk-js@0.5.0","maintainers":[{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"}],"homepage":"https://drukverify.com/docs/sdks/js/install","bugs":{"url":"https://github.com/DrukVerify/ekyc-sdk-js/issues"},"dist":{"shasum":"0ca82f8c40720d2a7458eafe248b7e33e338b312","tarball":"https://registry.npmjs.org/@drukverify/ekyc-sdk-js/-/ekyc-sdk-js-0.5.0.tgz","fileCount":16,"integrity":"sha512-WN2noTXe33XLKH03TUH1eDklh/STjCS5O5PeMEq3XQSPBOP7E6wLC2dVaNTi3fvErSpFD+L+/pbzm6sa70wy8A==","signatures":[{"sig":"MEUCIQCvw72sW6AqwxWTKZshE0cFvXr0o6iG2Xo1uI10jxejNAIgLyqpmiexjq6VMQLaabbf3Es20bkSm/U9D1v5M+snJ+k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIAa0DSG8FtDRY+fSS0c7ketY5aauWYsn+ZIMPisPRtngAiA8d36i5WqFrh9I/g5zOojUMgkQ7gBgKexvJXjDRUi0WQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":306568},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./capture":{"types":"./dist/capture.d.ts","import":"./dist/capture.mjs","require":"./dist/capture.js"}},"gitHead":"601fd21da38acd6a7ce722f81266fdf96af436ce","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"},"repository":{"url":"git+https://github.com/DrukVerify/ekyc-sdk-js.git","type":"git"},"_npmVersion":"10.9.8","description":"Universal JavaScript SDK for eKYC — face verification, document OCR, liveness detection, fraud analysis. Works in browser and Node.js.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.1.9","typescript":"^5.4.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk-js_0.5.0_1790269200518_0.4050119576505202","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@drukverify/ekyc-sdk-js","version":"0.6.0","keywords":["ekyc","ocr","face-verification","liveness","document-ocr","kyc","identity-verification"],"author":{"url":"Cloud Bhutan","name":"Drukverify"},"license":"MIT","_id":"@drukverify/ekyc-sdk-js@0.6.0","maintainers":[{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"}],"homepage":"https://drukverify.com/docs/sdks/js/install","bugs":{"url":"https://github.com/DrukVerify/ekyc-sdk-js/issues"},"dist":{"shasum":"acbf47040a39596d4c2543cea826bef28667e380","tarball":"https://registry.npmjs.org/@drukverify/ekyc-sdk-js/-/ekyc-sdk-js-0.6.0.tgz","fileCount":16,"integrity":"sha512-xUVSJaDq4C4KifurdQAenmoEFBsGjU871joLPXIq8oxNc3QP5QpTvAgDQAR79nqb3PA6VRZcsukCM0DSaoH7AA==","signatures":[{"sig":"MEYCIQC1fODBzz6P7DZi5DCL0+18g9cFCFQEmuRI9gVtaH7VbQIhAI8zDFu1dku/zlUOJEih5ZQOe07dXYUBKIbnUMPkwCsk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICOdTqPs4XxUbrsAi6fwXt/M8LshLZe3mTwmRcWQ08X5AiEAxnFpmIUMPOK21q/is1RiE1qxzPhehvzDnBsxhLgCrsI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":309187},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./capture":{"types":"./dist/capture.d.ts","import":"./dist/capture.mjs","require":"./dist/capture.js"}},"gitHead":"b52e264cc143e810d88b76fd9c9801b3dfb03921","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"},"repository":{"url":"git+https://github.com/DrukVerify/ekyc-sdk-js.git","type":"git"},"_npmVersion":"10.9.8","description":"Universal JavaScript SDK for eKYC — face verification, document OCR, liveness detection, fraud analysis. Works in browser and Node.js.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.2","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.1.9","typescript":"^5.4.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/ekyc-sdk-js_0.6.0_1790293422428_0.772982969465074","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"_id":"@drukverify/ekyc-sdk-js@0.7.0","bugs":{"url":"https://github.com/DrukVerify/ekyc-sdk-js/issues"},"dist":{"shasum":"8914a2e0f22d6c3cce4f30e7b305d3d4bfe34f22","tarball":"https://registry.npmjs.org/@drukverify/ekyc-sdk-js/-/ekyc-sdk-js-0.7.0.tgz","fileCount":16,"integrity":"sha512-CDQosAJphwxiaw/AzcGHQr3HDLgjiqJGrV9WcKL9DV8UPYOhK5FZpcnTLGgrdNSyQUcIYF+HlaS95qrkVbjjkg==","signatures":[{"sig":"MEUCIFjx5MMDjBmBvkO5d4bhwULkg1KY7CutjNkQtZ1/b6NNAiEAiu44M0dyqKM+Bgo4yM20Qcd00bsLKavHF4BswjanVWM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIH9jdfUGYVFxXGXSrUb/svTurQCi8Q+36nXLl48bjhH8AiEA5HtJuo+A6ZXYXhl7eNlH54+fHKEuGS1aNl6zyw/eyIs="}],"unpackedSize":314982},"main":"./dist/index.js","name":"@drukverify/ekyc-sdk-js","types":"./dist/index.d.ts","author":{"url":"Cloud Bhutan","name":"Drukverify"},"module":"./dist/index.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./capture":{"types":"./dist/capture.d.ts","import":"./dist/capture.mjs","require":"./dist/capture.js"}},"gitHead":"cc039456b084033070d8144e77cc9239b09d8488","license":"MIT","scripts":{"dev":"tsup --watch","test":"vitest run","build":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm run build"},"version":"0.7.0","_npmUser":{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"},"homepage":"https://drukverify.com/docs/sdks/js/install","keywords":["ekyc","ocr","face-verification","liveness","document-ocr","kyc","identity-verification"],"repository":{"url":"git+https://github.com/DrukVerify/ekyc-sdk-js.git","type":"git"},"_npmVersion":"10.9.9","description":"Universal JavaScript SDK for eKYC — face verification, document OCR, liveness detection, fraud analysis. Works in browser and Node.js.","directories":{},"maintainers":[{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"}],"sideEffects":false,"_nodeVersion":"22.23.3","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","vitest":"^2.1.9","typescript":"^5.4.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ekyc-sdk-js_0.7.0_1790932918442_0.6938184117286375"}}},"time":{"created":"2026-07-17T14:48:12.145Z","modified":"2026-10-02T09:21:58.737Z","0.3.2":"2026-07-17T14:48:12.545Z","0.4.0":"2026-08-16T21:08:00.965Z","0.5.0":"2026-09-24T17:00:00.620Z","0.6.0":"2026-09-24T23:43:42.534Z","0.7.0":"2026-10-02T09:21:58.524Z"},"bugs":{"url":"https://github.com/DrukVerify/ekyc-sdk-js/issues"},"author":{"url":"Cloud Bhutan","name":"Drukverify"},"license":"MIT","homepage":"https://drukverify.com/docs/sdks/js/install","keywords":["ekyc","ocr","face-verification","liveness","document-ocr","kyc","identity-verification"],"repository":{"url":"git+https://github.com/DrukVerify/ekyc-sdk-js.git","type":"git"},"description":"Universal JavaScript SDK for eKYC — face verification, document OCR, liveness detection, fraud analysis. Works in browser and Node.js.","maintainers":[{"name":"tshewang_rinzin","email":"trigdzeen@gmail.com"}],"readme":"# @drukverify/ekyc-sdk-js\n\nUniversal JavaScript SDK for eKYC — face verification, document OCR, liveness detection, and fraud analysis. Works in both browser and Node.js.\n\n**Zero runtime dependencies** — uses native `fetch` and `FormData`.\n\n## Installation\n\n```bash\nnpm install @drukverify/ekyc-sdk-js\n```\n\n## Quick Start\n\n### Node.js (server-side, secret key)\n\n```typescript\nimport { EkycClient } from '@drukverify/ekyc-sdk-js';\nimport { readFileSync } from 'node:fs';\n\nconst client = new EkycClient({\n  baseUrl: 'https://api.drukverify.com',\n  apiKey: process.env.DV_SECRET_KEY, // dv_sk_live_… — server-side only\n});\n\nconst image = readFileSync('./cid-front.jpg');\nconst ocr = await client.ocr.scanDocument(image, { type: 'cid' });\nconsole.log(ocr.fields.full_name, ocr.fields.date_of_birth);\n```\n\n### Browser (session token)\n\nNever embed a secret key in browser code. Your backend mints a short-lived\nsession token via `POST /v1/sessions` (with the secret key) and hands it to\nthe page:\n\n```typescript\nimport { EkycClient } from '@drukverify/ekyc-sdk-js';\n\nconst { token } = await fetch('/your-backend/session').then(r => r.json());\nconst client = new EkycClient({\n  baseUrl: 'https://api.drukverify.com',\n  apiKey: token, // dv_tok_…\n});\n\nconst file = document.querySelector('input[type=file]').files[0];\nconst fraud = await client.fraud.detect(file, { documentType: 'cid' });\nconsole.log(fraud.is_fraudulent, fraud.overall_score);\n```\n\n## Configuration\n\n```typescript\nconst client = new EkycClient({\n  baseUrl: 'https://api.drukverify.com', // required, no trailing slash\n  apiKey: token,                          // dv_tok_… (browser) or dv_sk_… (server)\n  version: '2026-05-12',                  // Drukverify-Version header (default shown)\n  timeout: 30000,                         // ms\n  headers: {},                            // extra headers\n});\n```\n\n## API Reference\n\n### Document OCR\n\n```typescript\nconst r = await client.ocr.scanDocument(image, {\n  backImage,            // optional back side\n  type: 'cid',          // optional hint: 'cid' | 'passport' (others auto-detect)\n  customerRef: 'u-123', // optional\n});\n// r.document_type, r.fields (per-type shape), r.ocr_id\n\nawait client.ocr.get(id);      // GET /v1/ocr/:id\nawait client.ocr.list();       // GET /v1/ocr\nawait client.ocr.delete(id);   // DELETE /v1/ocr/:id\n```\n\n### Fraud Detection\n\n```typescript\nconst r = await client.fraud.detect(image, { documentType: 'cid' });\n// Already scanned the same files? Reuse that run and skip the fraud route's OCR pass:\nconst quick = await client.fraud.detect(image, { backImage, ocrId: scan.ocr_id });\n// r.is_fraudulent, r.overall_score, r.signals.{fake_document,photo_substitution,tampering,copy_or_screen}\n\nawait client.fraud.get(fcId);  // GET /v1/fraud/checks/:id\n```\n\n### Liveness\n\n```typescript\n// Passive (1 frame)\nconst r = await client.liveness.check(selfie);\n\n// Burst (3–5 frames)\nconst r2 = await client.liveness.check([f1, f2, f3], { mode: 'burst' });\n\n// Challenge (server-chosen action)\nconst ch = await client.liveness.createChallenge();  // { action, challenge_token, expires_at }\n// Show ch.action, then capture: one neutral frame first, then 4–6 frames\n// over ~3 s while the user performs the action and returns to centre.\n// Frames must be upright and unmirrored; a blink needs ≥3 frames at ≤200 ms.\nconst [baseline] = await capture.captureSequence(1, 0);\nconst action = await capture.captureSequence(5, 250);   // FaceCapture, see below\nconst r3 = await client.liveness.check([baseline, ...action], {\n  mode: 'challenge',\n  challengeToken: ch.challenge_token, // one-shot, ~120s\n});\n// r3.is_live, r3.score, r3.reason\n\nawait client.liveness.get(lcId);\n```\n\n### Face Verification\n\n```typescript\n// 1:1 — document portrait vs selfie\nconst r = await client.verify(documentImage, selfieImage);\n// r.match, r.similarity\n\n// 1:N gallery\nawait client.verification.registerFace(image, 'customer-ref');\nawait client.verification.searchFace(image, { limit: 5, minSimilarity: 0.4 });\nawait client.verification.detectDuplicate(image);\nawait client.verification.listRegistrations();\nawait client.verification.deleteRegistration(id);\n```\n\n## Branding & Theming\n\n**The SDK imposes no UI.** All screens, flows, layouts, fonts, and result rendering\nare your application's own HTML/CSS — the SDK is an API client plus two *optional*\ncamera components. Everything below concerns only those two components.\n\n### Theme the built-in capture components\n\n```typescript\nconst capture = new FaceCapture(container, {\n  theme: {\n    accentColor: '#e30613',        // guide outline + button (your brand color)\n    buttonTextColor: '#fff',\n    maskColor: 'rgba(10,20,40,.6)', // dimmed area around the guide\n    guideLineWidth: 4,\n  },\n  labels: { captureButton: 'Take selfie' }, // any language, e.g. Dzongkha\n});\n```\n\n### Full CSS takeover\n\nSet `buttonClassName` (and `countdownClassName` for FaceCapture) and the SDK\napplies **no inline styles at all** — the elements are yours to style:\n\n```typescript\nnew DocumentCapture(container, {\n  theme: { buttonClassName: 'bank-btn bank-btn--capture' },\n  labels: { captureButton: 'Scan document' },\n});\n```\n\n### Headless mode\n\nRender your own controls entirely — the component only manages the camera,\nguide overlay, and best-frame selection:\n\n```typescript\nconst capture = new FaceCapture(container, { showCaptureButton: false });\ncapture.onCapture(handleBlob);\nawait capture.start();\n// your own button:\nmyButton.onclick = () => capture.captureWithCountdown();\n```\n\nAnd of course you can skip the capture components completely: every API method\naccepts any `Blob`/`File`, so a fully custom `getUserMedia` UI works unchanged.\n\n## Image Input Types\n\nAll image parameters accept any of the following:\n\n| Type | Example |\n|------|---------|\n| `File` | From `<input type=\"file\">` |\n| `Blob` | From canvas, camera, etc. |\n| `Buffer` | Node.js `fs.readFileSync()` |\n| `Uint8Array` | Raw bytes |\n| `ArrayBuffer` | From `fetch().arrayBuffer()` |\n| `string` (base64) | `\"/9j/4AAQ...\"` |\n| `string` (data URL) | `\"data:image/jpeg;base64,...\"` |\n\n## Camera Capture (Browser)\n\nThe SDK includes vanilla JS camera capture components — no React/Vue required.\n\n```typescript\nimport { DocumentCapture, FaceCapture } from '@drukverify/ekyc-sdk-js/capture';\n\n// Document capture with card-shaped guide\nconst docCapture = new DocumentCapture(containerElement, {\n  facingMode: 'environment',  // back camera\n  guideColor: '#00ff88',\n});\ndocCapture.onCapture((blob) => {\n  // Best-quality frame as JPEG Blob\n  client.ocr.scanDocument(blob);\n});\nawait docCapture.start();\n\n// Face capture with oval guide + countdown\nconst faceCapture = new FaceCapture(containerElement, {\n  facingMode: 'user',    // front camera\n  countdown: 3,          // 3-second countdown before capture\n});\nfaceCapture.onCapture((blob) => {\n  client.liveness.check(blob);\n});\nawait faceCapture.start();\n\n// Clean up\ndocCapture.destroy();\nfaceCapture.destroy();\n```\n\n### Capture Options\n\n**DocumentCapture:**\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `facingMode` | `'user' \\| 'environment'` | `'environment'` | Camera selection |\n| `width` | `number` | `1280` | Preferred video width |\n| `height` | `number` | `720` | Preferred video height |\n| `guideColor` | `string` | `'#00ff88'` | Overlay guide color |\n| `bestFrameCount` | `number` | `5` | Frames to evaluate for best quality |\n\n**FaceCapture:**\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `facingMode` | `'user' \\| 'environment'` | `'user'` | Camera selection |\n| `width` | `number` | `640` | Preferred video width |\n| `height` | `number` | `480` | Preferred video height |\n| `guideColor` | `string` | `'#00ff88'` | Overlay guide color |\n| `bestFrameCount` | `number` | `5` | Frames to evaluate for best quality |\n| `countdown` | `number` | `3` | Seconds before auto-capture (0 = manual) |\n\n## Image Utilities\n\n```typescript\nimport { resizeImage, toBlob } from '@drukverify/ekyc-sdk-js';\n\n// Resize image (browser only — uses canvas)\nconst resized = await resizeImage(file, 1024, 768, 0.85, 'image/jpeg');\n\n// Convert any input to Blob\nconst { blob, filename } = await toBlob(base64String);\n```\n\n## Error Handling\n\n```typescript\nimport { EkycError } from '@drukverify/ekyc-sdk-js';\n\ntry {\n  await client.verify(doc, selfie);\n} catch (err) {\n  if (err instanceof EkycError) {\n    console.error(err.message);  // Human-readable error\n    console.error(err.status);   // HTTP status code (0 for timeout)\n    console.error(err.body);     // Raw response body\n  }\n}\n```\n\n## TypeScript Types\n\nAll response types are exported:\n\n```typescript\nimport type {\n  // Verification\n  VerifyFaceResult, DetectFacesResult, Face,\n  RegisterFaceResult, SearchFaceResult, FaceMatch,\n  // OCR\n  DocumentOcrResult, PassportOcrResult, MrzData,\n  // Liveness\n  LivenessResult, DeepfakeResult,\n  // Fraud\n  FraudAnalysisResult, FakeDocumentResult,\n  PhotoSubstitutionResult, TamperingResult,\n  CopyScreenResult, SecurityFeaturesResult,\n  // Batch\n  BatchSubmitResult, BatchStatusResult, BatchResultsResponse,\n  // Config\n  EkycConfig,\n  // Image\n  ImageInput,\n} from '@drukverify/ekyc-sdk-js';\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}