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

@unbraided/kenal-ekyc-sdk

v1.1.1

Published

Kenal eKYC SDK for React Native applications

Readme

@unbraided/kenal-ekyc-sdk

A React Native SDK for integrating Kenal's eKYC solution in your applications.

Installation

npm install @unbraided/kenal-ekyc-sdk

Ensure you have the required peer dependencies:

npm install react-native-webview

For TypeScript users, install type definitions:

npm install --save-dev @types/react @types/react-native

Usage

Initializing the SDK

import { KenalClient } from "@unbraided/kenal-ekyc-sdk";

KenalClient.initialize({
  apiKey: "YOUR_API_KEY",
  environment: "sandbox", // or 'production'
});

Unified eKYC Service (Recommended)

The Ekyc service provides a unified interface for all document types including Passport, MyKad, MyPR, MyTentera, and AML checks. This is the recommended approach for new integrations.

Starting Verification

import React, { useState } from "react";
import { View, Button, TextInput } from "react-native";
import { Ekyc, KenalClient, KenalWebView } from "@unbraided/kenal-ekyc-sdk";

const EkycScreen = () => {
  const [verificationUrl, setVerificationUrl] = useState(null);

  const startVerification = async () => {
    try {
      const result = await Ekyc.startVerification({
        RefID: "customer-12345",
        Name: "JOHN DOE",
        IDNumber: "990101011234",
        // Add other optional parameters based on document type
      });

      setVerificationUrl(result.fullURL);
      
      console.log("Verification started:", result);
    } catch (error) {
      console.error("Verification error:", error);
      alert(`Failed to start verification: ${error.message}`);
    }
  };

  if (verificationUrl) {
    return (
      <KenalWebView
        url={verificationUrl}
        onComplete={(data) => console.log("Verification completed:", data)}
        onError={(error) => console.error("WebView error:", error)}
      />
    );
  }

  return (
    <View>
      <Button title="Start Verification" onPress={startVerification} />
    </View>
  );
};

Parameters by Document Type

Required for All Document Types

  • RefID (string, required) - Your unique reference identifier for this verification

Passport Verification

await Ekyc.startVerification({
  RefID: "customer-12345",
  Name: "JOHN DOE",              // Required
  IDNumber: "A12345678",         // Required (Passport number)
  DocIssueCountry: "USA",        // Required (ISO 3166-1 alpha-3 code)
});

Required Fields:

  • Name - Full name as on passport (always required)
  • IDNumber - Passport number (always required)
  • DocIssueCountry - Country that issued the passport (always required)

MyKad Verification

await Ekyc.startVerification({
  RefID: "customer-12345",
  Name: "AHMAD BIN ABDULLAH",    // Required if AutofillFromOCR disabled
  IDNumber: "990101011234",      // Required if AutofillFromOCR disabled
});

Required Fields:

  • Name - Full name as on MyKad (required only if OCR autofill is disabled)
  • IDNumber - 12-digit MyKad number (required only if OCR autofill is disabled)

Note: If your workflow has OCR autofill enabled, these fields are optional and will be extracted from the ID card.

MyPR Verification

await Ekyc.startVerification({
  RefID: "customer-12345",
  Name: "TAN AH KOW",            // Required if AutofillFromOCR disabled
  IDNumber: "A1234567",          // Required if AutofillFromOCR disabled (MyPR number)
});

Required Fields:

  • Name - Full name as on MyPR (required only if OCR autofill is disabled)
  • IDNumber - MyPR number (required only if OCR autofill is disabled)

MyTentera Verification

await Ekyc.startVerification({
  RefID: "customer-12345",
  Name: "MOHD FAIZAL",           // Required if AutofillFromOCR disabled
  IDNumber: "850315021234",      // Required if AutofillFromOCR disabled
  ArmyNumber: "ATM123456",       // Required if AutofillFromOCR disabled
});

Required Fields:

  • Name - Full name (required only if OCR autofill is disabled)
  • IDNumber - IC number (required only if OCR autofill is disabled)
  • ArmyNumber - Military service number (required only if OCR autofill is disabled)

AML Check Only

await Ekyc.startVerification({
  RefID: "customer-12345",
  Name: "JOHN DOE",              // Required
  Birthdate: "1985-06-20",       // Optional
  Nationality: "MYS",            // Optional
  IDNumber: "990101011234",      // Optional
});

Required Fields:

  • Name - Full name (always required for standalone AML checks)

Note: For AML checks, other fields like Birthdate, Nationality, and IDNumber are optional but recommended for more accurate results.


Generating Recovery Links

Recovery links allow users to resume incomplete verifications. You can generate them using the validationId from a previous verification.

const generateRecoveryLink = async (validationId: string) => {
  try {
    const recovery = await Ekyc.generateRecoveryLink({
      validationId: validationId,
    });

    console.log("Recovery link:", recovery.fullURL);
    console.log("Expires at:", new Date(recovery.expiresAt * 1000));
    
    // Open the recovery link in KenalWebView
    setVerificationUrl(recovery.fullURL);
  } catch (error) {
    console.error("Recovery link error:", error);
  }
};

Response:

{
  token: string;        // JWT token for the recovery session
  fullURL: string;      // Full URL to resume verification
  expiresAt: number;    // Unix timestamp (seconds) when link expires
}

Important Notes:

  • Recovery links expire after 1 hour
  • The recovery link allows users to continue from where they left off

Complete Example with Recovery Link

Note: This example shows the SDK usage. In production, validationId management should happen on your backend server.

import React, { useState } from "react";
import { View, Button, Alert } from "react-native";
import { Ekyc, KenalClient, KenalWebView } from "@unbraided/kenal-ekyc-sdk";

const CompleteEkycExample = () => {
  const [verificationUrl, setVerificationUrl] = useState(null);

  // Initialize SDK
  React.useEffect(() => {
    KenalClient.initialize({
      apiKey: "YOUR_API_KEY",
      environment: "sandbox",
    });
  }, []);

  const startVerification = async () => {
    try {
      const result = await Ekyc.startVerification({
        RefID: "customer-12345",
        Name: "JOHN DOE",
        IDNumber: "990101011234",
      });

      setVerificationUrl(result.fullURL);
    } catch (error) {
      Alert.alert("Error", error.message);
    }
  };

  const requestRecoveryLink = async () => {
    try {      
      const validationId = "your-validation-id-from-kenal-callback";
      
      const recovery = await Ekyc.generateRecoveryLink({
        validationId: validationId,
      });

      Alert.alert(
        "Recovery Link Generated",
        `Expires: ${new Date(recovery.expiresAt * 1000).toLocaleString()}`,
        [
          {
            text: "Open Now",
            onPress: () => setVerificationUrl(recovery.fullURL),
          },
          { text: "Cancel", style: "cancel" },
        ]
      );
    } catch (error) {
      Alert.alert("Error", error.message);
    }
  };

  if (verificationUrl) {
    return (
      <View style={{ flex: 1 }}>
        <Button title="← Back" onPress={() => setVerificationUrl(null)} />
        <KenalWebView
          url={verificationUrl}
          onComplete={(data) => {
            console.log("Verification completed:", data);
            setVerificationUrl(null);
          }}
          onError={(error) => {
            console.error("WebView error:", error);
            Alert.alert("Error", error.message);
          }}
        />
      </View>
    );
  }

  return (
    <View style={{ padding: 20 }}>
      <Button title="Start Verification" onPress={startVerification} />
      <Button title="Request Recovery Link" onPress={requestRecoveryLink} />
    </View>
  );
};

export default CompleteEkycExample;

TypeScript Support

The SDK exports TypeScript types for all parameters and responses:

import type {
  EkycStartParams,
  EkycStartResponse,
  GenerateRecoveryLinkParams,
  GenerateRecoveryLinkResponse,
} from "@unbraided/kenal-ekyc-sdk";

// Use in your code
const params: EkycStartParams = {
  RefID: "customer-12345",
  Name: "JOHN DOE",
  IDNumber: "990101011234",
};

Legacy Document-Specific Services

The following services are maintained for backward compatibility. For new integrations, use the unified Ekyc service above.

MyKad Verification (Legacy)

import React, { useState } from "react";
import { View, Button, TextInput, StyleSheet } from "react-native";
import { MyKad, KenalWebView } from "@unbraided/kenal-ekyc-sdk";

const MyKadScreen = () => {
  const [name, setName] = useState("");
  const [idNumber, setIDNumber] = useState("");
  const [refID, setRefID] = useState("");
  const [useOCRForData, setUseOCRForData] = useState(false);
  const [verificationUrl, setVerificationUrl] = useState(null);

  const startVerification = async () => {
    try {
      const result = await MyKad.start({
        name: name,
        idNumber: idNumber,
        useOCRForData: useOCRForData,
        refId: refID,
      });

      setVerificationUrl(result.fullURL);
    } catch (error) {
      console.error("Verification error:", error);
      alert(`Failed to start verification: ${error.message}`);
    }
  };

  const handleComplete = (data) => {
    console.log("Verification completed:", data);
  };

  if (verificationUrl) {
    return (
      <KenalWebView
        url={verificationUrl}
        onComplete={handleComplete}
        onError={(error) => console.error("WebView error:", error)}
      />
    );
  }

  return (
    <View style={styles.container}>
      <TextInput style={styles.input} placeholder="Enter your name" value={name} onChangeText={setName} />
      <TextInput style={styles.input} placeholder="Enter your ID number" value={idNumber} onChangeText={setIdNumber} />
      <TextInput style={styles.input} placeholder="Enter a reference ID" value={refID} onChangeText={setRefID} />
      <Button title="Start Verification" onPress={startVerification} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: "center",
  },
  input: {
    height: 40,
    borderWidth: 1,
    borderColor: "#ccc",
    borderRadius: 5,
    marginBottom: 10,
    paddingHorizontal: 10,
  },
});

export default MyKadScreen;

Passport Verification (Legacy)

import React, { useState } from "react";
import { View, Button, TextInput, StyleSheet } from "react-native";
import { Passport, KenalWebView } from "@unbraided/kenal-ekyc-sdk";

const PassportScreen = () => {
  const [name, setName] = useState("");
  const [passportNumber, setPassportNumber] = useState("");
  const [docIssueCountry, setDocIssueCountry] = useState("");
  const [refID, setRefID] = useState("");
  const [verificationUrl, setVerificationUrl] = useState(null);

  const startVerification = async () => {
    try {
      const result = await Passport.start({
        name: name,
        passportNumber: passportNumber,
        docIssueCountry: docIssueCountry,
        refId: refID,
      });

      setVerificationUrl(result.fullURL);
    } catch (error) {
      console.error("Verification error:", error);
      alert(`Failed to start verification: ${error.message}`);
    }
  };

  const handleComplete = (data) => {
    console.log("Verification completed:", data);
  };

  if (verificationUrl) {
    return (
      <KenalWebView
        url={verificationUrl}
        onComplete={handleComplete}
        onError={(error) => console.error("WebView error:", error)}
      />
    );
  }

  return (
    <View style={styles.container}>
      <TextInput style={styles.input} placeholder="Enter your name" value={name} onChangeText={setName} />
      <TextInput style={styles.input} placeholder="Enter passport number" value={passportNumber} onChangeText={setPassportNumber} />
      <TextInput style={styles.input} placeholder="Enter issuing country" value={docIssueCountry} onChangeText={setDocIssueCountry} />
      <TextInput style={styles.input} placeholder="Enter a reference ID" value={refID} onChangeText={setRefID} />
      <Button title="Start Verification" onPress={startVerification} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: "center",
  },
  input: {
    height: 40,
    borderWidth: 1,
    borderColor: "#ccc",
    borderRadius: 5,
    marginBottom: 10,
    paddingHorizontal: 10,
  },
});

export default PassportScreen;

API Reference

KenalClient

Initializes the SDK with your API key and environment settings.

KenalClient.initialize({
  apiKey: string, // Your Kenal API key
  environment: "sandbox" | "production",
});

Ekyc (Recommended)

Unified service for all document types and AML checks.

Ekyc.startVerification(params)

Starts a new eKYC verification process.

Parameters:

interface EkycStartParams {
  RefID: string;              // Required: Your unique reference ID
  Name?: string;              // Optional/Required based on document type
  IDNumber?: string;          // Optional/Required based on document type
  DocIssueCountry?: string;   // Required for Passport
  Birthdate?: string;         // Optional (YYYY-MM-DD format)
  Nationality?: string;       // Optional
  ArmyNumber?: string;        // Required for MyTentera (if OCR disabled)
}

Returns:

Promise<{
  token: string;     // JWT token for the verification session
  fullURL: string;   // Full URL to open in KenalWebView
}>

Example:

const result = await Ekyc.startVerification({
  RefID: "customer-12345",
  Name: "JOHN DOE",
  IDNumber: "990101011234",
});

Ekyc.generateRecoveryLink(params)

Generates a recovery link for an existing verification session.

Parameters:

interface GenerateRecoveryLinkParams {
  validationId: string;  // Required: Validation ID from previous verification
}

Returns:

Promise<{
  token: string;        // JWT token for the recovery session
  fullURL: string;      // Full URL to resume verification
  expiresAt: number;    // Unix timestamp (seconds) when link expires
}>

Example:

const recovery = await Ekyc.generateRecoveryLink({
  validationId: "0d27685f-cf9d-4790-b22c-b004ba988f37",
});

MyKad (Legacy)

Static service for MyKad verification.

MyKad.start({
  name: string;
  idNumber: string;
  refId?: string;
  useOCRForData?: boolean;
}): Promise<{ fullURL: string }>;

Parameters:

  • name - Full name (required if useOCRForData is false)
  • idNumber - 12-digit MyKad number (required if useOCRForData is false)
  • refId - Your unique reference ID (optional)
  • useOCRForData - Set to true to extract data via OCR (optional, default: false)

Passport (Legacy)

Static service for Passport verification.

Passport.start({
  name: string;
  passportNumber: string;
  docIssueCountry: string;
  refId?: string;
}): Promise<{ fullURL: string }>;

Parameters:

  • name - Full name as on passport (required)
  • passportNumber - Passport number (required)
  • docIssueCountry - Country that issued the passport (required)
  • refId - Your unique reference ID (optional)

KenalWebView

Component for displaying the eKYC verification flow.

<KenalWebView
  url={string}                          // Required: verification URL
  onComplete={(data) => {}}            // Called when verification completes
  onError={(error) => {}}              // Called on error
/>

Props:

  • url (string, required) - The verification URL returned from start methods
  • onComplete (function) - Callback when verification successfully completes
  • onError (function) - Callback when an error occurs