> ## 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.

# React Native KYC SDK: 모바일 신원 인증

> Didit의 React Native·Expo KYC SDK로 TypeScript, 네이티브 iOS·Android, NFC 여권 인증을 지원합니다. 전체 KYC 검사 건당 $0.33부터, 월 $10 무료, 약정 없음.



React Native SDK 통합 프롬프트
        프롬프트를 클립보드에 복사



      
      

\<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>



      
      

붙여넣을 곳

네이티브 iOS 및 Android SDK를 감싸는 크로스 플랫폼 React Native SDK로, 신원 확인을 위한 통합된 TypeScript API를 제공합니다.> [card] [GitHub 저장소](https://github.com/didit-protocol/sdk-react-native)
>
> GitHub에서 소스 코드와 예제를 확인하세요> [card] [npm 패키지](https://www.npmjs.com/package/@didit-protocol/sdk-react-native)
>
> @didit-protocol/sdk-react-native> [!NOTE]
>
> ### **네이티브 SDK**: React Native 및 Expo 앱에 권장되는 방식입니다. 이 SDK는 최상의 사용자 경험, 최적화된 카메라 처리, 완전한 NFC 지원을 위해 네이티브 iOS 및 Android SDK를 감쌉니다.***## 요구 사항| 요구 사항 | 최소 버전 |
| - | - |
| React Native | 0.76+ (새 아키텍처 / TurboModules) |
| Node.js | 20+ |
| TypeScript | 5+ |### 플랫폼 요구 사항| 플랫폼 | 최소 버전 | 비고 |
| - | - | - |
| iOS | 13.0+ | NFC 여권 판독에는 iOS 15.0+가 필요합니다 |
| Android | API 24+ (7.0) | Kotlin 1.9+, Java 17+ |> [!NOTE]
>
> **생체 인식 동의에는 네이티브 4.10.0 이상이 필요합니다.** 일리노이주, 텍사스주 또는 콜로라도주 법률이 적용되는 사용자의 경우, Didit은 첫 얼굴 촬영 전에 명시적인 [생체 인식 동의](https://docs.didit.me/ko/getting-started/biometric-consent.md)를 요청할 수 있습니다. iOS와 Android 네이티브 4.10.0 이상을 고정한 React Native SDK 릴리스는 이 단계를 표시합니다. 이전 버전은 이 단계를 표시할 수 없습니다. 해당 세션은 이전과 같이 실행되며, 결정 결과에는 동의가 수집되지 않은 것으로 보고됩니다(`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). 해당 주에서 사용자를 인증한다면 업그레이드하세요.***## 설치### Expo (권장)```bash theme={null}
npx expo install @didit-protocol/sdk-react-native
```그다음 `app.json`(또는 `app.config.js`)에 구성 플러그인을 추가합니다. NFC는 기본적으로 활성화되어 있습니다:```json theme={null}
{
  "expo": {
    "plugins": ["@didit-protocol/sdk-react-native"]
  }
}
```플러그인이 두 플랫폼을 자동으로 구성합니다:- **Android:** Gradle에 Didit Maven 저장소를 추가하고, `diditSdkAndroidNfcEnabled` Gradle 속성을 설정하며, BouncyCastle 종속성 및 패키징 규칙을 적용합니다
- **iOS:** Podfile에 DiditSDK podspec을 추가합니다(NFC가 활성화된 경우 iOS 15로 고정됨)플러그인은 `Info.plist`를 편집하지 않습니다. 같은 파일의 `ios.infoPlist` 아래에 [iOS 권한 키](#ios)를 추가하고, NFC를 사용하는 경우 ISO7816 select 식별자도 추가합니다. `D392F000260100000001`을 사용하면 SDK가 [JPKI](https://docs.didit.me/ko/core-technology/nfc-verification/overview.md#일본-마이넘버카드-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"
        ]
      }
    }
  }
}
```#### NFC 종속성 비활성화NFC 지원 없이 빌드하려면(바이너리 크기가 더 작고 NFC 기능이 필요하지 않음) 플러그인 옵션을 전달합니다:```json theme={null}
{
  "expo": {
    "plugins": [
      [
        "@didit-protocol/sdk-react-native",
        { "iosNfcEnabled": false, "androidNfcEnabled": false }
      ]
    ]
  }
}
```NFC를 비활성화하면 iOS NFC 기능, NFC 권한(entitlements), NFC 관련 프로비저닝 설정이 필요하지 않습니다.> [!WARNING]
>
> 이 SDK는 Expo Go에서 사용할 수 없는 네이티브 모듈(카메라, NFC)을 사용합니다. [개발 빌드](https://docs.expo.dev/develop/development-builds/introduction/)를 사용하거나 `npx expo prebuild`를 실행하여 네이티브 프로젝트를 생성해야 합니다.### React Native CLI```bash theme={null}
npm install @didit-protocol/sdk-react-native
# or
yarn add @didit-protocol/sdk-react-native
```#### iOS 설정`Podfile`에 DiditSDK pod를 추가합니다(CocoaPods trunk에는 등록되어 있지 않습니다). 아래 블록은 `DIDIT_SDK_IOS_NFC_ENABLED` 환경 변수를 지원하므로, 설치 시점에 NFC 없는 서브스펙(`DiditSDK/Core`)을 켜거나 끌 수 있습니다:```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]
>
> podspec URL의 태그는 설치된 패키지 버전의 `diditNativeSdkVersions.ios`와 일치해야 합니다. React Native `4.13.2`는 네이티브 iOS `4.13.2`와 네이티브 Android `4.13.2`에 고정되어 있습니다. podspec이 `main`을 가리키도록 하지 마십시오. 패키지는 정확히 그 네이티브 iOS 버전에 의존하므로, `main`이 앞서 나가는 순간 CocoaPods는 `DiditSDK`에 대해 서로 호환되지 않는 두 가지 요구 사항을 보게 되고 모든 `pod install`이 실패합니다. Expo 구성 플러그인은 이 URL을 자동으로 생성합니다. 순수 React Native CLI 경로에서만 이 URL을 직접 작성해야 합니다.그다음 종속성을 설치합니다:```bash theme={null}
cd ios
bundle exec pod install
```NFC 종속성 없이 다시 빌드하려면 CocoaPods를 정리한 다음 환경 변수를 설정하고 다시 실행합니다:```bash theme={null}
cd ios
rm -rf Pods Podfile.lock
DIDIT_SDK_IOS_NFC_ENABLED=false bundle exec pod install
```#### Android 설정프로젝트 수준의 `settings.gradle`에 Didit Maven 저장소를 추가합니다:```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```BouncyCastle 클래스 중복 충돌과 DiditSDK 전이 종속성이 유발할 수 있는 OSGI `MANIFEST.MF` 중복을 해결하려면 앱의 `android/app/build.gradle`(`android { ... }` 블록 안)에 다음을 추가합니다:```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'
        }
    }
}
```Android NFC 종속성 없이 빌드하려면(`me.didit:didit-sdk` 대신 `me.didit:didit-sdk-core` 아티팩트를 사용함) `android/gradle.properties`에 다음을 추가합니다:```properties theme={null}
diditSdkAndroidNfcEnabled=false
```NFC를 포함한 전체 Android SDK를 사용하려면 해당 속성을 제거하거나 `true`로 설정합니다.***## 권한### iOS앱의 `Info.plist`에 다음 키를 추가하십시오. 필수 iOS 개인정보 보호 키가 없으면 SDK가 해당 보호 리소스에 접근하는 순간 iOS가 앱을 종료합니다.| 권한 | Info.plist 키 | 설명 | 필수 여부 |
| - | - | - | - |
| 카메라 | `NSCameraUsageDescription` | 문서 스캔 및 얼굴 인증 | 예 |
| 마이크 | `NSMicrophoneUsageDescription` | 라이브니스 영상 녹화 | 예 |
| 사진 보관함 | `NSPhotoLibraryUsageDescription` | 문서 이미지 업로드 | 예 |
| 위치 | `NSLocationWhenInUseUsageDescription` | 사기 방지를 위한 위치 정보 | 예 |
| NFC | `NFCReaderUsageDescription` | 여권 및 신분증의 NFC 칩 읽기 | 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>
```#### NFC 구성칩이 있는 여권 및 신분증의 NFC 읽기를 활성화하려면 다음을 수행하십시오.1) Xcode에서 **NFC 기능을 추가**합니다:
   * 대상을 선택한 후 **Signing & Capabilities** > **+ Capability** > **Near Field Communication Tag Reading**을 선택합니다.

2) `Info.plist`에 **ISO7816 식별자**를 추가합니다:```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`을 설정하면 SDK가 일본 마이넘버 카드(My Number Card)를 [JPKI](https://docs.didit.me/ko/core-technology/nfc-verification/overview.md#일본-마이넘버카드-jpki)를 통해 읽을 수 있습니다. 이 식별자가 없으면 iOS가 해당 카드를 SDK에 전달하지 않습니다. 마이넘버 카드 읽기는 아직 프로덕션에서 활성화되어 있지 않으며, 이 식별자는 다른 문서에는 아무런 영향을 주지 않으므로 지금 추가해도 됩니다.3) NFC 태그 읽기가 활성화된 **권한 파일(entitlements)을 추가**합니다:```xml theme={null}
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
```앱의 프로비저닝 프로필에 NFC Tag Reading 기능이 포함되어 있는지 확인하십시오. NFC가 비활성화되어 있으면 이 NFC 구성은 필요하지 않습니다.### Android다음 권한은 SDK의 `AndroidManifest.xml`에 선언되어 있으며 자동으로 병합됩니다.| 권한 | 설명 | 필수 여부 |
| - | - | - |
| `INTERNET` | API 통신을 위한 네트워크 접근 | 예 |
| `ACCESS_NETWORK_STATE` | 네트워크 사용 가능 여부 감지 | 예 |
| `CAMERA` | 문서 스캔 및 얼굴 인증 | 예 |
| `NFC` | 여권 및 신분증의 NFC 칩 읽기 | NFC 사용 시 |카메라 및 NFC 하드웨어 기능은 선택 사항(`android:required="false"`)으로 선언되어 있으므로, 이러한 기능이 없는 기기에도 앱을 설치할 수 있습니다.***## 빠른 시작```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;
}
```***## 연동 방식SDK는 두 가지 연동 방식을 지원합니다.### 방식 1: 세션 토큰 (프로덕션 권장)백엔드에서 [인증 세션 생성 API](https://docs.didit.me/ko/sessions-api/create-session.md)를 사용해 세션을 생성한 다음, 토큰을 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);
```이 방식을 사용하면 다음 항목을 완전하게 제어할 수 있습니다.- 세션을 사용자와 연결 (`vendor_data`)
- 사용자 지정 메타데이터 설정
- 세션별 콜백 구성### 방식 2: 워크플로 ID (간편한 연동)간단한 연동을 원하면 SDK가 워크플로 ID를 사용해 세션을 직접 생성할 수 있습니다.```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 },
});
```***## 구성`DiditConfig` 객체를 전달하여 SDK 동작을 사용자 지정합니다.```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
});
````startVerificationWithWorkflow`의 경우 구성은 `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,
  },
});
```### 구성 옵션| 속성 | 타입 | 기본값 | 설명 |
| - | - | - | - |
| `languageCode` | `string` | 기기 로캘 | ISO 639-1 언어 코드(예: `"en"`, `"fr"`, `"ar"`) |
| `showLanguageSelector` | `boolean` | `false` | 환영 화면에 웹 스타일 언어 선택기를 표시합니다 |
| `fontFamily` | `string` | 시스템 글꼴 | 사용자 지정 글꼴 패밀리 이름(네이티브에 등록되어 있어야 함) |
| `loggingEnabled` | `boolean` | `false` | SDK 디버그 로깅을 활성화합니다 |
| `showCloseButton` | `boolean` | `true` | 인증 단계 화면에 닫기(X) 버튼을 표시합니다 |
| `showExitConfirmation` | `boolean` | `true` | 사용자가 종료를 시도할 때 확인 대화 상자를 표시합니다 |
| `closeOnComplete` | `boolean` | `false` | 완료되면 인증 UI를 자동으로 닫습니다 |
| `defaultDocumentCamera` | `CameraLens?` | 네이티브 기본값(`CameraLens.Back`) | 문서 촬영 화면이 열릴 때 사용되는 렌즈 |
| `defaultLivenessCamera` | `CameraLens?` | 네이티브 기본값(`CameraLens.Front`) | 얼굴(라이브니스) 촬영 화면이 열릴 때 사용되는 렌즈 |
| `showDocumentCameraSwitchButton` | `boolean` | `true` | 문서 촬영 화면에 촬영 중 카메라 전환 버튼을 표시합니다 |
| `showLivenessCameraSwitchButton` | `boolean` | `true` | 얼굴 촬영 화면에 촬영 중 카메라 전환 버튼을 표시합니다 |### 카메라 옵션카메라 옵션은 [웹 SDK 카메라 옵션](https://docs.didit.me/ko/integration/web-sdks/javascript-sdk.md#카메라-옵션)과 동일합니다.
각 렌즈는 `CameraLens.Front` 또는 `CameraLens.Back`입니다.
기기에 요청한 렌즈가 없으면 SDK는 기기가 가진 첫 번째 카메라를 사용합니다.
카메라가 하나뿐인 기기에서는 카메라 전환 버튼도 표시되지 않습니다.
전환 옵션을 `false`로 설정하면 해당 단계에서 사용자가 기본 렌즈만 사용하도록 고정됩니다.```tsx theme={null}
import { startVerification, CameraLens } from '@didit-protocol/sdk-react-native';

await startVerification('your-session-token', {
  defaultLivenessCamera: CameraLens.Back,
  showLivenessCameraSwitchButton: false,
});
```> [!NOTE]
>
> **테마 및 색상**: 색상, 배경 및 소개 화면 설정은 SDK 구성이 아니라 Didit Console의 [화이트 라벨 설정](https://business.didit.me)에서 구성합니다. 이렇게 하면 모든 플랫폼에서 브랜드가 일관되게 유지됩니다.***## 언어 지원SDK는 **54개 언어**를 지원합니다. 언어를 지정하지 않으면 SDK는 기기 로캘을 사용하며, 대체 언어는 영어입니다.```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 });
```**[지원되는 전체 언어 보기 →](https://docs.didit.me/ko/integration/supported-languages.md)*****## 고급 옵션다음 옵션은 SDK가 사용자를 대신해 세션을 생성하는 `startVerificationWithWorkflow`에서만 사용할 수 있습니다.### 연락처 정보 (사전 입력 및 알림)인증 양식을 미리 채우고 이메일 알림을 활성화하려면 연락처 정보를 제공하십시오.```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
  },
});
```### 예상 정보 (교차 검증)추출된 문서 데이터와 자동으로 교차 검증할 수 있도록 사용자의 예상 정보를 제공하십시오.```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
  },
});
````ExpectedDetails`의 모든 필드는 선택 사항입니다. 전체 타입은 [`src/types.ts`](https://github.com/didit-protocol/sdk-react-native/blob/main/src/types.ts)를 참조하십시오.### 사용자 지정 메타데이터세션과 함께 사용자 지정 JSON 메타데이터를 저장합니다(사용자에게 표시되지 않음).```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  vendorData: 'user-123',
  metadata: '{"internalId": "abc123", "source": "mobile-app"}',
});
```***## 결과 처리`startVerification`과 `startVerificationWithWorkflow`는 모두 `Promise<VerificationResult>`를 반환합니다. 결과는 구별된 유니온(판별 유니온)이며, 결과를 확인하려면 `type` 필드를 사용하세요.### 결과 케이스| 케이스 | 설명 |
| - | - |
| `completed` | 인증 절차가 완료되었습니다(결과는 `session.status`에서 확인하세요) |
| `cancelled` | 사용자가 인증 절차를 취소했습니다 |
| `failed` | 인증 중 오류가 발생했습니다 |### SessionData 속성| 속성 | 타입 | 설명 |
| - | - | - |
| `sessionId` | `string` | 고유한 세션 식별자 |
| `status` | `VerificationStatus` | `Approved`, `Pending` 또는 `Declined` |### 오류 유형| 오류 | 설명 |
| - | - |
| `sessionExpired` | 세션이 만료되었습니다 |
| `networkError` | 네트워크 연결 문제 |
| `cameraAccessDenied` | 카메라 권한이 허용되지 않았습니다 |
| `notInitialized` | SDK가 초기화되지 않았습니다(Android 전용) |
| `apiError` | API 요청이 실패했습니다 |
| `unknown` | 메시지가 포함된 기타 오류 |### 연결 끊김인증 중 기기의 연결이 끊어지면, SDK는 흐름을 "인터넷 연결 없음" 화면으로 대체하여 단계가 로딩 상태에 머무르지 않도록 합니다.
SDK는 백그라운드에서 계속 확인하며, Didit에 다시 연결되는 즉시 화면을 자동으로 닫고 사용자는 있던 단계부터 이어서 진행합니다.
이 화면에는 **다시 시도** 버튼이 있으며, `showCloseButton`이 `true`(기본값)이면 **인증 종료** 버튼도 함께 표시됩니다.
인증을 종료하면 오류가 `networkError`인 `failed` 결과로 끝나므로, 앱은 사용자가 연결 문제로 나갔다는 것을 알 수 있습니다.### 결과 처리 전체 예제```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;
  }
}
```***## 엔드 투 엔드 예제 (백엔드 세션 → React Native SDK → webhook)운영 환경에 바로 적용할 수 있는 연동 방식입니다. 백엔드가 세션을 생성하고, RN 앱이 `session_token`을 받아 SDK로 절차를 실행합니다. 최종 결정은 webhook을 통해 백엔드로 전달되며, 클라이언트 측 결과만으로는 절대 신뢰하지 마세요.### 1. 백엔드 — 세션 생성```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 — token 교환 후 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. 백엔드 — 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);
});
```HMAC 서명 검증에 대한 자세한 내용은 [webhook 가이드](https://docs.didit.me/ko/integration/webhooks.md)를 참조하세요.***## 전체 예제```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.