@soyio/soyio-rn-sdk
v6.0.4
Published
Soyio React Native SDK
Readme
Installation
- Install the core SDK using npm (or your favorite package manager)
# Using npm
npm install @soyio/soyio-rn-sdk
# Using yarn
yarn add @soyio/soyio-rn-sdk- You'll also need to install the required peer dependencies:
# Using npm
npm install react-native-webview react-native-inappbrowser-reborn
# Using yarn
yarn add react-native-webview react-native-inappbrowser-rebornThe core package covers:
ConsentBox- WebView disclosure flows
- in-app browser disclosure/authentication flows
- passkey browser flows
If your disclosure flow requires the native FaceTec-backed experience, install the addon as well:
# Using npm
npm install @soyio/soyio-rn-sdk-native-disclosure
# Using yarn
yarn add @soyio/soyio-rn-sdk-native-disclosureThe addon is the only package that bundles the native iOS and Android disclosure implementation, including FaceTec, camera usage, and NFC-specific setup.
iOS Setup
Run cd ios && pod install after installing your dependencies.
- If you install only
@soyio/soyio-rn-sdk, no Soyio-specific camera or NFC permissions are required. - If you also install
@soyio/soyio-rn-sdk-native-disclosure, follow that package's README for camera permissions, NFC entitlements, and native disclosure setup.
Android Setup
For React Native 0.60+, auto-linking should handle Android setup automatically.
- If you install only
@soyio/soyio-rn-sdk, there are no Soyio-specific Android camera or NFC requirements. - If you also install
@soyio/soyio-rn-sdk-native-disclosure, follow that package's README for the additional native disclosure setup.
Deep Link Setup
Add an intent filter in your main <activity> with your chosen scheme. This must match the uriScheme passed to the SDK.
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="your-app-scheme" />
</intent-filter>URI Scheme Setup
You need to configure a custom URI scheme for your application to handle deep linking properly:
npx uri-scheme add custom-uri-schemeReplace custom-uri-scheme with your desired scheme name. This scheme should match the uriScheme parameter you use in the SoyioWidget options. It is essential for the Disclosure and Auth flows to return control to your application once they finish (especially when using the In-App Browser or Passkeys). It is not needed if you are only using the ConsentBox.
Usage
Soyio React Native provides two ways to integrate the Soyio verification flow:
- Component: A
SoyioWidgetcomponent that renders a WebView within your app. - InAppBrowser Functions: Direct functions that open the verification flow in an in-app browser.
ℹ️ Native disclosure / NFC validation is only available when you install
@soyio/soyio-rn-sdk-native-disclosureand integrate with theSoyioWidgetcomponent (WebView). The InAppBrowser mode does not support it.
Component Integration
1. Disclosure Request
A disclosure_request is a process that a user goes through where they are verified, and then they share the necessary data as required by each company.
This verification can happen in one of the following two ways:
Validation: Through document validation and facial video. This occurs when a user has never been verified before with Soyio.
Authentication: Through an access key (passkey) or facial video. This can occur when a user has already been validated previously with Soyio.
To instantiate this process in the code, you have two options:
1.a Disclosure request on-the-fly:
This doesn't require any previous setup. Given your company and disclosure template IDs, you can create disclosure requests freely when the user starts the widget:
import { View, StyleSheet } from "react-native";
import { SoyioWidget } from "@soyio/soyio-rn-sdk";
export default function App() {
const options = {
uriScheme: "<your-app-scheme>", // Required: Your app's URI scheme
companyId: "<company id>", // Optional: Starts with 'com_'
userReference: "<company identifier of user>", // Optional
isSandbox: true, // Optional
};
// For initialize a disclosure request
const disclosureParams = {
templateId: "<template id>", // Starts with 'dtpl_'
userEmail: "<user email>", // Optional
};
const handleSuccess = () => {
console.log("Verification successful!");
};
return (
<View style={styles.container}>
<SoyioWidget
options={options}
requestType="disclosure"
requestParams={disclosureParams}
onSuccess={handleSuccess}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});1.b Created disclosure request:
You can alternatively create a disclosure request beforehand with some matchers to make sure the person completing the request matches the one that your application thinks it is.
For more details about the use case, please refer to the documentation.
To use this option, simply specify the disclosure request ID along with any optional parameters:
import { View, StyleSheet } from "react-native";
import { SoyioWidget } from "@soyio/soyio-rn-sdk";
export default function App() {
const options = {
uriScheme: "<your-app-scheme>", // Required: Your app's URI scheme
isSandbox: false, // Optional
};
// For initialize a disclosure request
const disclosureParams = {
disclosureRequestId: "<disclosure request id>", // Starts with 'dreq_'
};
const handleSuccess = () => {
console.log("Verification successful!");
};
return (
<View style={styles.container}>
<SoyioWidget
options={options}
requestType="disclosure"
requestParams={disclosureParams}
onSuccess={handleSuccess}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});Note that user and template properties are not specified here because they must be specified when creating the disclosure request beforehand.
2. Auth Request
The auth_request is a process where, using a previously created auth_request_id, a request is initiated in which a user can authenticate with Soyio. This authentication can occur either through an access key or facial video.
import { View, StyleSheet } from "react-native";
import { SoyioWidget } from "@soyio/soyio-rn-sdk";
export default function App() {
const options = {
uriScheme: "<your-app-scheme>", // Required: Your app's URI scheme
isSandbox: false, // Optional
};
const authRequestParams = {
authRequestId: "<auth request id>", // Starts with 'authreq_'
};
const handleSuccess = () => {
console.log("Authentication successful!");
};
return (
<View style={styles.container}>
<SoyioWidget
options={options}
requestType="authentication_request"
requestParams={authRequestParams}
onSuccess={handleSuccess}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});3. Consent
A consent is a component that renders a checkbox with a legal text, which the user can check to give their consent to a specific agreement.
import { View, StyleSheet } from "react-native";
import { ConsentBox } from "@soyio/soyio-rn-sdk";
export default function App() {
const options = {
// uriScheme: "<your-app-scheme>", // Not required for consent
isSandbox: true, // Optional
};
const consentParams = {
templateId: "<consent template id>", // Starts with 'constpl_'
// actionToken: "<action token>", // Optional: To restore state
// entityId: "<entity id>", // Optional: To check existing consent
// context: "<context>", // Optional: Additional context
// optionalReconsentBehavior: "notice", // Optional
// mandatoryReconsentBehavior: "notice", // Optional
// allowGranularScopeSelection: true, // Optional
};
const handleEvent = (event) => {
// Check if the event is a consent change
if (event.eventName === 'CONSENT_CHECKBOX_CHANGE') {
console.log('Is Selected:', event.isSelected);
console.log('Action Token:', event.actionToken);
}
};
return (
<View style={styles.container}>
<ConsentBox
options={options}
params={consentParams}
onEvent={handleEvent}
appearance={{ theme: 'soyio', mode: 'dark' }} // Optional: Customize appearance
showSkeleton={true} // Optional: Show loading skeleton (default: true)
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});Consent Events
The onEvent callback receives events with the following structure:
{
eventName: 'CONSENT_CHECKBOX_CHANGE',
isSelected: boolean,
actionToken?: string,
identifier: string
}isSelected: Boolean value indicating whether the consent checkbox is selected.actionToken: Token corresponding to the current state. You can use this to restore the consent state later or validate it server-side.
ConsentBox Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| options | SoyioWidgetConsentOptions | Required | Widget options (uriScheme, isSandbox, etc.) |
| params | ConsentParams | Required | Consent parameters (templateId, etc.) |
| onEvent | (event) => void | - | Callback for consent events |
| appearance | SoyioAppearance | - | Appearance customization |
| showSkeleton | boolean | true | Show loading skeleton while content loads |
| autoHeight | boolean | true | Auto-adjust height based on content |
Consent Attribute Descriptions
templateId: (Required) Identifier of consent template. It must start with'constpl_'.actionToken: (Optional) In case of losing the state of the consent (i.e. app restart), you can use a previously generatedactionTokento restore the state of the consent.entityId: (Optional) Identifier of theentityassociated with aConsentAction. If provided and a consent was previously granted by this entity, the UI will display a message indicating that consent has already been given.context: (Optional) Additional information that will be saved with the consent. Useful when you want to track the consent from a specific context.optionalReconsentBehavior: (Optional) Behavior when consent is already given on an optional category (notice,askAgain,hide).mandatoryReconsentBehavior: (Optional) Behavior when consent is already given on a mandatory category (notice,askAgain).allowGranularScopeSelection: (Optional) Iftrue, users can grant consent for individual scopes (for example products or branches) when the consent template supports multi-scope selection.
4. Customizing Appearance
The ConsentBox (and other components) can be customized to match your application's look and feel using the appearance prop.
Available Themes
| Theme | Description |
|-------|-------------|
| 'soyio' | Default Soyio theme |
| 'flat' | Flat minimal theme |
| 'neutral' | Neutral palette for lighter branding |
| 'night' | Deprecated alias for theme: 'soyio' with mode: 'dark' |
Available Color Modes
| Mode | Description |
|------|-------------|
| 'light' | Forces light mode |
| 'dark' | Forces dark mode |
| 'auto' | Follows the device color scheme |
<ConsentBox
options={options}
params={consentParams}
appearance={{
theme: 'soyio',
mode: 'dark',
variables: {
colorPrimary: '#6366f1',
colorBackground: '#0f172a',
borderRadius: '8px',
},
}}
/>TypeScript Types
import type { SoyioAppearance, SoyioTheme } from '@soyio/soyio-rn-sdk';theme: 'night' is still accepted as a deprecated alias for backwards compatibility, but new integrations should prefer theme + mode.
For a full list of available customization options and examples, please refer to the Appearance Customization Guide.
Loading State
By default, SoyioWidget shows a centered ActivityIndicator while the WebView loads, replacing the blank white screen that would otherwise appear for a few seconds.
You can customize or disable this behavior with the renderLoading prop:
// Default: shows a centered ActivityIndicator (no prop needed)
<SoyioWidget
options={options}
requestType="disclosure"
requestParams={disclosureParams}
/>
// Custom loading UI
<SoyioWidget
options={options}
requestType="disclosure"
requestParams={disclosureParams}
renderLoading={() => (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Loading...</Text>
</View>
)}
/>
// Disable loading overlay entirely
<SoyioWidget
options={options}
requestType="disclosure"
requestParams={disclosureParams}
renderLoading={null}
/>Event Handling
The SoyioWidget component supports the following event handlers:
onSuccess: Called when the verification/authentication process completes successfullyonEvent: Called for widget events (e.g., consent checkbox changes, tooltip state updates)onReady: Called when the webview finishes loading
WebView Link Navigation
When SoyioWidget renders in WebView mode, document links and other links that leave the active widget frame open through the operating system via Linking.openURL. This keeps privacy document PDFs in the browser or system viewer instead of replacing the widget content.
InAppBrowser Integration
For cases where you prefer to open the verification flow in an in-app browser instead of a WebView, you can use the direct function approach.
1. Disclosure Request (InAppBrowser)
1.a Disclosure request on-the-fly:
import { openDisclosure } from "@soyio/soyio-rn-sdk";
const handleDisclosure = async () => {
const options = {
uriScheme: "<your-app-scheme>", // Required: Your app's URI scheme
companyId: "<company id>", // Optional: Starts with 'com_'
userReference: "<company identifier of user>", // Optional
isSandbox: true, // Optional
};
const disclosureParams = {
templateId: "<template id>", // Starts with 'dtpl_'
userEmail: "<user email>", // Optional
};
await openDisclosure({
options,
requestParams: disclosureParams,
onComplete: () => console.log("Disclosure completed successfully!"),
onCancel: () => console.log("Disclosure was cancelled by user"),
});
};1.b Created disclosure request:
import { openDisclosure } from "@soyio/soyio-rn-sdk";
const handleDisclosure = async () => {
const options = {
uriScheme: "<your-app-scheme>", // Required: Your app's URI scheme
isSandbox: false, // Optional
};
const disclosureParams = {
disclosureRequestId: "<disclosure request id>", // Starts with 'dreq_'
};
await openDisclosure({
options,
requestParams: disclosureParams,
onComplete: () => console.log("Disclosure completed successfully!"),
onCancel: () => console.log("Disclosure was cancelled by user"),
});
};2. Auth Request (InAppBrowser)
import { openAuthenticationRequest } from "@soyio/soyio-rn-sdk";
const handleAuthRequest = async () => {
const options = {
uriScheme: "<your-app-scheme>", // Required: Your app's URI scheme
isSandbox: false, // Optional
};
const authRequestParams = {
authRequestId: "<auth request id>", // Starts with 'authreq_'
};
await openAuthenticationRequest({
options,
requestParams: authRequestParams,
onComplete: () => console.log("Authentication completed successfully!"),
onCancel: () => console.log("Authentication was cancelled by user"),
});
};Event Handling (InAppBrowser)
The InAppBrowser functions support the following callback handlers:
onComplete: Called when the verification/authentication process completes successfullyonCancel: Called when the user cancels the process or navigates away
Attribute Descriptions
uriScheme: (Required for Disclosure and Auth) The URI scheme for your application. It is used to return control to your app after completing the flow in an In-App Browser or when using external authentication flows like Passkeys. The monolith uses this scheme to build the redirect URL (e.g.,<your-app-scheme>://success) when the verification process finishes. Not used in theConsentBox.companyId: (Optional) The unique identifier for the company, must start with'com_'.userReference: (Optional) A reference identifier provided by the company for the user engaging with the widget. This identifier is used in events (onEventandwebhooks) to inform the company which user the events are associated with.userEmail: (Optional) The user's email address.templateId: (Required for new disclosure requests) Identifier of template. Specifies the order and quantity of documents requested from the user, as well as the mandatory data that the user is asked to share with the company. It must start with'dtpl_'.isSandbox: (Optional) Indicates if the widget should operate in sandbox mode, defaulting tofalse.developmentUrl: (Optional) Custom development URL for testing purposes.authRequestId: (Required for authentication requests) Identifier of auth request obtained when creating theAuthRequest. It must start with'authreq_'.disclosureRequestId: (Required for existing disclosure requests) Identifier of an existing disclosure request. It must start with'dreq_'.
TypeScript support
This package includes TypeScript declarations.
Development & Testing
1. Installation
To develop the package, use yarn to install dependencies:
yarn install2. Building
Build the package using:
yarn build # Runs both ESM and CJS builds3. Smoke Testing / Local Development
This repo includes a React Native app under example/app to smoke test the SDK during development.
- Install the example app dependencies:
cd example/app yarn install - (Optional) Use the helper script:
yarn smoke:setup - Replace the placeholder IDs in
example/app/App.tsx. - Run the platform helper scripts if you prefer:
yarn smoke:ios yarn smoke:android
iOS
- Install pods:
cd example/app/ios bundle install bundle exec pod install - Run the app:
cd .. yarn ios
Android
- Ensure you have an emulator or device running.
- JDK 17 is required for Android builds.
- Run the app:
yarn smoke:android
Notes:
- The app pulls the SDK from
file:../.., so local changes are reflected immediately. - Metro is configured to watch the repo root (
example/app/metro.config.js).
