React Native SDK
Build with

The React Native SDK mirrors the web SDK's core API (same props, same callbacks) but runs on-device, native liveness — Apple Vision on iOS and Google ML Kit on Android, via a react-native-vision-camera v5 (Nitro) frame processor. Because it ships native code, it needs a custom native build and does not run in Expo Go. For shared concepts — supported countries, branding, results, and errors — see Client SDKs.

Feature availability. This SDK (2.0.x) covers the core capture flow. The newer web-SDK features — workflow embedding (workflowId), the capture add-ons (contact OTP, proof of address, questionnaire), business (KYB) verification, and countries beyond NG/GH/KE/ZA/CI — are not in this release yet. See Feature availability. Until parity lands, run those flows via a hosted workflow link or the web SDK.

Requirements
Build with

RequirementMinimum
iOS deployment target15.1
Android minSdkVersion24 (Android 7.0) · compileSdk 34 · NDK 27.1
Expo SDK56 (React 19, React Native 0.85)
React Native0.83+, with the New Architecture enabled (VisionCamera v5 / Nitro requires it; Expo SDK 56 enables it by default)
Build toolchainXcode + CocoaPods (iOS) · JDK 17 for Android Gradle builds
RuntimeA dev client or bare build — not Expo Go

Peer dependencies to install in your app: expo (≥56), react (≥19), react-native (≥0.83), react-native-vision-camera (v5), react-native-vision-camera-worklets (≥5), react-native-worklets (≥0.8), react-native-nitro-modules (≥0.35), react-native-nitro-image (≥0.15), react-native-safe-area-context (≥4), react-native-svg (≥15).

Install
Build with

Pick the path that matches your project.

shell
npx expo install @myazahq/kyc-sdk-react-native \
  react-native-vision-camera react-native-vision-camera-worklets \
  react-native-worklets react-native-nitro-modules react-native-nitro-image \
  react-native-safe-area-context react-native-svg

Add the config plugins to app.json (the SDK plugin adds the iOS camera-usage string and Android CAMERA / INTERNET permissions; the VisionCamera plugin wires up the camera + frame processors), then build a dev client:

json
// app.json
{
  "expo": {
    "plugins": [
      ["react-native-vision-camera", { "enableMicrophonePermission": false }],
      "@myazahq/kyc-sdk-react-native"
    ]
  }
}
shell
npx expo prebuild
npx expo run:ios       # or: npx expo run:android

The SDK plugin accepts an optional custom camera prompt: ["@myazahq/kyc-sdk-react-native", { "cameraPermission": "Your message…" }].

Bare React Native app (no Expo prebuild)

The SDK uses a few expo-* modules, so add the Expo module runtime (you don't need the managed workflow), then install the SDK and its peers:

shell
# 1. One-time: add Expo modules to a bare RN app
npx install-expo-modules@latest

# 2. Install the SDK + peer dependencies
npm install @myazahq/kyc-sdk-react-native \
  react-native-vision-camera react-native-vision-camera-worklets \
  react-native-worklets react-native-nitro-modules react-native-nitro-image \
  react-native-safe-area-context react-native-svg \
  expo expo-image-manipulator expo-image-picker expo-speech expo-font \
  expo-glass-effect expo-application expo-crypto expo-device expo-localization

# 3. iOS pods
cd ios && pod install && cd ..

Then add the native permissions manually (the config plugin only runs under prebuild):

xml
<!-- iOS  ios/<App>/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>We use the camera to photograph your ID and capture a live selfie.</string>
xml
<!-- Android  android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />

The native face-detector module (a VisionCamera v5 Nitro HybridObject plus its Android lib loader) is autolinked — no manual linking. Ensure the New Architecture is enabled and the worklets/frame-processor build is set up per VisionCamera's setup docs (it relies on react-native-worklets / react-native-vision-camera-worklets, installed above).

Voice guidance is text-to-speech output — the SDK never records audio, so no microphone permission is requested or required (enableMicrophonePermission: false).

Usage
Build with

<MyazaKYC /> renders a "Verify Identity" trigger plus the full-screen flow. The API is identical to the web SDK — same props and callbacks.

tsx
import { MyazaKYC } from "@myazahq/kyc-sdk-react-native";

export default function VerifyScreen() {
  return (
    <MyazaKYC
      apiKey="pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      country="NG"
      idTypes={["bvn", "drivers-license", "passport"]}
      userData={{ firstName: "Jane", lastName: "Doe" }}
      enableSelfie
      enableDocumentCapture
      enableLiveness
      showThemeToggle
      appearance={{ primaryColor: "#5645F5", companyName: "Myaza", logo: "default", theme: "light" }}
      consent={{ title: "Welcome, {firstName}", description: "A quick check to confirm it's really you." }}
      success={{ title: "You're all set, {firstName}!", description: "We'll email you once your verification is reviewed." }}
      metadata={{ requestId: "order_1001", userId: "user_42" }}
      onSubmit={(submission) => {
        // The verification was created; status is always 'pending'.
        // Reconcile the final result on your backend via webhook or a secret-key
        // GET /verifications/:id call (never from the client).
        console.log("submitted", submission.verificationId);
      }}
      onError={(err) => console.error(err.code, err.message)}
      onClose={() => console.log("closed")}
    >
      Verify Identity
    </MyazaKYC>
  );
}

Unlike the web SDK there is no stylesheet to import — styling is built in. It accepts the same core props as the web SDK's props table (apiKey, country, idTypes, userData, enableSelfie, enableDocumentCapture, allowDocumentUpload, enableLiveness, voiceGuidance, appearance, consent, success, showThemeToggle, disableClose, metadata, all callbacks) — the web-only rows (workflowId, livenessMode, deviceIntelligence, and the capture add-ons) don't apply here yet. className doesn't apply (React Native has no class names); style the trigger by passing style, or render your own trigger with the hook.

disableClose blocks user dismissal on native too — the iOS swipe-down and the Android back button. Because the built-in <MyazaKYC /> trigger has no external close handle, pair disableClose with the useMyazaKYC() hook and call its close() to dismiss the flow yourself.

Programmatic control
Build with

For a custom trigger, drive the flow with the useMyazaKYC() hook:

tsx
import { useMyazaKYC } from "@myazahq/kyc-sdk-react-native";
import { Pressable, Text } from "react-native";

function Trigger() {
  const { open, close, isOpen, currentStep } = useMyazaKYC({
    apiKey: "pk_test_…",
    country: "NG",
    onSubmit: (s) => console.log(s.verificationId),
  });

  return (
    <Pressable onPress={open} disabled={isOpen}>
      <Text>Verify ({currentStep ?? "idle"})</Text>
    </Pressable>
  );
}

The flow advances through the same KYCStep values as the web SDK: consentid-typeid-inputdocument-capturelivenesssubmitted.