npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

smartcomply-web-sdk

v1.0.19

Published

Drop-in identity verification (KYC) widget for web apps — face liveness, NIN/BVN, document verification

Readme

SmartComply Web SDK

Drop-in identity verification (KYC) widget for web applications. Embed one line of code and let your users verify their identity through facial liveness detection, government ID checks (BVN/NIN), and international document verification (passport, national ID, driver's license).

Overview

SmartComply SDK is a KYC-as-a-service widget that businesses embed in their web apps to verify end-user identities. It handles the full verification flow — from collecting ID details to live face matching — and delivers results asynchronously via webhook.

Target Audience

  • Fintechs, banks, and lending platforms that need to onboard customers securely
  • Any business required to perform Know Your Customer (KYC) checks before granting account access

What It Does

The SDK verifies that a person is real, alive, and who they claim to be:

  1. Identity verification — Validates the user's BVN/NIN against government databases, or extracts data from uploaded documents via OCR
  2. Liveness detection — Camera-based challenge-response (blink, turn head, open mouth) to prove the person is physically present — not a photo or video replay
  3. Face matching — Compares the user's live selfie against:
    • The government-returned photo (BVN/NIN flow), or
    • The face on their uploaded document (passport/license flow)

Two Verification Flows

| Flow | How it works | ID Types | |------|-------------|----------| | Data verification | User enters an ID number → backend validates against government database → face match against government photo | BVN, NIN | | Document verification | User uploads/captures a document photo → OCR extracts data + expiry check → face match against document photo | Passport, National ID, Driver's License |

End-to-End Flow

┌─────────────────────────────────────────────────────────────────────┐
│  YOUR APP                                                           │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  SmartComply Widget (modal)                                   │  │
│  │                                                               │  │
│  │  Welcome → Country → ID Type → Enter ID / Upload Doc          │  │
│  │      → Face Liveness (camera) → Done                          │  │
│  └───────────────────────────────────────────────────────────────┘  │
│                              │                                      │
│                    submit    │                                      │
│                              ▼                                      │
│                      Adhere Backend                                 │
│                         │                                           │
│               ┌─────────┼──────────┐                               │
│               ▼         ▼          ▼                                │
│          Face Match   OCR      Gov DB Check                        │
│          (DeepFace)  (document)  (BVN/NIN)                         │
│               └─────────┼──────────┘                               │
│                         ▼                                           │
│                    Webhook POST ──────────► YOUR SERVER             │
│                    (signed with HMAC)       (result handler)        │
└─────────────────────────────────────────────────────────────────────┘

Install

npm install smartcomply-web-sdk

Alternative: CDN (No Build Step)

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/smartcomply.browser.js"></script>
<script>
  // SDK available as window.SmartComplySDK
  SmartComplySDK.SmartComplyFlow.open({
    apiKey: "your_api_key",
    clientId: "your_client_id",
    onComplete: (result) => console.log("Done:", result),
  });
</script>

Option 1: Drop-in Widget (Recommended)

The fastest way to add KYC. Opens a complete, branded verification modal — handles everything automatically.

<button id="verify-btn">Verify Identity</button>

<script type="module">
  import { SmartComplyFlow } from "smartcomply-web-sdk";

  document.getElementById("verify-btn").onclick = () => {
    SmartComplyFlow.open({
      apiKey: "pk_live_your_api_key",
      clientId: "your-sdk-config-uuid",
      environment: "production",

      onComplete(result) {
        // Verification submitted! Final result arrives via webhook.
        console.log("Entry ID:", result.entryId);
        console.log("Status:", result.status);  // "processing"
        // Update your UI — tell the user to wait for confirmation
      },

      onError(err) {
        console.error("Verification failed:", err.message);
      },

      onClose() {
        // User closed the modal without completing
      },
    });
  };
</script>

That's it. The SDK will:

  1. Create a secure session with the Adhere backend
  2. Show a branded welcome screen (your brand name + theme from dashboard)
  3. Let the user select their country and ID type
  4. Collect their BVN/NIN number or capture their document photo
  5. Run face liveness detection (camera + challenge actions)
  6. Record a video and submit everything to the backend
  7. Show a result screen and call your onComplete callback

What the User Sees

| Step | Screen | Description | |------|--------|-------------| | 1 | Welcome | Your brand name, description, and what to expect | | 2 | Country | Select country (auto-skipped if only one country configured) | | 3 | ID Type | Choose from the channels you configured (e.g., BVN, NIN, Passport) | | 4a | ID Input | Enter BVN/NIN number → instant backend verification against government DB | | 4b | Document | Capture a photo of passport/ID card (camera or file upload) | | 5 | Liveness | Camera opens — user completes challenge actions (blink, turn head, open mouth) | | 6 | Done | "Verification Submitted" — user clicks Done, result arrives via webhook |

SmartComplyFlow.open() Options

SmartComplyFlow.open({
  // Required
  apiKey: string,         // Your API key from the Adhere dashboard
  clientId: string,       // UUID from your SDK Config (created in dashboard)

  // Optional
  environment: "production" | "sandbox",  // Default: "sandbox"
  timeout: number,                        // Request timeout in ms (default: 30000)

  // Callbacks
  onComplete: (result) => void,   // Verification submitted successfully
  onError: (error) => void,       // Unrecoverable error
  onClose: () => void,            // User closed the modal
});

onComplete Result

{
  entryId: 42,                    // Use this to track the verification
  status: "processing",           // Always "processing" — final result via webhook
  submittedAt: "2026-04-13T...",  // ISO timestamp
  verificationResult: {           // Only for data verification (BVN/NIN)
    status: "success",
    code: "VERIFICATION_COMPLETE",
    data: { first_name: "Amara", last_name: "Okafor", identity_check_id: 123, ... }
  }
}

Option 2: Headless (Custom UI)

For full control over the user interface, use the SDK's API methods directly.

Initialize

import { SmartComply } from "smartcomply-web-sdk";

const sdk = new SmartComply({
  apiKey: "pk_live_your_api_key",
  clientId: "your-sdk-config-uuid",
  environment: "production",
});

Create Session

Every verification flow starts with a session. Sessions last 30 minutes and are single-use (revoked after liveness submission).

const session = await sdk.createSession();
// session.token — used internally for all subsequent API calls
// session.expires_at — ISO timestamp

Load Configuration

Fetch your SDK config (brand name, theme, available ID types per country):

const config = await sdk.initializeConfig();

console.log(config.brand_name);        // "Your Company Name"
console.log(config.verification_type); // ["data_verification"]

// Channels are grouped by country with field definitions:
console.log(config.channels);
// {
//   "nigeria": [
//     { id: 8, name: "National Identity Number (NIN)", fields: [{ type: "input", label: "Identification Number" }] },
//     { id: 2, name: "Bank Verification Number Advanced (BVN)", fields: [{ type: "input", label: "Bank Verification Number" }] }
//   ]
// }

Use config.channels to build your own country/ID type selector. Each channel's fields array tells you what inputs to render.

Verify Identity (Data Verification)

For BVN/NIN — validates against the government database:

const result = await sdk.onboarding.verify({
  identity_type_id: 8,                                    // Channel ID from config.channels
  fields: { identification_number: "12345678901" },       // Field keys from channel's fields definition
});

if (result.status === "success") {
  console.log(result.data.identity_check_id); // Save this — needed for face matching in liveness
  console.log(result.data.first_name);        // "Amara"
}

Liveness Check (with built-in camera UI)

Mount the SDK's liveness UI into any container element:

const container = document.getElementById("liveness-container");

const result = await sdk.liveness.startCheck(container, {
  identifier: "12345678901",          // The ID number entered by the user
  identifier_type: "NIN",
  country: "NG",
  id_file: documentBlob,              // Optional: document photo (for document flow)
  identity_check: identityCheckId,    // Optional: from verify response (for data flow)
}, ["BLINK", "TURN_LEFT", "OPEN_MOUTH"]);

console.log(result.status); // "processing"

The SDK handles camera access, face detection, action prompts, video recording, and submission.

Liveness Check (fully manual)

If you want to handle camera and recording yourself:

// 1. Create entry
const entry = await sdk.liveness.create({
  identifier: "A12345678",
  identifier_type: "Passport",
  country: "US",
  challenge_actions: ["BLINK", "TURN_LEFT", "OPEN_MOUTH"],
  autoshot_file: selfieBlob,          // Captured selfie (JPEG/PNG, max 5MB)
  id_file: passportPhotoBlob,         // Optional: document photo
  identity_check: identityCheckId,    // Optional: from verify response
});

// 2. Run your own camera/detection/recording UI
// ...

// 3. Submit the recorded video + snapshot
const result = await sdk.liveness.submit(entry.id, videoBlob, snapshotBlob);
// result.status === "processing"

After submission, the session is revoked. Each clientId can only complete one full verification.


Receiving Results (Webhook)

Verification is processed asynchronously. After the user submits, the backend runs face matching using AI (DeepFace with RetinaFace detection) and delivers results via webhook to the URL configured in your SDK Config.

Webhook Payload — Data Verification (BVN/NIN)

POST https://your-server.com/webhook
Content-Type: application/json
X-Adhere-Signature: <hmac-sha256-hex>

{
  "event": "liveness.completed",
  "data": {
    "entry_id": 42,
    "status": "passed",
    "is_verified": true,
    "match_score": 0.15,
    "confidence_percentage": 62.5,
    "identity_face_match": {
      "verified": true,
      "distance": 0.12,
      "threshold": 0.4,
      "confidence_percentage": 70.0
    },
    "metadata": { "ip_address": "...", "user_agent": "..." }
  }
}

Webhook Payload — Document Verification (Passport/License)

{
  "event": "liveness.completed",
  "data": {
    "entry_id": 43,
    "status": "passed",
    "is_verified": true,
    "match_score": 0.18,
    "confidence_percentage": 55.0,
    "document_verification": {
      "status": "verified",
      "document_type": "passport",
      "is_expired": false,
      "face_match_verified": true,
      "face_match_score": 0.22,
      "extracted_name": "AMARA OKAFOR",
      "extracted_expiry_date": "2030-06-15"
    },
    "metadata": { "ip_address": "...", "user_agent": "..." }
  }
}

Understanding the Scores

  • match_score (distance) — Raw distance between face embeddings. Lower = more similar. Threshold is 0.4 (Facenet default).
  • confidence_percentage — Human-readable score: how close the match is to perfect. 100% = identical, 0% = at the threshold boundary.
  • identity_face_match — Only present in data verification (BVN/NIN). Confirms the person doing liveness matches the face on the government database.
  • document_verification — Only present in document verification. Includes OCR results and document-to-selfie face match.

Possible Statuses

| Status | Meaning | |--------|---------| | passed | All checks passed — person is verified | | failed | Face mismatch, expired document, or processing error | | processing | Still being processed (rare — usually completes in seconds) |

Verify Signature

Always verify the webhook signature to prevent spoofing:

const crypto = require("crypto");

app.post("/webhook/smartcomply", express.json(), (req, res) => {
  const signature = req.headers["x-adhere-signature"];
  const secret = process.env.WEBHOOK_SECRET.replace(/-/g, "");
  const expected = crypto
    .createHmac("sha256", secret)
    .update(JSON.stringify(req.body))
    .digest("hex");

  const isValid = crypto.timingSafeEqual(
    Buffer.from(signature, "hex"),
    Buffer.from(expected, "hex")
  );

  if (!isValid) return res.status(401).send("Bad signature");

  // Handle the event
  const { event, data } = req.body;

  if (event === "liveness.completed" && data.is_verified) {
    // ✓ User is verified — update your database
    markUserAsVerified(data.entry_id);
  }

  res.json({ received: true });
});

Challenge Actions

| Action | What the user does | |--------|-------------------| | BLINK | Blink both eyes | | TURN_LEFT | Turn head to the left | | TURN_RIGHT | Turn head to the right | | TURN_HEAD | Turn head in any direction | | OPEN_MOUTH | Open mouth wide |

Actions must be UPPERCASE. We recommend using 3 actions: ["BLINK", "TURN_LEFT", "OPEN_MOUTH"].


Error Handling

import { SDKError, AuthError, NetworkError } from "smartcomply-web-sdk";

try {
  await sdk.createSession();
} catch (err) {
  if (err instanceof AuthError) {
    // 401: Invalid API key, expired session, or disabled branch
  } else if (err instanceof NetworkError) {
    // No internet, timeout, DNS failure
  } else if (err instanceof SDKError) {
    // Backend error: validation, insufficient balance, etc.
    console.log(err.statusCode);  // HTTP status
    console.log(err.errorCode);   // Machine-readable code
    console.log(err.errorData);   // Additional error details
  }
}

| Error Code | HTTP | Meaning | |------------|------|---------| | INVALID_API_KEY | 401 | Bad API key or expired session | | SDK_CONFIG_NOT_FOUND | 404 | Invalid clientId | | VALIDATION_ERROR | 400 | Missing or invalid fields | | INSUFFICIENT_BALANCE | 402 | Top up your wallet |


Theming

The widget automatically uses the theme from your SDK Config (set in the Adhere dashboard):

  • default — Clean blue on white
  • midnight_blue — Dark mode with blue accents
  • sunset_gold — Warm gold on cream
  • forest_emerald — Green on mint

No client-side theme configuration required.


Browser Support

Requires camera access (getUserMedia), video recording (MediaRecorder), and WebAssembly.

| Browser | Version | |---------|---------| | Chrome | 80+ | | Firefox | 75+ | | Safari | 14+ | | Edge | 80+ |


Prerequisites

  1. Adhere account — Sign up at the dashboard
  2. API Key — Format: pk_live_... (from dashboard → API Keys)
  3. SDK Config — Create in dashboard with your brand name, theme, verification types, channels, and webhook URL
  4. Client ID — The UUID shown on your SDK Config
  5. Funded wallet — Each verification deducts from your balance
  6. Webhook endpoint — A URL on your server to receive verification results

TypeScript Support

Full TypeScript definitions are included. Key types:

import type {
  FlowOptions,
  FlowResult,
  SDKConfig,
  SDKInitConfig,
  SessionResponse,
  VerifyIdentityResponse,
  LivenessCreateResponse,
  LivenessSubmitResponse,
  ChallengeAction,
  LivenessWebhookPayload,
  ApiResponse,
} from "smartcomply-web-sdk";

Quick Start (Test in 2 Minutes)

For production, always use npm install. Clone only for testing/contributing.

# 1. Install globally (for testing)
npm install -g smartcomply-web-sdk

# 2. Or clone and run demo (testing only)
git clone https://github.com/386konsult/smartcomply-web-sdk.git
cd smartcomply-web-sdk
npm install
npm run demo
# Opens http://localhost:3000 with test page

Testing

Test the SDK locally before integrating:

cd smartcomply-web-sdk
npm run demo

This starts a mock API server and opens a browser test page. Use these test credentials:

  • API Key: Any string works in demo mode
  • Client ID: Create one in your Adhere dashboard

License

ISC