> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK KYC React Native: Verifikasi Identitas Mobile

> SDK KYC React Native & Expo dari Didit: TypeScript, iOS & Android native, NFC e-paspor. Mulai $0.33 per KYC lengkap, gratis $10/bulan, tanpa kontrak.



Prompt Integrasi SDK React Native
        Salin prompt ke papan klip



      
      

\<pre>

\`Integrate Didit identity verification into my React Native app using the native SDK.

\## Requirements
\- React Native 0.76+ (New Architecture / TurboModules)
\- Node.js 20+, TypeScript 5+
\- iOS 13.0+ (NFC requires iOS 15+)
\- Android API 24+ (Android 7.0), Kotlin 1.9+, Java 17+
\- New Architecture (TurboModules) only - package is published as @didit-protocol/sdk-react-native v4.x (latest 4.13.2)

\## Installation

\### Expo (recommended)
npx expo install @didit-protocol/sdk-react-native

Add to app.json (NFC is enabled by default):
\{
"expo": {
"plugins": ["@didit-protocol/sdk-react-native"]
}
}

To opt out of NFC dependencies:
\{
"expo": {
"plugins": [["@didit-protocol/sdk-react-native", { "iosNfcEnabled": false, "androidNfcEnabled": false }]]
}
}

The config plugin automatically adds the Didit Maven repo (Android), the DiditSDK podspec (iOS),
and BouncyCastle packaging rules for Android. This SDK requires a development build — it does not work in Expo Go.
The plugin does not edit Info.plist: add the iOS permission keys and, for NFC, the ISO7816 select identifiers
(including D392F000260100000001 for the Japan My Number Card) under expo.ios.infoPlist in app.json.

\### React Native CLI
npm install @didit-protocol/sdk-react-native

iOS — add this block to ios/Podfile inside the app target (NFC-aware; pins to iOS 15 when NFC is on):
didit_sdk_ios_nfc_enabled = ENV.fetch('DIDIT_SDK_IOS_NFC_ENABLED', 'true').downcase != 'false'
didit_sdk_ios_pod = didit_sdk_ios_nfc_enabled ? 'DiditSDK' : 'DiditSDK/Core'
pod didit_sdk_ios_pod, :podspec => 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.13.2/DiditSDK.podspec'
The tag in that URL must equal diditNativeSdkVersions.ios in the package (4.13.2); do not use 'main', because the package requires that exact version and every pod install fails when the URL resolves to a different one.
Then: cd ios && bundle exec pod install

Android — add to settings.gradle (dependencyResolutionManagement.repositories):
maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
To disable NFC, add diditSdkAndroidNfcEnabled=false to android/gradle.properties.

\## Backend: Create Session (your server)
POST https://verification.didit.me/v3/session/
Headers: { "x-api-key": DIDIT_API_KEY, "Content-Type": "application/json" }
Body: { "workflow_id": DIDIT_WORKFLOW_ID, "vendor_data": "user-id" }
Response: { "session_id": "uuid", "session_token": "short-token", "url": "https://verify.didit.me/session/short-token", "status": "Not Started" }
Send session_token to the React Native app (never expose DIDIT_API_KEY to the device).

\## Integration
import { startVerification, VerificationStatus } from '@didit-protocol/sdk-react-native';

// Option A: With session token from your backend (recommended)
const result = await startVerification('session-token-from-backend');

// Option B: With workflow ID (SDK creates session internally)
const result = await startVerificationWithWorkflow('your-workflow-id', {
vendorData: 'user-123',
});

// Handle result
switch (result.type) {
case 'completed':
if (result.session.status === VerificationStatus.Approved) { /* grant access */ }
break;
case 'cancelled':
// User dismissed the verification flow
break;
case 'failed':
// SDK error — show result.error.message
break;
}

\## Result Statuses (VerificationStatus enum)
\- VerificationStatus.Approved — user identity verified, grant access
\- VerificationStatus.Declined — verification failed, show retry or contact support
\- VerificationStatus.Pending  — needs manual review by your compliance team

\## Full Verification Results
The SDK only returns the status. Full decision data (document fields, face match scores, AML hits, etc.) arrives via webhook to your backend.
Set up webhooks: https://docs.didit.me/integration/webhooks

\## Rate Limits (session creation)
\- 600 session-create requests / minute per x-api-key (see https://docs.didit.me/integration/rate-limiting)
\- On 429, retry honouring Retry-After / X-RateLimit-* headers

\## Environment Variables (backend only — never expose in the app)
\- DIDIT_API_KEY — from Didit Console > API & Webhooks
\- DIDIT_WORKFLOW_ID — from Didit Console > Workflows

\## Docs
\- React Native SDK: https://docs.didit.me/integration/native-sdks/react-native-sdk
\- GitHub: https://github.com/didit-protocol/sdk-react-native
\- npm: https://www.npmjs.com/package/@didit-protocol/sdk-react-native
\- Webhooks: https://docs.didit.me/integration/webhooks
\- API Reference: https://docs.didit.me/api-reference/overview`

\</pre>



      
      

Tempel ke

SDK React Native lintas platform yang membungkus SDK native iOS dan Android, menyediakan API TypeScript terpadu untuk verifikasi identitas.> [card] [Repositori GitHub](https://github.com/didit-protocol/sdk-react-native)
>
> Lihat kode sumber dan contoh di GitHub> [card] [Paket npm](https://www.npmjs.com/package/@didit-protocol/sdk-react-native)
>
> @didit-protocol/sdk-react-native> [!NOTE]
>
> ### **SDK Native**: Ini adalah pendekatan yang direkomendasikan untuk aplikasi React Native dan Expo. SDK ini membungkus SDK native iOS dan Android untuk pengalaman pengguna terbaik, penanganan kamera yang dioptimalkan, dan dukungan NFC penuh.***## Persyaratan| Persyaratan | Versi Minimum |
| - | - |
| React Native | 0.76+ (New Architecture / TurboModules) |
| Node.js | 20+ |
| TypeScript | 5+ |### Persyaratan Platform| Platform | Versi Minimum | Catatan |
| - | - | - |
| iOS | 13.0+ | Pembacaan paspor NFC memerlukan iOS 15.0+ |
| Android | API 24+ (7.0) | Kotlin 1.9+, Java 17+ |> [!NOTE]
>
> **Persetujuan biometrik memerlukan native 4.10.0 atau yang lebih baru.** Untuk orang yang tunduk pada hukum Illinois, Texas, atau Colorado, Didit dapat meminta [persetujuan biometrik](https://docs.didit.me/id/getting-started/biometric-consent.md) secara eksplisit sebelum pengambilan wajah pertama. Rilis React Native SDK yang mematok native iOS dan Android 4.10.0 atau yang lebih baru menampilkan langkah tersebut. Versi sebelumnya tidak dapat menampilkan langkah ini: sesinya tetap berjalan seperti sebelumnya, dan keputusan melaporkan persetujuan sebagai belum dikumpulkan (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Perbarui jika Anda memverifikasi orang di negara bagian tersebut.***## Instalasi### Expo (Direkomendasikan)```bash theme={null}
npx expo install @didit-protocol/sdk-react-native
```Lalu tambahkan config plugin ke `app.json` (atau `app.config.js`) Anda. NFC diaktifkan secara default:```json theme={null}
{
  "expo": {
    "plugins": ["@didit-protocol/sdk-react-native"]
  }
}
```Plugin ini secara otomatis mengonfigurasi kedua platform:- **Android:** Menambahkan repositori Maven Didit ke Gradle, mengatur properti Gradle `diditSdkAndroidNfcEnabled`, dan menerapkan aturan dependensi dan pengemasan BouncyCastle
- **iOS:** Menambahkan podspec DiditSDK ke Podfile (dipatok ke iOS 15 saat NFC diaktifkan)Plugin tidak mengedit `Info.plist`. Tambahkan [kunci izin iOS](#ios) dan, untuk NFC, identifier pemilihan ISO7816 di bawah `ios.infoPlist` dalam file yang sama. `D392F000260100000001` memungkinkan SDK membaca Kartu My Number Jepang melalui [JPKI](https://docs.didit.me/id/core-technology/nfc-verification/overview.md#japan-my-number-card-jpki):```json theme={null}
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NFCReaderUsageDescription": "NFC is used to read passport chip data for identity verification.",
        "com.apple.developer.nfc.readersession.iso7816.select-identifiers": [
          "D23300000045737445494420763335",
          "A0000002471001",
          "A0000002472001",
          "00000000000000",
          "D392F000260100000001"
        ]
      }
    }
  }
}
```#### Menonaktifkan dependensi NFCUntuk membangun tanpa dukungan NFC (biner lebih kecil, tidak memerlukan kapabilitas NFC), berikan opsi plugin:```json theme={null}
{
  "expo": {
    "plugins": [
      [
        "@didit-protocol/sdk-react-native",
        { "iosNfcEnabled": false, "androidNfcEnabled": false }
      ]
    ]
  }
}
```Saat NFC dinonaktifkan, Anda tidak memerlukan kapabilitas NFC iOS, entitlement NFC, atau konfigurasi provisioning yang terkait NFC.> [!WARNING]
>
> SDK ini menggunakan modul native (kamera, NFC) yang **tidak tersedia di Expo Go**. Anda harus menggunakan [build pengembangan](https://docs.expo.dev/develop/development-builds/introduction/) atau menjalankan `npx expo prebuild` untuk menghasilkan proyek native.### React Native CLI```bash theme={null}
npm install @didit-protocol/sdk-react-native
# or
yarn add @didit-protocol/sdk-react-native
```#### Pengaturan iOSTambahkan pod DiditSDK ke `Podfile` Anda (pod ini tidak ada di CocoaPods trunk). Blok di bawah ini menghormati variabel lingkungan `DIDIT_SDK_IOS_NFC_ENABLED` sehingga Anda dapat beralih ke subspec tanpa NFC (`DiditSDK/Core`) saat instalasi:```ruby theme={null}
# In your ios/Podfile — at the top, before the target block:
didit_sdk_ios_nfc_enabled = ENV.fetch('DIDIT_SDK_IOS_NFC_ENABLED', 'true').downcase != 'false'

def max_ios_version(*versions)
  versions.map(&:to_s).max_by { |version| Gem::Version.new(version) }
end

platform :ios, didit_sdk_ios_nfc_enabled ? max_ios_version(min_ios_version_supported, '15.0') : min_ios_version_supported

# Inside your app target:
didit_sdk_ios_pod = didit_sdk_ios_nfc_enabled ? 'DiditSDK' : 'DiditSDK/Core'
pod didit_sdk_ios_pod, :podspec => 'https://raw.githubusercontent.com/didit-protocol/sdk-ios/4.13.2/DiditSDK.podspec'
```> [!WARNING]
>
> Tag di URL podspec harus cocok dengan `diditNativeSdkVersions.ios` pada versi paket yang terpasang.
> React Native `4.13.2` mematok native iOS `4.13.2` dan native Android `4.13.2`. Jangan arahkan podspec
> ke `main`: paket ini bergantung pada versi iOS native yang tepat itu, sehingga begitu `main` maju, CocoaPods melihat dua persyaratan yang tidak kompatibel untuk
> `DiditSDK` dan setiap `pod install` gagal. Plugin konfigurasi Expo menghasilkan URL ini untuk Anda; hanya jalur React Native CLI murni yang perlu menuliskannya secara manual.Lalu instal dependensi:```bash theme={null}
cd ios
bundle exec pod install
```Untuk membangun ulang tanpa dependensi NFC, bersihkan CocoaPods dan jalankan ulang dengan variabel lingkungan yang sudah diatur:```bash theme={null}
cd ios
rm -rf Pods Podfile.lock
DIDIT_SDK_IOS_NFC_ENABLED=false bundle exec pod install
```#### Pengaturan AndroidTambahkan repositori Maven Didit ke `settings.gradle` tingkat proyek Anda:```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```Tambahkan kode berikut ke `android/app/build.gradle` Anda (di dalam blok `android { ... }`) untuk mengatasi konflik class duplikat BouncyCastle dan duplikat `MANIFEST.MF` OSGI yang dapat dipicu oleh dependensi transitif DiditSDK:```groovy theme={null}
android {
    configurations.configureEach {
        exclude group: 'org.bouncycastle', module: 'bcprov-jdk15to18'
        exclude group: 'org.bouncycastle', module: 'bcutil-jdk15to18'
        exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15to18'
        exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
    }
    packaging {
        resources {
            pickFirsts += ['org/bouncycastle/**']
            excludes += 'META-INF/versions/9/OSGI-INF/MANIFEST.MF'
        }
    }
}
```Untuk membangun tanpa dependensi NFC Android (menggunakan artefak `me.didit:didit-sdk-core` alih-alih `me.didit:didit-sdk`), tambahkan ini ke `android/gradle.properties`:```properties theme={null}
diditSdkAndroidNfcEnabled=false
```Hapus properti tersebut, atau atur menjadi `true`, untuk menggunakan SDK Android lengkap dengan NFC.***## Izin### iOSTambahkan kunci berikut ke `Info.plist` aplikasi Anda. Kunci privasi iOS yang wajib tetapi tidak ada akan menyebabkan iOS menghentikan aplikasi begitu SDK mengakses sumber daya yang dilindungi tersebut.| Izin | Kunci Info.plist | Deskripsi | Wajib |
| - | - | - | - |
| Kamera | `NSCameraUsageDescription` | Pemindaian dokumen dan verifikasi wajah | Ya |
| Mikrofon | `NSMicrophoneUsageDescription` | Perekaman video liveness | Ya |
| Pustaka Foto | `NSPhotoLibraryUsageDescription` | Unggah gambar dokumen | Ya |
| Lokasi | `NSLocationWhenInUseUsageDescription` | Geolokasi untuk pencegahan penipuan | Ya |
| NFC | `NFCReaderUsageDescription` | Membaca chip NFC pada paspor/kartu identitas | Jika menggunakan NFC |```xml theme={null}
<key>NSCameraUsageDescription</key>
<string>Camera access is required to scan your identity documents for verification.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required to record video for liveness verification.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo library access is required to upload document images.</string>
<key>NFCReaderUsageDescription</key>
<string>NFC is used to read passport chip data for identity verification.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location access is used to detect your country for identity verification.</string>
```#### Konfigurasi NFCUntuk mengaktifkan pembacaan NFC pada paspor dan kartu identitas yang memiliki chip:1) **Tambahkan kapabilitas NFC** di Xcode:
   * Pilih target Anda > **Signing & Capabilities** > **+ Capability** > **Near Field Communication Tag Reading**

2) **Tambahkan pengidentifikasi ISO7816** ke `Info.plist`:```xml theme={null}
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
    <string>D23300000045737445494420763335</string>
    <string>A0000002471001</string>
    <string>A0000002472001</string>
    <string>00000000000000</string>
    <string>D392F000260100000001</string>
</array>
````D392F000260100000001` memungkinkan SDK membaca My Number Card Jepang melalui [JPKI](https://docs.didit.me/id/core-technology/nfc-verification/overview.md#japan-my-number-card-jpki): tanpa pengidentifikasi ini, iOS tidak melaporkan kartu tersebut ke SDK. Pembacaan My Number Card belum diaktifkan di produksi, dan pengidentifikasi ini tidak berpengaruh pada dokumen lain, sehingga Anda dapat menambahkannya sekarang.3) **Tambahkan file entitlements** dengan pembacaan NFC tag diaktifkan:```xml theme={null}
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
```Pastikan profil provisioning aplikasi menyertakan kapabilitas NFC Tag Reading. Konfigurasi NFC ini tidak diperlukan jika NFC dinonaktifkan.### AndroidIzin berikut dideklarasikan di `AndroidManifest.xml` SDK dan digabungkan secara otomatis:| Izin | Deskripsi | Wajib |
| - | - | - |
| `INTERNET` | Akses jaringan untuk komunikasi API | Ya |
| `ACCESS_NETWORK_STATE` | Mendeteksi ketersediaan jaringan | Ya |
| `CAMERA` | Pemindaian dokumen dan verifikasi wajah | Ya |
| `NFC` | Membaca chip NFC pada paspor/kartu identitas | Jika menggunakan NFC |Fitur perangkat keras kamera dan NFC dideklarasikan sebagai opsional (`android:required="false"`), sehingga aplikasi Anda dapat diinstal di perangkat yang tidak memiliki fitur tersebut.***## Mulai Cepat```tsx theme={null}
import { startVerification, VerificationStatus } from '@didit-protocol/sdk-react-native';

// Start verification with a session token from your backend
const result = await startVerification('your-session-token');

switch (result.type) {
  case 'completed':
    if (result.session.status === VerificationStatus.Approved) {
      console.log('Identity verified!');
    }
    break;
  case 'cancelled':
    console.log('User cancelled');
    break;
  case 'failed':
    console.log('Error:', result.error.message);
    break;
}
```***## Metode IntegrasiSDK mendukung dua metode integrasi:### Metode 1: Token Sesi (Direkomendasikan untuk Produksi)Buat sesi di backend Anda menggunakan [Create Verification Session API](https://docs.didit.me/id/sessions-api/create-session.md), lalu teruskan token ke SDK:```tsx theme={null}
import { startVerification } from '@didit-protocol/sdk-react-native';

// Your backend creates a session and returns the token
const sessionToken = await yourBackend.createVerificationSession(userId);

// Pass the token to the SDK
const result = await startVerification(sessionToken);
```Pendekatan ini memberi Anda kendali penuh atas:- Mengaitkan sesi dengan pengguna Anda (`vendor_data`)
- Mengatur metadata kustom
- Mengonfigurasi callback per sesi### Metode 2: ID Alur Kerja (Integrasi Lebih Sederhana)Untuk integrasi yang lebih sederhana, SDK dapat membuat sesi secara langsung menggunakan ID alur kerja Anda:```tsx theme={null}
import { startVerificationWithWorkflow } from '@didit-protocol/sdk-react-native';

const result = await startVerificationWithWorkflow('your-workflow-id', {
  vendorData: 'user-123',
  contactDetails: { email: 'user@example.com' },
  config: { loggingEnabled: true },
});
```***## KonfigurasiSesuaikan perilaku SDK dengan meneruskan objek `DiditConfig`:```tsx theme={null}
const result = await startVerification('your-session-token', {
  languageCode: 'es',           // Force Spanish language
  showLanguageSelector: true,   // Let the user change language
  fontFamily: 'Avenir',         // Custom font (must be registered natively)
  loggingEnabled: true,         // Enable debug logging
  showCloseButton: true,        // Show close (X) button on step screens
  showExitConfirmation: true,   // Confirm before exit
  closeOnComplete: false,       // Auto-dismiss UI on completion
});
```Untuk `startVerificationWithWorkflow`, teruskan konfigurasi di dalam `options.config`:```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  vendorData: 'user-123',
  config: {
    languageCode: 'es',
    showLanguageSelector: true,
    loggingEnabled: true,
    showCloseButton: true,
    showExitConfirmation: true,
  },
});
```### Opsi Konfigurasi| Properti | Tipe | Default | Deskripsi |
| - | - | - | - |
| `languageCode` | `string` | Lokal perangkat | Kode bahasa ISO 639-1 (misalnya `"en"`, `"fr"`, `"ar"`) |
| `showLanguageSelector` | `boolean` | `false` | Tampilkan pemilih bahasa bergaya web di layar selamat datang |
| `fontFamily` | `string` | Font sistem | Nama keluarga font kustom (harus didaftarkan secara asli) |
| `loggingEnabled` | `boolean` | `false` | Aktifkan pencatatan debug SDK |
| `showCloseButton` | `boolean` | `true` | Tampilkan tombol tutup (X) pada layar langkah verifikasi |
| `showExitConfirmation` | `boolean` | `true` | Tampilkan dialog konfirmasi saat pengguna mencoba keluar |
| `closeOnComplete` | `boolean` | `false` | Tutup UI verifikasi secara otomatis saat selesai |
| `defaultDocumentCamera` | `CameraLens?` | Default sistem (`CameraLens.Back`) | Lensa yang digunakan saat layar pengambilan dokumen dibuka |
| `defaultLivenessCamera` | `CameraLens?` | Default sistem (`CameraLens.Front`) | Lensa yang digunakan saat layar pengambilan wajah (liveness) dibuka |
| `showDocumentCameraSwitchButton` | `boolean` | `true` | Tampilkan pengalih kamera saat pengambilan di layar pengambilan dokumen |
| `showLivenessCameraSwitchButton` | `boolean` | `true` | Tampilkan pengalih kamera saat pengambilan di layar pengambilan wajah |### Opsi kameraOpsi kamera sama dengan [opsi kamera Web SDK](https://docs.didit.me/id/integration/web-sdks/javascript-sdk.md#opsi-kamera).
Setiap lensa adalah `CameraLens.Front` atau `CameraLens.Back`.
Jika perangkat tidak memiliki lensa yang diminta, SDK menggunakan kamera pertama yang tersedia.
Pengalih kamera juga disembunyikan pada perangkat yang hanya memiliki satu kamera.
Atur opsi pengalih ke `false` untuk mengunci pengguna pada lensa default langkah tersebut.```tsx theme={null}
import { startVerification, CameraLens } from '@didit-protocol/sdk-react-native';

await startVerification('your-session-token', {
  defaultLivenessCamera: CameraLens.Back,
  showLivenessCameraSwitchButton: false,
});
```> [!NOTE]
>
> **Tema & Warna**: Warna, latar belakang, dan pengaturan layar pembuka dikonfigurasi melalui [pengaturan White Label](https://business.didit.me) Anda di Didit Console, bukan di konfigurasi SDK. Hal ini memastikan pencitraan merek yang konsisten di semua platform.***## Dukungan BahasaSDK mendukung **54 bahasa**. Jika tidak ada bahasa yang ditentukan, SDK menggunakan locale perangkat dengan bahasa Inggris sebagai cadangan.```tsx theme={null}
// Use device locale (default)
await startVerification(token);

// Force specific language
await startVerification(token, { languageCode: 'fr' });

// Let the user change language on the welcome screen
await startVerification(token, { showLanguageSelector: true });
```**[Lihat Semua Bahasa yang Didukung →](https://docs.didit.me/id/integration/supported-languages.md)*****## Opsi LanjutanOpsi ini hanya tersedia dengan `startVerificationWithWorkflow`, saat SDK membuat sesi atas nama Anda.### Detail Kontak (Pengisian Otomatis & Notifikasi)Berikan detail kontak untuk mengisi otomatis formulir verifikasi dan mengaktifkan notifikasi email:```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  contactDetails: {
    email: 'user@example.com',
    sendNotificationEmails: true,  // Send status update emails
    emailLang: 'en',               // Email language (ISO 639-1)
    phone: '+14155552671',         // E.164 format
  },
});
```### Detail yang Diharapkan (Validasi Silang)Berikan detail pengguna yang diharapkan untuk validasi silang otomatis dengan data dokumen yang diekstrak:```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  expectedDetails: {
    firstName: 'John',
    lastName: 'Doe',
    dateOfBirth: '1990-05-15',     // YYYY-MM-DD format
    gender: 'M',
    nationality: 'USA',            // ISO 3166-1 alpha-3
    country: 'USA',
    address: '1 Market St, San Francisco, CA',
    identificationNumber: 'A1234567',
    ipAddress: '203.0.113.42',
    portraitImage: 'https://...',  // URL or base64 reference image
  },
});
```Semua kolom `ExpectedDetails` bersifat opsional. Lihat [`src/types.ts`](https://github.com/didit-protocol/sdk-react-native/blob/main/src/types.ts) untuk tipe lengkapnya.### Metadata KustomSimpan metadata JSON kustom bersama sesi (tidak ditampilkan kepada pengguna):```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  vendorData: 'user-123',
  metadata: '{"internalId": "abc123", "source": "mobile-app"}',
});
```***## Penanganan HasilBaik `startVerification` maupun `startVerificationWithWorkflow` mengembalikan `Promise<VerificationResult>`. Hasilnya berupa union terdiskriminasi, sehingga Anda menggunakan kolom `type` untuk menentukan hasilnya.### Kasus Hasil| Kasus | Deskripsi |
| - | - |
| `completed` | Alur verifikasi selesai (periksa `session.status` untuk hasilnya) |
| `cancelled` | Pengguna membatalkan alur verifikasi |
| `failed` | Terjadi error selama verifikasi |### Properti SessionData| Properti | Tipe | Deskripsi |
| - | - | - |
| `sessionId` | `string` | Identifier sesi yang unik |
| `status` | `VerificationStatus` | `Approved`, `Pending`, atau `Declined` |### Tipe Error| Error | Deskripsi |
| - | - |
| `sessionExpired` | Sesi telah kedaluwarsa |
| `networkError` | Masalah konektivitas jaringan |
| `cameraAccessDenied` | Izin kamera belum diberikan |
| `notInitialized` | SDK belum diinisialisasi (hanya Android) |
| `apiError` | Permintaan API gagal |
| `unknown` | Error lain beserta pesannya |### Koneksi terputusJika perangkat kehilangan koneksi selama verifikasi, SDK menutupi alur dengan layar "No internet connection", alih-alih membiarkan langkah tetap dalam keadaan memuat.
SDK terus memeriksa di latar belakang dan menutup layar itu dengan sendirinya begitu Didit dapat dijangkau kembali, dan pengguna melanjutkan dari langkah tempat ia berada.
Layar ini menampilkan **Try Again** dan, jika `showCloseButton` bernilai `true` (bawaan), **Exit Verification**.
Jika pengguna keluar, verifikasi berakhir dengan hasil `failed` dengan error `networkError`, sehingga aplikasi Anda tahu bahwa pengguna keluar karena masalah koneksi.### Contoh Lengkap Penanganan Hasil```tsx theme={null}
import {
  startVerification,
  VerificationStatus,
  type VerificationResult,
} from '@didit-protocol/sdk-react-native';

async function verify(token: string) {
  const result: VerificationResult = await startVerification(token);

  switch (result.type) {
    case 'completed':
      switch (result.session.status) {
        case VerificationStatus.Approved:
          console.log('Approved! Session:', result.session.sessionId);
          // User is verified — grant access
          break;
        case VerificationStatus.Pending:
          console.log('Under review. Session:', result.session.sessionId);
          // Show "verification in progress" UI
          break;
        case VerificationStatus.Declined:
          console.log('Declined. Session:', result.session.sessionId);
          // Handle declined verification
          break;
      }
      break;

    case 'cancelled':
      console.log('User cancelled the verification.');
      // Maybe show retry option
      break;

    case 'failed':
      console.log(`Error [${result.error.type}]: ${result.error.message}`);
      // Handle error — show retry or contact support
      break;
  }
}
```***## Contoh End-to-End (Sesi Backend → React Native SDK → Webhook)Ini adalah integrasi siap produksi: backend Anda membuat sesi, aplikasi RN Anda menerima `session_token`, lalu SDK menjalankan alurnya. Keputusan akhir dikirim ke backend Anda melalui webhook, jadi jangan pernah hanya mengandalkan hasil di sisi klien.### 1. Backend: membuat sesi```ts theme={null}
// Node.js / Express example. Run on your server. NEVER ship DIDIT_API_KEY to the device.
import express from "express";

const app = express();
app.use(express.json());

app.post("/api/verification/start", async (req, res) => {
  const response = await fetch("https://verification.didit.me/v3/session/", {
    method: "POST",
    headers: {
      "x-api-key": process.env.DIDIT_API_KEY!,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      workflow_id: process.env.DIDIT_WORKFLOW_ID,
      vendor_data: req.body.userId, // your stable user id
    }),
  });

  if (!response.ok) {
    return res.status(500).json({ error: `Didit ${response.status}` });
  }

  const { session_id, session_token } = await response.json();
  // Persist session_id <-> userId so you can match the webhook later.
  res.json({ session_id, session_token });
});
```### 2. React Native: menukar token dan memulai SDK```tsx theme={null}
import { useCallback, useState } from 'react';
import { Button, View } from 'react-native';
import {
  startVerification,
  VerificationStatus,
  type VerificationResult,
} from '@didit-protocol/sdk-react-native';

export function VerifyButton({ userId }: { userId: string }) {
  const [loading, setLoading] = useState(false);

  const onPress = useCallback(async () => {
    setLoading(true);
    try {
      const r = await fetch('https://your-backend.example.com/api/verification/start', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ userId }),
      });
      const { session_token } = await r.json();

      const result: VerificationResult = await startVerification(session_token);

      switch (result.type) {
        case 'completed':
          if (result.session.status === VerificationStatus.Approved) {
            // Optimistic UI; rely on the webhook delivered to your backend as the source of truth.
          }
          break;
        case 'cancelled':
          // User dismissed the flow
          break;
        case 'failed':
          // Show retry — result.error.type / result.error.message
          break;
      }
    } finally {
      setLoading(false);
    }
  }, [userId]);

  return (
    <View>
      <Button title={loading ? 'Starting...' : 'Verify identity'} onPress={onPress} disabled={loading} />
    </View>
  );
}
```### 3. Backend: menerima keputusan akhir melalui webhook```ts theme={null}
app.post("/api/webhooks/didit", express.raw({ type: "application/json" }), (req, res) => {
  // 1. Verify the X-Signature header (see Webhooks docs)
  // 2. Parse the body
  const event = JSON.parse(req.body.toString());
  if (event.webhook_type === "status.updated") {
    // event.session_id, event.status ("Approved" | "Declined" | "In Review" | ...)
    // Look up the user by session_id and update their verification state.
  }
  res.sendStatus(200);
});
```Lihat [Panduan webhook](https://docs.didit.me/id/integration/webhooks.md) untuk detail verifikasi tanda tangan HMAC.***## Contoh Lengkap```tsx theme={null}
import { useState, useCallback } from 'react';
import {
  Text,
  View,
  TextInput,
  TouchableOpacity,
  Alert,
  ActivityIndicator,
  SafeAreaView,
} from 'react-native';
import {
  startVerification,
  VerificationStatus,
  type VerificationResult,
} from '@didit-protocol/sdk-react-native';

export default function App() {
  const [token, setToken] = useState('');
  const [loading, setLoading] = useState(false);

  const handleVerify = useCallback(async () => {
    if (!token.trim()) {
      Alert.alert('Error', 'Please enter a session token.');
      return;
    }

    setLoading(true);
    try {
      const result = await startVerification(token.trim(), {
        loggingEnabled: true,
      });

      switch (result.type) {
        case 'completed':
          Alert.alert(
            'Verification Complete',
            `Status: ${result.session.status}\nSession: ${result.session.sessionId}`
          );
          break;
        case 'cancelled':
          Alert.alert('Cancelled', 'The user cancelled the verification.');
          break;
        case 'failed':
          Alert.alert('Failed', `${result.error.type}: ${result.error.message}`);
          break;
      }
    } catch (error) {
      Alert.alert('Error', `Unexpected error: ${error}`);
    } finally {
      setLoading(false);
    }
  }, [token]);

  return (
    <SafeAreaView style={{ flex: 1, padding: 24, justifyContent: 'center' }}>
      <TextInput
        placeholder="Enter session token..."
        value={token}
        onChangeText={setToken}
        autoCapitalize="none"
        style={{
          borderWidth: 1,
          borderColor: '#ccc',
          borderRadius: 8,
          padding: 12,
          marginBottom: 16,
        }}
      />
      <TouchableOpacity
        onPress={handleVerify}
        disabled={loading}
        style={{
          backgroundColor: '#1a1a1a',
          borderRadius: 8,
          padding: 16,
          alignItems: 'center',
          opacity: loading ? 0.6 : 1,
        }}
      >
        {loading ? (
          <ActivityIndicator color="#fff" />
        ) : (
          <Text style={{ color: '#fff', fontWeight: '600' }}>
            Start Verification
          </Text>
        )}
      </TouchableOpacity>
    </SafeAreaView>
  );
}
```***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.