React Native integration
This guide describes SDK installation in your React Native application, followed by photo capture and upload. See the overview to obtain the package, SDK key and environment URLs.
Prerequisites
- React Native 0.72 or later, with its Android and iOS build tools.
- CocoaPods for iOS installation, and Xcode for signing and running on a device.
- A physical device to validate the production workflow.
- The
certificall-mobile-sdk-react-native-<version>.tgzpackage provided by Certificall.
With Expo, use a development build (expo prebuild). Expo Go cannot load the SDK.
1. Install the package
Copy the delivered file to vendor/, then declare the dependency:
{
"dependencies": {
"certificall-mobile-sdk-react-native": "file:./vendor/certificall-mobile-sdk-react-native-<version>.tgz"
}
}
npm install
The package contains the native iOS and Android SDK. No special .npmrc or Metro configuration is needed for the .tgz package.
2. Configure iOS
React Native autolinking detects the module. Install pods from the iOS directory:
cd ios
pod install
If autolinking does not detect the module, add this declaration to your Podfile, then run pod install again:
pod 'CertificallTrustRN', :path => '../node_modules/certificall-mobile-sdk-react-native'
Add usage descriptions to Info.plist:
<key>NSCameraUsageDescription</key>
<string>Required to capture certified photos.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Required to certify the photo's location.</string>
<key>NSMotionUsageDescription</key>
<string>Required to collect motion during capture.</string>
Capture does not require photo library permission. In Xcode, select your application's Team and Bundle Identifier under Signing & Capabilities, then rebuild the application.
3. Configure Android
Autolinking registers the module. The bridge includes the android/libs/certificall-trust-sdk.aar binary and declares its native dependencies in Gradle.
If your setup does not use autolinking, add CertificallTrustPackage to the package list in MainApplication.kt:
import com.certificall.reactnative.CertificallTrustPackage
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply { add(CertificallTrustPackage()) }
Declare permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
The SDK includes its own file provider and the declarations needed to detect the camera. You do not need to declare a FileProvider for the SDK.
Rebuild the application after installation:
npx react-native run-android
4. Request permissions and configure the SDK
On iOS, use the SDK helpers. On Android, use PermissionsAndroid: the SDK's request*Permission() helpers are iOS-only.
Request permissions before configuration, which starts position and motion collection. This example initializes the workflow after camera and location access have been granted.
import { PermissionsAndroid, Platform } from 'react-native';
import { CertificallTrust } from 'certificall-mobile-sdk-react-native';
export async function prepareCapture(): Promise<boolean> {
if (Platform.OS === 'android') {
const permissions = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.CAMERA,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
]);
const granted = PermissionsAndroid.RESULTS.GRANTED;
if (
permissions[PermissionsAndroid.PERMISSIONS.CAMERA] !== granted ||
permissions[PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION] !== granted
) {
return false;
}
} else {
const cameraGranted = await CertificallTrust.requestCameraPermission();
const location = await CertificallTrust.requestLocationPermission();
await CertificallTrust.requestMotionPermission();
if (!cameraGranted || location !== 'granted') return false;
}
await CertificallTrust.configure({
apiKey: '<your SDK API key>',
baseUrl: 'https://dev.certificall.app/certificall/',
appVersion: '1.0.0',
});
return true;
}
Call this preparation when your screen opens, then wait for the user's action to take the photo. appVersion is the version of your application, not the SDK.
5. Capture, then upload
import { CertificallTrust } from 'certificall-mobile-sdk-react-native';
const photo = await CertificallTrust.takePhoto({
reportToken: 'JOB-2026-001',
metadata: { site: 'Paris', zone: 'A1' },
});
// Save this JSON to your storage before upload if the capture
// must survive the application being closed.
const serializedPhoto = JSON.stringify(photo);
const sent = await CertificallTrust.sendPhoto(photo);
console.log('Case:', sent.caseId);
console.log('PDF certificate:', sent.pdfUrl);
console.log('Warnings:', sent.warnings);
The serializedPhoto variable alone is not persistent storage. You can read the saved JSON and pass it to sendPhoto() without taking another photo. See Storage and retries.
The trust score is provided by the analysis result webhook.
API surface
Methods are exposed on CertificallTrust.
| Method | Return value | Use |
|---|---|---|
configure({ apiKey, baseUrl?, appVersion? }) | Promise<void> | Configure and start collection. |
takePhoto({ reportToken?, metadata? }?) | Promise<CapturedPhoto> | Local capture with its signals. |
sendPhoto(photo) | Promise<SentPhoto> | Upload and certification. |
isDebugBuild() | Promise<boolean> | Application build type. |
requestCameraPermission() | Promise<boolean> | Camera permission, iOS-only. |
requestLocationPermission() | Promise<string> | Location permission, iOS-only. |
requestMotionPermission() | Promise<boolean> | Request motion permission, iOS-only. |
getNetworkStatus() | Promise<{ connected, connectionType }> | Current network status. |
startNetworkMonitoring(callback) | { remove() } | Network change notifications. |
getCurrentPosition() | Promise<LocationPosition> | Current position. |
watchPosition(callback) | { remove() } | Position monitoring. |
getCurrentMotion() | Promise<MotionData> | Current motion. |
watchMotion(callback) | { remove() } | Motion monitoring. |
getDeviceSnapshot({ includeLocation?, includeMotion? }?) | Promise<DeviceSnapshot> | Device snapshot. |
To stop a network, position or motion subscription, call its remove() method. A connected network does not guarantee a successful upload: also handle sendPhoto() errors.
Read an error
Capture and upload errors carry a code. Additional information is in userInfo:
try {
const photo = await CertificallTrust.takePhoto();
// Save the capture before upload.
await CertificallTrust.sendPhoto(photo);
} catch (error) {
const failure = error as {
code?: string;
userInfo?: { reasons?: string[]; status?: number; reason?: string };
};
if (failure.code === 'CAPTURE_CANCELLED') {
// The user closed the camera: nothing was uploaded.
} else {
console.log(failure.code, failure.userInfo);
}
}
The error reference describes device refusals and retry conditions.
Troubleshooting
| Symptom | Check |
|---|---|
| JavaScript module not found | Check the .tgz path in package.json, run npm install again, then restart Metro. |
CertificallTrust native module is not linked | Install pods and rebuild the native application. Check that you are not using Expo Go. |
| Podspec not detected | Check CertificallTrustRN.podspec in the installed package and the Podfile declaration. |
| Android permission not requested | Use PermissionsAndroid, before configure(). |
NOT_INITIALIZED | Wait for configure() to resolve before capture or upload. |
DEVICE_NOT_TRUSTED | Read userInfo.reasons and device checks. |
SERVER_REJECTED without a case result | Check the key, environment, baseUrl suffix and HTTP status. |
| Development photo rejected | Send it to pre-production; for production, take a new photo with a distribution build. |