Welcome to DGVerify
DGVerify provides a modern identity verification journey with face verification, document verification, and clear final outcomes for partner applications across multiple mobile platforms.
Explore More →DGVerify Home
Understand how your verification system works and why this solution is provided for partner onboarding.
01 Why We Provide This Solution
- Provide a single verification journey with both facial and document checks.
- Support country-wise document setup so partners can verify only required document types.
- Give a consistent SDK experience across Android, iOS, Flutter, and React Native.
- Return a clear final decision to partner apps: Accepted or Failed.
02 How Your System Works
DGVerify SDK
A cross-platform WebView SDK for embedding the Digipay electronic Know Your Customer (eKYC) verification flow directly into your mobile application. Available for Android, iOS, Flutter, and React Native.
01 Overview
The DGVerify SDK abstracts away the complexity of identity verification. You supply your credentials (or a pre-built verification_url from your backend), and the SDK handles authentication, session initiation, and loading the KYC flow inside a secure in-app WebView. The hosted page handles all document capture, liveness checks, and result handling.
POST /auth/authenticate — Exchange client credentials for a bearer token.POST /ekyc/initiate_verification_process — Create a session and receive a verification_url.verification_url in its own managed in-app WebView. The hosted page handles identity capture and completion.02 Choose Your Platform
Select the SDK for your mobile platform to get started:
webview_flutter. Works on Android and iOS targets..tgz package. KycSdkModal with react-native-webview.03 Integration Modes
All platforms support two integration modes:
| Mode | How it works | Best for |
|---|---|---|
| Credentials mode | App holds Digipay credentials. SDK calls authenticate + initiate internally. | Development, testing, simple setups |
| URL mode | Your backend calls authenticate + initiate and returns verification_url to the app. SDK only loads the URL. |
Production — secrets never leave the server |
verification_url to the mobile app.How It Works
End-to-end system workflow for onboarding, workflow setup, and user verification journey.
01 Digipay Team Configuration
- Contact the Digipay team and request country configuration for your project.
- Share your required verification document list country-wise (for example, Passport, National ID, Driving License).
- Digipay enables only the selected document types for each configured country.
02 Create Your Verification Workflow
From the workflow section, create a new workflow and configure the required services.
- Select Facial Verification.
- Select Document Verification.
- Choose the document types that were configured for your target country.
03 Workflow Diagram
Partner Team DGVerify Team SDK User Journey
│ │ │
│ Request country setup │ │
│─────────────────────────────────────▶│ │
│ Share country-wise document list │ │
│─────────────────────────────────────▶│ │
│ │ Configure country + docs │
│ │────────────────────────────────────▶│
│ │ │
│ Create workflow in console: │ │
│ Facial + Document Verification │ │
│─────────────────────────────────────▶│ │
│ │ │
│ │ │ Start SDK flow
│ │ │───────────────▶
│ │ │ Face verification (pass)
│ │ │───────────────▶
│ │ │ Show configured docs
│ │ │───────────────▶
│ │ │ Upload one document
│ │ │───────────────▶
│ │ Process verification │
│ │◀────────────────────────────────────│
│ Result received in SDK: │ │
│ Accepted / Failed │ │
│◀─────────────────────────────────────│ │
04 End User Journey in SDK
DigipayConfig
The configuration object used across all platforms to supply credentials and session parameters to the SDK.
01 Fields
clientId:clientSecret, Base64-encode the result, and prefix with Basic .user_id in the initiate request. Must be a non-blank string that your app supplies (e.g., a customer ID from your session). The SDK does not generate this value.02 Helper: fromCredentials
All platforms provide a fromCredentials helper that builds DigipayConfig from a raw clientId and clientSecret, handling the Base64 encoding of the Basic auth header for you.
// Android / Kotlin
val config = DigipayConfig(
baseUrl = "https://your-api.example.com/digipay/v3/",
basicAuthHeader = "Basic <base64(clientId:clientSecret)>",
companyId = "<company-id>",
apiKey = "<api-key>",
kycWfNumber = "<workflow-number>",
callbackUrl = "https://your-callback.example.com/ekyc",
userId = "<end-user-id>"
)
Android Integration
Drop-in AAR library. Pass credentials or a verification_url; the SDK handles auth, initiation, and opens the flow in a full-screen WebView Activity.
| Property | Value |
|---|---|
| Artifact | kyc-sdk-release.aar |
| Entry point | com.digipay.ekyc.KycSdk |
| Config type | com.digipay.ekyc.DigipayConfig |
| Min SDK | API 24 (Android 7.0) |
| Compile SDK | 35 (recommended) |
| Kotlin | 1.9+ / 2.x |
| AGP | 8.x |
01 Add the AAR
Copy kyc-sdk-release.aar into your app module's libs/ directory:
your-app/
└── app/
├── libs/
│ └── kyc-sdk-release.aar ← place here
├── src/
└── build.gradle.kts
:ekyc module under ekyc/libs/. This keeps Digipay wiring isolated. See §5 below.02 Gradle Setup
Transitives are not bundled inside the AAR — you must declare them in your app/build.gradle.kts:
android {
defaultConfig { minSdk = 24 }
buildFeatures { buildConfig = true }
}
dependencies {
implementation(files("libs/kyc-sdk-release.aar"))
// Required transitive dependencies
implementation("androidx.core:core-ktx:1.15.0")
implementation("androidx.activity:activity-ktx:1.9.3")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.google.code.gson:gson:2.11.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
implementation("androidx.appcompat:appcompat:1.7.0")
}
03 Secrets via local.properties
Store Digipay credentials in the root local.properties (gitignored) and expose them as BuildConfig fields. You can use either a prebuilt DIGIPAY_BASIC_AUTH header or raw DIGIPAY_CLIENT_ID + DIGIPAY_CLIENT_SECRET.
# local.properties (do not commit)
DIGIPAY_BASE_URL=https://your-api.example.com/digipay/v3/
DIGIPAY_CLIENT_ID=<your-client-id>
DIGIPAY_CLIENT_SECRET=<your-client-secret>
DIGIPAY_COMPANY_ID=<company-id>
DIGIPAY_API_KEY=<api-key>
DIGIPAY_KYC_WF_NUMBER=<workflow-number>
DIGIPAY_CALLBACK_URL=https://your-callback.example.com/ekyc
DIGIPAY_USER_ID=your-end-user-id
If your team already has a prebuilt header, you may keep using DIGIPAY_BASIC_AUTH instead of DIGIPAY_CLIENT_ID/DIGIPAY_CLIENT_SECRET.
// app/build.gradle.kts — expose as BuildConfig fields
import java.util.Properties
val lp = Properties().apply {
rootProject.file("local.properties").takeIf { it.exists() }
?.inputStream()?.use { load(it) }
}
android {
defaultConfig {
buildConfigField("String", "DIGIPAY_BASE_URL", "\"${lp["DIGIPAY_BASE_URL"]}\"")
buildConfigField("String", "DIGIPAY_CLIENT_ID", "\"${lp["DIGIPAY_CLIENT_ID"]}\"")
buildConfigField("String", "DIGIPAY_CLIENT_SECRET","\"${lp["DIGIPAY_CLIENT_SECRET"]}\"")
buildConfigField("String", "DIGIPAY_COMPANY_ID", "\"${lp["DIGIPAY_COMPANY_ID"]}\"")
buildConfigField("String", "DIGIPAY_API_KEY", "\"${lp["DIGIPAY_API_KEY"]}\"")
buildConfigField("String", "DIGIPAY_KYC_WF_NUMBER","\"${lp["DIGIPAY_KYC_WF_NUMBER"]}\"")
buildConfigField("String", "DIGIPAY_CALLBACK_URL","\"${lp["DIGIPAY_CALLBACK_URL"]}\"")
buildConfigField("String", "DIGIPAY_USER_ID", "\"${lp["DIGIPAY_USER_ID"]}\"")
}
}
04 Launch the SDK
launchWebWorkflow is a suspending function — call it from a coroutine scope.
import com.digipay.ekyc.DigipayConfig
import com.digipay.ekyc.KycSdk
val config = DigipayConfig.fromCredentials(
baseUrl = BuildConfig.DIGIPAY_BASE_URL,
clientId = BuildConfig.DIGIPAY_CLIENT_ID,
clientSecret = BuildConfig.DIGIPAY_CLIENT_SECRET,
companyId = BuildConfig.DIGIPAY_COMPANY_ID,
apiKey = BuildConfig.DIGIPAY_API_KEY,
kycWfNumber = BuildConfig.DIGIPAY_KYC_WF_NUMBER,
callbackUrl = BuildConfig.DIGIPAY_CALLBACK_URL,
userId = currentUser.id // your end-user id
)
lifecycleScope.launch {
try {
KycSdk.launchWebWorkflow(this@MyActivity, config)
} catch (t: Throwable) {
// handle auth failure or network error
}
}
// Backend already supplies verification_url — no DigipayConfig needed
val url = myBackend.createEkycSession(userId)
lifecycleScope.launch {
KycSdk.launchWebWorkflow(this@MyActivity, url)
}
@Composable
fun StartKycButton(config: DigipayConfig) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
runCatching { KycSdk.launchWebWorkflow(context, config) }
.onFailure { /* show error state */ }
}
}) { Text("Start KYC") }
}
05 Network Security (Dev / HTTP)
For non-HTTPS (development) verification URLs, add a Network Security Config rather than blanket cleartext:
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">your.dev.host</domain>
</domain-config>
</network-security-config>
Reference it in AndroidManifest.xml: android:networkSecurityConfig="@xml/network_security_config". Do not use cleartext in production.
WebChromeClient.onPermissionRequest, and Android runtime camera permission handling.06 Recommended: Separate :ekyc Module
Isolate all Digipay wiring in a dedicated library module to keep your :app module clean:
// ekyc/src/.../DigipayKycModule.kt
object DigipayKycModule {
fun configForUser(userId: String) = DigipayConfig.fromCredentials(
baseUrl = BuildConfig.DIGIPAY_BASE_URL,
clientId = BuildConfig.DIGIPAY_CLIENT_ID,
clientSecret = BuildConfig.DIGIPAY_CLIENT_SECRET,
companyId = BuildConfig.DIGIPAY_COMPANY_ID,
apiKey = BuildConfig.DIGIPAY_API_KEY,
kycWfNumber = BuildConfig.DIGIPAY_KYC_WF_NUMBER,
callbackUrl = BuildConfig.DIGIPAY_CALLBACK_URL,
userId = userId
)
suspend fun launch(context: Context, userId: String) =
KycSdk.launchWebWorkflow(context, configForUser(userId))
suspend fun launch(context: Context, verificationUrl: String) =
KycSdk.launchWebWorkflow(context, verificationUrl)
}
// From any Activity in :app
lifecycleScope.launch {
runCatching { DigipayKycModule.launch(this@MainActivity, userId) }
.onFailure { /* show error */ }
}
iOS Integration
Swift SDK delivered as an XCFramework. Presents the eKYC flow inside a WKWebView-based modal view controller from any UIViewController.
| Property | Value |
|---|---|
| Binary artifact | DigipayEkycSDK.xcframework |
| Swift module | DigipayEkycSDK |
| Entry API | KycSdk |
| Config type | DigipayConfig |
| Minimum iOS | iOS 14+ |
01 Add the XCFramework
- Drag
DigipayEkycSDK.xcframeworkinto the Xcode project navigator. - In the app target → General → Frameworks, Libraries, and Embedded Content: set Embed & Sign.
- In any Swift source file that uses the SDK:
import DigipayEkycSDK.
02 Info.plist — Camera & Microphone
The KYC flow typically requires camera access (and sometimes microphone). Add usage descriptions to your app's Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is required for identity verification.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access may be required during verification.</string>
03 Integration Helper File
Keep all Digipay-specific wiring in a single dedicated Swift file in your app target (not inside the SDK package). Collect a unique clientId + clientSecret from each client and pass them into fromCredentials:
// DigipayKycIntegration.swift — add to your app target only
import UIKit
import DigipayEkycSDK
enum DigipayKycIntegration {
private static func makeConfig() throws -> DigipayConfig {
try DigipayConfig.fromCredentials(
baseURL: "https://your-api.example.com/digipay/v3/",
clientId: "your-client-id",
clientSecret: "your-client-secret",
companyId: "your-company-id",
apiKey: "your-api-key",
kycWorkflowNumber: "your-kyc-wf-number",
userId: "your-end-user-id",
callbackURL: "https://your-callback.example.com/ekyc"
)
}
// Credentials mode
@MainActor
static func startKyc(from presenter: UIViewController) {
Task {
do {
let config = try makeConfig()
try await KycSdk.launchWebWorkflow(from: presenter, config: config)
} catch {
print("Digipay KYC failed:", error.localizedDescription)
}
}
}
// URL mode (recommended for production)
@MainActor
static func startKyc(from presenter: UIViewController, verificationURL: String) {
do {
try KycSdk.launchWebWorkflow(from: presenter, verificationURL: verificationURL)
} catch {
print("Digipay KYC failed:", error.localizedDescription)
}
}
}
Call from any screen:
// Credentials mode
DigipayKycIntegration.startKyc(from: self)
// URL mode — backend supplies the URL
let url = await myBackend.createEkycSession()
DigipayKycIntegration.startKyc(from: self, verificationURL: url)
04 App Lifecycle Notes
| Setup | What to do |
|---|---|
| UIKit + AppDelegate | Call KycSdk.launchWebWorkflow(...) from any view controller. No required AppDelegate changes. |
| UIKit + SceneDelegate | Launch from a view controller in the active scene — not from a standalone AppDelegate call. |
| SwiftUI | Obtain a UIViewController (e.g. via UIHostingController root or key window rootViewController) and pass it to launchWebWorkflow(from:). |
UIApplication.shared.open(...) to open the verification_url — this opens Safari externally. Always use KycSdk.launchWebWorkflow to keep the flow inside the SDK WebView.Flutter Integration
Dart package that mirrors the native SDK flow using webview_flutter for the in-app WebView. Supports Android and iOS targets.
| Property | Value |
|---|---|
| Package name | digipay_flutter_kyc_sdk |
| Import | package:digipay_flutter_kyc_sdk/flutter_sdk.dart |
| Flutter SDK | ≥ 3.10.0 |
| Dart SDK | ≥ 2.19.0 < 4.0.0 |
| Key dependencies | http, webview_flutter (transitive) |
01 Install
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
digipay_flutter_kyc_sdk:
path: ../flutter-sdk # relative path to SDK folder
dependencies:
digipay_flutter_kyc_sdk:
git:
url: https://github.com/your-org/flutter-sdk.git
ref: main
dependencies:
digipay_flutter_kyc_sdk: ^1.0.0
Then run:
flutter pub get
02 Launch the SDK
import 'package:digipay_flutter_kyc_sdk/flutter_sdk.dart';
final config = fromCredentials(
baseUrl: 'https://your-api.example.com/digipay/v3/',
clientId: '<your-client-id>',
clientSecret: '<your-client-secret>',
companyId: '<company-id>',
apiKey: '<api-key>',
kycWfNumber: '<workflow-number>',
callbackUrl: 'https://your-callback.example.com/ekyc',
userId: '<end-user-id>',
);
// In a button handler where BuildContext is available:
await launchWebWorkflowWithConfig(context, config);
final url = await myApi.createEkycSession();
await launchWebWorkflow(context, url);
// Push as a full-screen route — config mode
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => KycSdkSheet(config: config),
),
);
// Or with a pre-built URL from your backend
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => KycSdkSheet(verificationUrl: urlFromBackend),
),
);
verification_url with url_launcher, launchUrl(), or the system browser. Always use launchWebWorkflow, launchWebWorkflowWithConfig, or KycSdkSheet to keep the eKYC flow inside the SDK-owned WebView.NSCameraUsageDescription (plus microphone if needed) with WKWebView media permission support.03 Public API
| Export | Description |
|---|---|
fromCredentials(...) | Build DigipayConfig from raw clientId/clientSecret. |
fetchVerificationUrl(config, options:) | Fetch verification_url without opening the WebView (advanced use). |
launchWebWorkflow(context, url) | Open a pre-built URL in the SDK WebView. |
launchWebWorkflowWithConfig(context, config, options:) | Full credentials mode — authenticate, initiate, then open WebView. |
KycSdkSheet | Widget for pushing as a full-screen MaterialPageRoute. |
React Native Integration
npm package distributed as a .tgz tarball. Uses KycSdkModal with react-native-webview for the in-app verification flow.
| Property | Value |
|---|---|
| Package name | @digipay/react-native-kyc-sdk |
| Distribution | digipay-react-native-kyc-sdk-1.1.0.tgz |
| Peer: React | ≥ 18.0.0 |
| Peer: React Native | ≥ 0.71.0 |
| Peer: WebView | react-native-webview ≥ 13.0.0 |
01 Install
Place the tarball next to your package.json, then install:
# Yarn
yarn add ./sdk/digipay-react-native-kyc-sdk-1.1.0.tgz
yarn add react-native-webview
# npm
npm install ./sdk/digipay-react-native-kyc-sdk-1.1.0.tgz
npm install react-native-webview
iOS: Run pod install from the ios/ directory and rebuild.
Android: Sync Gradle and rebuild. react-native-webview autolinks on modern React Native.
02 Integration — KycSdkModal
import React from "react";
import { Button, View } from "react-native";
import { KycSdkModal, fromCredentials, type DigipayConfig } from "@digipay/react-native-kyc-sdk";
export function KycScreen() {
const [open, setOpen] = React.useState(false);
const config: DigipayConfig = fromCredentials({
baseUrl: "https://your-api.example.com/digipay/v3/",
clientId: "<your-client-id>",
clientSecret: "<your-client-secret>",
companyId: "<company-id>",
apiKey: "<api-key>",
kycWfNumber: "<workflow-number>",
callbackUrl: "https://your-callback.example.com/ekyc",
userId: "<end-user-id>",
});
return (
<View style={{ flex: 1 }}>
<Button title="Start KYC" onPress={() => setOpen(true)} />
<KycSdkModal
visible={open}
onRequestClose={() => setOpen(false)}
config={config}
/>
</View>
);
}
// Backend supplies verification_url — DigipayConfig is not needed
<KycSdkModal
visible={open}
onRequestClose={() => setOpen(false)}
verificationUrl={urlFromBackend}
/>
03 DigipayConfig Type
type DigipayConfig = {
baseUrl: string;
basicAuthHeader: string; // "Basic <base64(clientId:clientSecret)>"
companyId: string;
apiKey: string;
kycWfNumber: string;
callbackUrl: string;
userId: string; // required for initiate; sent as user_id
};
04 Optional Helpers
| API | When to use |
|---|---|
fromCredentials(...) | Build DigipayConfig from raw clientId/clientSecret. |
fetchVerificationUrl(config, options?) | Fetch URL in JS without opening UI, then pass to KycSdkModal as verificationUrl. |
launchWebWorkflow(url) | Opens flow via Linking.openURL (external browser). Not recommended for production UX — use KycSdkModal instead. |
Info.plist camera permission with WKWebView media support.API Reference
API Reference is divided into 3 parts: Authentication, Initiate EKYC, and ID Verification.
01 Authentication
POST : http://<base_url>/digipay/v3/auth/authenticate
Basic Auth:
Digipay provides authorization through Basic Auth header. Your Client ID serves as username and Secret Key serves as password. This header is required for API requests.
Headers
| Parameter | Type | Description |
|---|---|---|
UserName | String | Enter Client ID as username |
Password | String | Enter Secret Key as password |
Response 200 (OK)
{
"status_code": 200,
"data": {
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJlMzgyYzEzMGFlOGU0YmRmYWIyZjg4ZTE0YjZjMTlhOSIsInJvbGVzIjpbIlJPTEVfTUVSQ0hBTlQiXSwiZXhwIjoxNzA2MTAwNTE4fQ.fYvleRbfU0kTo2DXK3nc_Kz2uCspiauU5G-PqsQIrio",
"expiry_time": "2024-01-24 18:18:38"
}
}
access_token : token returned if the client is verified
expiry_time : expiry time of token
Response 400 (BAD REQUEST)
{
"success": 0,
"error": [1],
"data": {
"message": "BAD_REQUEST"
}
}
Responses
| Status Code | Description |
|---|---|
200 | OK |
400 | Bad Request |
404 | Not Found |
500 | Internal Server Error |
02 Initiate EKYC
POST : http://<base_url>/digipay/v3/ekyc/initiate_verification_process
This API is used to initiate eKYC verification process.
Body Params
| Parameter | Type | Description | Value |
|---|---|---|---|
kyc_wf_number | String | KYC workflow number for eKYC flow | card_ke1 |
device_info | Json | Device metadata | "device_type": 1 |
callback_url | String | Callback URL for eKYC result | demo.digipay.com |
redirection_url | String | Redirect URL to origin | demo.digipay.com |
Headers
| Parameter | Type | Description | Value |
|---|---|---|---|
Authorization | String | Token to authenticate user request | Token duik7309njdlkhdauhknksadhjkas986876sd873j |
CompanyID | String | Unique primary company id | 76bc712200ca444fa334f9e55e5fd7a8 |
Request Example
curl --request POST \
--url https://192.168.1.102/digipay/v3/ekyc/initiate_verification_process \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"kyc_wf_number": "card_ke1",
"device_info": {
"device_type": 1,
"device_key": "metadata"
},
"callback_url": "demo.digipay.com",
"redirection_url": "demo.digipay.com"
}'
Response 200 (OK)
{
"success": 1,
"error": [],
"data": {
"verification_url": "https://identity.digipay.guru/",
"verification_id": "4f5b616193784835b979c788d9ef5226"
}
}
Response 400 (BAD REQUEST)
{
"success": 0,
"error": [1],
"data": {
"message": "BAD_REQUEST"
}
}
Responses
| Status Code | Description |
|---|---|
200 | OK |
400 | Bad Request |
404 | Not Found |
500 | Internal Server Error |
03 ID Verification
GET : http://<base_url>/digipay/v3/ekyc/id_verifications/{id}
Get user detail for which eKYC is completed.
Path Params
| Parameter | Type | Description | Value |
|---|---|---|---|
id | String | Primary key of id_verification received in initiate verification API | 1234 |
Headers
| Parameter | Type | Description | Value |
|---|---|---|---|
Authorization | String | Token to authenticate user request | Token duik7309njdlkhdauhknksadhjkas986876sd873j |
CompanyID | String | Unique primary company id | 76bc712200ca444fa334f9e55e5fd7a8 |
Response 200 (OK)
{
"success": 1,
"error": [],
"data": {
"id_verifications": {
"is_active": true,
"created_by": "65f4d2509bfe450fa8815a559697bc47",
"created_date": 1698643150,
"updated_by": null,
"updated_date": 1698643150,
"id": "d4e8890a3339449ba72e769ca6ac01cc",
"reference_number": "1698643150",
"user_id": "5465dsf1213235dfsf",
"full_name": "ABC",
"selfie_image": null,
"birth_date": 54154546,
"first_name": null,
"middle_name": "jds",
"last_name": "fdldff",
"age": 16,
"nationality": "dfsdfs",
"email": "email.com",
"verification_mode": "dff",
"allow_na": true,
"callback_url": "dfskljdfs",
"redirect_url": "dfskjdf",
"verification_type": null,
"offline_allowed": "true",
"online_allowed": "true",
"status": 1,
"reject_reason": null,
"device_info": null
}
}
}
Response 400 (BAD REQUEST)
{
"success": 0,
"error": [1],
"data": {
"message": "BAD_REQUEST"
}
}
Responses
| Status Code | Description |
|---|---|
200 | OK |
400 | Bad Request |
404 | Not Found |
500 | Internal Server Error |
Security Guidance
Best practices for securely integrating the DGVerify SDK in production applications.
01 Use URL Mode in Production
The single most impactful security measure is keeping your Digipay credentials on the server:
clientId, clientSecret, companyId, apiKey. It calls /auth/authenticate and /ekyc/initiate_verification_process.verification_url02 Never Hardcode Credentials
clientId, clientSecret, apiKey) to source control — not even in test branches. Use local.properties on Android, xcconfig files on iOS, or environment variable injection in CI/CD pipelines.03 TLS / HTTPS
- All Digipay API endpoints must be accessed over HTTPS in production.
- On Android, avoid using
android:usesCleartextTraffic="true"globally. Scope cleartext exceptions to specific development hosts only via Network Security Config. - On iOS, coordinate any ATS exceptions with your security team. Standard HTTPS requires no ATS changes.
04 userId Handling
The userId you supply is sent as user_id in the initiate request. Use a stable, non-PII identifier where possible (e.g. an internal customer UUID). Avoid sending raw email addresses or government IDs as the user identifier.
05 WebView Security
- Do not open
verification_urlin a custom WebView you control — use the SDK's WebView only. This ensures the correct security context and event handling for the hosted KYC flow. - Do not inject arbitrary JavaScript into the SDK WebView.
- Camera and microphone permissions are requested by the hosted page at runtime; the SDK facilitates the browser permission bridge. Verify your app has the correct
Info.plist(iOS) or manifest (Android) entries.
Troubleshooting
Common errors and how to resolve them across all platforms.
01 Common Errors
| Symptom / Error | Likely Cause & Fix |
|---|---|
| authenticate HTTP 401 | Invalid basicAuthHeader. Verify the Base64-encoded clientId:clientSecret exactly matches the value from your Digipay portal. |
| initiate HTTP 401 | JWT rejected on the initiate call. Check companyId and apiKey values — a mismatch here causes a 401 even if authenticate succeeded. |
initiate: missing data.verification_url |
Invalid kycWfNumber or an unregistered callbackUrl. Confirm both values in your Digipay project settings. |
userId must not be blank |
You are using credentials mode but did not set userId on DigipayConfig. Always supply your end-user identifier before launching. |
Blank WebView / ERR_CLEARTEXT_NOT_PERMITTED |
(Android) The verification_url uses HTTP but cleartext traffic is blocked. Add a Network Security Config scoped to your dev host, or switch to HTTPS. |
| Camera not working in WebView | The hosted page may not have reached getUserMedia yet, or permissions are denied. On iOS verify NSCameraUsageDescription is in Info.plist; on Android confirm the SDK's merged manifest includes CAMERA. Check that the device granted the permission prompt. |
| URL opens in system browser | You are using url_launcher / Linking.openURL / UIApplication.open instead of the SDK launch function. Use KycSdk.launchWebWorkflow, KycSdkModal, or KycSdkSheet. |
| Pod install errors (React Native / iOS) | Run pod install (or bundle exec pod install) from the ios/ directory after installing the npm package, then do a full rebuild. |
Flutter: missing webview_flutter plugin |
Run flutter pub get — webview_flutter is a transitive dependency of the SDK and should be resolved automatically. |
02 Integration Checklist
- ✓SDK artifact added to project (
.aar/.xcframework/pubspec.yaml/package.json). - ✓All required transitive dependencies declared (Android only).
- ✓Flutter / Dart / React Native / iOS versions meet SDK peer requirements.
- ✓
DigipayConfigbuilt with a non-blankuserId(credentials mode) or backendverification_urlobtained (URL mode). - ✓Launch function called from the correct lifecycle context (coroutine scope / async Task / BuildContext).
- ✓iOS:
NSCameraUsageDescriptionadded toInfo.plist. - ✓Android: Network Security Config configured for any non-HTTPS dev endpoints.
- ✓Digipay credentials not committed to source control.
- ✓Production deployment uses URL mode (secrets on backend).