@veryai/react-native-sdk
v1.0.58
Published
React Native wrapper for Very SDK - Palm biometrics verification
Readme
React Native SDK Integration
Full documentation: https://very.org/docs/native-sdk/integration
Installation
npm install @veryai/react-native-sdkFor iOS, install the native dependency:
cd ios && pod installAdd camera permission to Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is needed for palm biometric verification.</string>Published on npm.
Asset Loading: Bundled vs Slim
The SDK ships with the palm-recognition native asset bundled inside it by default — your app works offline, no first-scan download wait. If you'd rather keep your binary small and have the SDK fetch the asset from CDN on first scan, you can opt into slim mode per platform.
| Mode | Adds to app size | First-scan UX | Works offline | | ------ | ----------------------------------------- | ---------------------------- | ------------- | | Bundled (default) | ~18 MB per ABI (Android), ~8 MB (iOS) | instant | yes | | Slim | nothing | one-time download (5–15 s) | no (first scan only) |
Cached assets persist across app launches; the download only happens once.
iOS — switching to slim
Step 1 — disable RN auto-linking for this package only. Add or edit react-native.config.js at your project root:
module.exports = {
dependencies: {
'@veryai/react-native-sdk': {
platforms: { ios: null },
},
},
};Step 2 — declare the slim subspec explicitly in ios/Podfile inside your app target:
target 'YourApp' do
config = use_native_modules!
use_react_native!(...)
pod 'veryai-react-native-sdk/Core',
:path => '../node_modules/@veryai/react-native-sdk'
endStep 3:
cd ios && pod installTo go back to bundled, delete the react-native.config.js entry and the pod 'veryai-react-native-sdk/Core' line, then pod install again.
Android — switching to slim
In android/app/build.gradle (the app module, not the project root), add:
android {
packaging {
jniLibs {
excludes += '**/libPalmAPISaas.so'
}
}
}This filters the bundled .so out at packaging time. The runtime falls through to CDN download.
Verifying which mode you're in
iOS — after pod install:
grep -c "VerySDK_BundledModel\|packed_data" ios/Pods/Pods.xcodeproj/project.pbxproj
# > 0 → bundled, 0 → slimAndroid — after a build:
unzip -l android/app/build/outputs/apk/debug/app-debug.apk | grep libPalmAPISaas
# matches → bundled, no output → slimCDN endpoints (slim mode)
The SDK tries the primary CDN first and falls back automatically. Allowlist both hostnames if your network has egress restrictions.
| Asset | Primary | Backup |
| -------------------------------- | ------------------------------------------------ | ------------------------------------------------------- |
| Android libPalmAPISaas.so (per ABI) | assets.very.org/sdk/data/<abi>/... | r2.assets.very.org/sdk/v1/<abi>/... |
| iOS packed_data.bin | assets.very.org/sdk/data/packed_data.bin | r2.assets.very.org/sdk/v1/packed_data.bin |
Getting an SDK Key
Native SDK keys are not yet available via the Developer Portal. Contact [email protected] to get your SDK key and client credentials.
Enroll a New User
Pass undefined for userId to register a new user. The SDK opens a consent screen, collects the user's email, then guides them through a palm scan.
import { VerySDK } from "@veryai/react-native-sdk";
const supported = await VerySDK.isSupported();
if (!supported) {
console.warn("Device not supported");
return;
}
const result = await VerySDK.authenticate({
sdkKey: "your_sdk_key",
userId: undefined, // undefined = new enrollment
themeMode: "dark",
presentationStyle: "fullScreen",
});
if (result.isSuccess) {
console.log("Auth code:", result.code);
console.log("User ID:", result.userId);
} else {
console.error("Error:", result.error, result.errorMessage);
}Verify an Existing User
Pass the user's ID from a previous enrollment to verify their identity.
const result = await VerySDK.authenticate({
sdkKey: "your_sdk_key",
userId: "vu-1ed0a927-...", // from previous enrollment
themeMode: "dark",
});
if (result.isSuccess) {
console.log("Verified:", result.code);
}Exchange the Auth Code (Backend)
When authentication succeeds, the SDK returns an authorization code. Send this to your backend, which exchanges it for an id_token:
POST https://api.very.org/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=your_client_id
&client_secret=your_client_secret
&code=AUTH_CODE_FROM_SDK
&redirect_uri=your_redirect_uriResponse:
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJhbGciOi..."
}Decode the id_token JWT to get the user's identity:
{
"iss": "https://connect.very.org",
"sub": "vu-1ed0a927-a336-45dd-9c73-20092db9ae8d",
"aud": ["your_client_id"],
"email": "[email protected]",
"exp": 1761013475,
"iat": 1761009875
}- For enrollment: store the
sub(user ID) — pass it asuserIdfor future verifications - For verification: confirm the
submatches the expected user
Important: The
client_secretfor token exchange must only be stored on your backend. Never embed it in the mobile app.
Configuration Reference
VeryConfig
| Parameter | Type | Default | Description |
| ------------------- | ------- | -------------- | ------------------------------------------------------------------ |
| sdkKey | String | required | Your SDK API key |
| userId | String? | undefined | Undefined for enrollment, user ID for verification |
| language | String? | device | Locale code (e.g. "en", "es", "ja"). 35 languages supported. |
| themeMode | String | "dark" | "dark" or "light" |
| presentationStyle | String | "fullScreen" | "fullScreen" or "bottomSheet". iOS presents modally regardless. |
| livenessMode | String? | "touch" | "gesture" or "touch". iOS only — Android always uses touch. |
| debugLogging | boolean | false | Verbose API request/response logging to the native console. |
Liveness-only flow not wrapped yet. The native SDKs also ship a standalone liveness check (
VeryAILiveness/VeryLivenessConfig) withshowError/showSuccessoptions. The React Native wrapper currently exposes only theauthenticate(palm-auth) flow; surfacing the liveness flow is tracked separately.
VeryResult
| Property | Type | Description |
| -------------- | ------- | ------------------------------------------------------------- |
| isSuccess | boolean | Whether authentication completed successfully |
| code | string | Authorization code to exchange for id_token on your backend |
| userId | string | The user's VeryAI ID |
| signedToken | string? | Signed JWT token (when available) |
| error | string? | Error code string |
| errorMessage | string? | Human-readable error message |
Requirements
- React Native 0.73+
- iOS 13.0+ / Android 6 (API 23)+
- Physical device (no simulator)
- Camera permission
Error Codes
The full list lives in the top-level README. One slim-mode-specific code worth calling out:
| Code | Name | Meaning |
|------|-------------------------------|------------------------------------------------------------------------|
| 6106 | NATIVE_LIB_DOWNLOAD_FAILED | Slim-mode partner: the SDK couldn't fetch the palm asset from CDN. Check internet, CDN allowlist, or revert to bundled mode. |
Use VerySDK.isSupported() to check device compatibility at runtime before showing the verification UI.
Prefetching the palm asset (slim mode)
In slim mode the palm asset is downloaded from CDN on the first scan, which can
add a 5–15s wait. Call VerySDK.prefetch() early — e.g. at app launch — to warm
that download in the background so the first scan is instant. It's
fire-and-forget, safe to call repeatedly, and a no-op in bundled mode or once the
asset is cached. (isSupported() already triggers the same warm-up as a side
effect, so an explicit prefetch() is only needed when you want to start the
download without the support check.)
import { VerySDK } from "@veryai/react-native-sdk";
// e.g. in your app's startup
VerySDK.prefetch();