@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-sdkEnsure you have the required peer dependencies:
npm install react-native-webviewFor TypeScript users, install type definitions:
npm install --save-dev @types/react @types/react-nativeUsage
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 ifuseOCRForDatais false)idNumber- 12-digit MyKad number (required ifuseOCRForDatais false)refId- Your unique reference ID (optional)useOCRForData- Set totrueto 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 methodsonComplete(function) - Callback when verification successfully completesonError(function) - Callback when an error occurs
