> ## 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 para React Native: verificación móvil

> SDK KYC de Didit para React Native y Expo: TypeScript, iOS y Android nativos, NFC. Desde $0.33 por KYC completo, $10 gratis/mes, sin contratos.



Prompt de integración del SDK de React Native
        Copiar el prompt al portapapeles



      
      

\<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.9.1)

\## 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.9.1/DiditSDK.podspec'
The tag in that URL must equal diditNativeSdkVersions.ios in the package (4.9.1); 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>



      
      

Pegar en

Un SDK multiplataforma de React Native que encapsula los SDK nativos de iOS y Android y ofrece una API unificada en TypeScript para la verificación de identidad.> [card] [Repositorio de GitHub](https://github.com/didit-protocol/sdk-react-native)
>
> Consulta el código fuente y los ejemplos en GitHub> [card] [Paquete de npm](https://www.npmjs.com/package/@didit-protocol/sdk-react-native)
>
> @didit-protocol/sdk-react-native> [!NOTE]
>
> ### **SDK nativo**: Es el enfoque recomendado para apps de React Native y Expo. El SDK encapsula los SDK nativos de iOS y Android para ofrecer la mejor experiencia de usuario, una gestión optimizada de la cámara y compatibilidad completa con NFC.***## Requisitos| Requisito | Versión mínima |
| - | - |
| React Native | 0.76+ (New Architecture / TurboModules) |
| Node.js | 20+ |
| TypeScript | 5+ |### Requisitos de plataforma| Plataforma | Versión mínima | Notas |
| - | - | - |
| iOS | 13.0+ | La lectura NFC de pasaportes requiere iOS 15.0+ |
| Android | API 24+ (7.0) | Kotlin 1.9+, Java 17+ |> [!NOTE]
>
> **El consentimiento biométrico requiere la versión nativa 4.10.0 o posterior.** Para las personas amparadas por la legislación de Illinois, Texas o Colorado, Didit puede solicitar un [consentimiento biométrico](https://docs.didit.me/es/getting-started/biometric-consent.md) explícito antes de la primera captura facial. Las versiones del SDK de React Native que fijan las versiones nativas de iOS y Android en 4.10.0 o posterior muestran ese paso. Las versiones anteriores no pueden mostrarlo: sus sesiones funcionan como antes y la decisión indica que el consentimiento no se recogió (`biometric_consent.reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK"`). Actualiza si verificas a personas de esos estados.***## Instalación### Expo (recomendado)```bash theme={null}
npx expo install @didit-protocol/sdk-react-native
```A continuación, añade el plugin de configuración a tu `app.json` (o `app.config.js`). NFC está habilitado por defecto:```json theme={null}
{
  "expo": {
    "plugins": ["@didit-protocol/sdk-react-native"]
  }
}
```El plugin configura automáticamente ambas plataformas:- **Android:** añade el repositorio Maven de Didit a Gradle, establece la propiedad de Gradle `diditSdkAndroidNfcEnabled` y aplica las reglas de dependencias y empaquetado de BouncyCastle
- **iOS:** añade el podspec de DiditSDK al Podfile (fijado a iOS 15 cuando NFC está habilitado)El plugin no modifica `Info.plist`. Añade las [claves de permisos de iOS](#ios) y, para NFC, los identificadores de selección ISO7816 en `ios.infoPlist` del mismo archivo. `D392F000260100000001` permite que el SDK lea la tarjeta My Number de Japón mediante [JPKI](https://docs.didit.me/es/core-technology/nfc-verification/overview.md#my-number-card-de-japón-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"
        ]
      }
    }
  }
}
```#### Desactivar las dependencias de NFCPara compilar sin compatibilidad con NFC (binario más pequeño, sin requerir capacidad NFC), pasa opciones al plugin:```json theme={null}
{
  "expo": {
    "plugins": [
      [
        "@didit-protocol/sdk-react-native",
        { "iosNfcEnabled": false, "androidNfcEnabled": false }
      ]
    ]
  }
}
```Con NFC desactivado, no necesitas la capacidad NFC de iOS, los entitlements de NFC ni la configuración de aprovisionamiento relacionada con NFC.> [!WARNING]
>
> Este SDK usa módulos nativos (cámara, NFC) que **no están disponibles en Expo Go**. Debes usar una [development build](https://docs.expo.dev/develop/development-builds/introduction/) o ejecutar `npx expo prebuild` para generar los proyectos nativos.### React Native CLI```bash theme={null}
npm install @didit-protocol/sdk-react-native
# or
yarn add @didit-protocol/sdk-react-native
```#### Configuración de iOSAñade el pod DiditSDK a tu `Podfile` (no está en el trunk de CocoaPods). El bloque siguiente respeta la variable de entorno `DIDIT_SDK_IOS_NFC_ENABLED`, de modo que puedes alternar la subspec sin NFC (`DiditSDK/Core`) en el momento de la instalación:```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.9.1/DiditSDK.podspec'
```> [!WARNING]
>
> La etiqueta de la URL del podspec debe coincidir con `diditNativeSdkVersions.ios` de la versión del paquete instalada.
> React Native `4.9.1` fija iOS nativo en `4.9.1` y Android nativo en `4.9.1`. No apuntes el podspec
> a `main`: el paquete depende de esa versión exacta de iOS nativo, así que en cuanto `main` avanza, CocoaPods ve dos requisitos incompatibles para
> `DiditSDK` y todos los `pod install` fallan. El plugin de configuración de Expo genera esta URL por ti; solo la
> ruta de React Native CLI sin Expo necesita escribirla a mano.Después, instala las dependencias:```bash theme={null}
cd ios
bundle exec pod install
```Para recompilar sin las dependencias de NFC, limpia CocoaPods y vuelve a ejecutar con la variable de entorno definida:```bash theme={null}
cd ios
rm -rf Pods Podfile.lock
DIDIT_SDK_IOS_NFC_ENABLED=false bundle exec pod install
```#### Configuración de AndroidAñade el repositorio Maven de Didit al `settings.gradle` de nivel de proyecto:```groovy theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://raw.githubusercontent.com/didit-protocol/sdk-android/main/repository" }
    }
}
```Añade lo siguiente al `android/app/build.gradle` de tu app (dentro del bloque `android { ... }`) para resolver los conflictos de clases duplicadas de BouncyCastle y el archivo `MANIFEST.MF` de OSGI duplicado que pueden provocar las dependencias transitivas de 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'
        }
    }
}
```Para compilar sin las dependencias de NFC de Android (usa el artefacto `me.didit:didit-sdk-core` en lugar de `me.didit:didit-sdk`), añade esto a `android/gradle.properties`:```properties theme={null}
diditSdkAndroidNfcEnabled=false
```Elimina esa propiedad, o establécela en `true`, para usar el SDK de Android completo con NFC.***## Permisos### iOSAñade las siguientes claves al `Info.plist` de tu aplicación. Si falta alguna de las claves de privacidad obligatorias de iOS, iOS cerrará la aplicación en cuanto el SDK acceda al recurso protegido correspondiente.| Permiso | Clave de Info.plist | Descripción | Obligatorio |
| - | - | - | - |
| Cámara | `NSCameraUsageDescription` | Escaneo de documentos y verificación facial | Sí |
| Micrófono | `NSMicrophoneUsageDescription` | Grabación de video para la prueba de vida | Sí |
| Fototeca | `NSPhotoLibraryUsageDescription` | Subida de imágenes de documentos | Sí |
| Ubicación | `NSLocationWhenInUseUsageDescription` | Geolocalización para la prevención del fraude | Sí |
| NFC | `NFCReaderUsageDescription` | Lectura de chips NFC en pasaportes y documentos de identidad | Si usas 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>
```#### Configuración de NFCPara habilitar la lectura NFC de pasaportes y documentos de identidad con chip:1) **Añade la capacidad NFC** en Xcode:
   * Selecciona tu target > **Signing & Capabilities** > **+ Capability** > **Near Field Communication Tag Reading**

2) **Añade los identificadores ISO7816** a `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` permite que el SDK lea la tarjeta My Number de Japón mediante [JPKI](https://docs.didit.me/es/core-technology/nfc-verification/overview.md#my-number-card-de-japón-jpki): sin él, iOS no notifica la tarjeta al SDK. La lectura de la tarjeta My Number aún no está habilitada en producción, y el identificador no cambia nada para otros documentos, así que puedes añadirlo ya.3) **Añade un archivo de entitlements** con la lectura de etiquetas NFC habilitada:```xml theme={null}
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
    <string>TAG</string>
</array>
```Asegúrate de que el perfil de aprovisionamiento de la aplicación incluya la capacidad NFC Tag Reading. Esta configuración de NFC no es necesaria si NFC está deshabilitado.### AndroidLos siguientes permisos están declarados en el `AndroidManifest.xml` del SDK y se fusionan automáticamente:| Permiso | Descripción | Obligatorio |
| - | - | - |
| `INTERNET` | Acceso a la red para la comunicación con la API | Sí |
| `ACCESS_NETWORK_STATE` | Detección de la disponibilidad de red | Sí |
| `CAMERA` | Escaneo de documentos y verificación facial | Sí |
| `NFC` | Lectura de chips NFC en pasaportes y documentos de identidad | Si usas NFC |Las funciones de hardware de cámara y NFC se declaran como opcionales (`android:required="false"`), de modo que tu aplicación puede instalarse en dispositivos que no las tengan.***## Inicio rápido```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;
}
```***## Métodos de integraciónEl SDK admite dos métodos de integración:### Método 1: token de sesión (recomendado para producción)Crea una sesión en tu backend con la [API de creación de sesiones de verificación](https://docs.didit.me/es/sessions-api/create-session.md) y luego pasa el token al 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);
```Este enfoque te da control total para:- Asociar sesiones con tus usuarios (`vendor_data`)
- Definir metadatos personalizados
- Configurar callbacks por sesión### Método 2: ID de workflow (integración más sencilla)Para integraciones más sencillas, el SDK puede crear sesiones directamente con el ID de tu flujo de verificación (workflow):```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 },
});
```***## ConfiguraciónPersonaliza el comportamiento del SDK pasando un objeto `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
});
```Para `startVerificationWithWorkflow`, pasa la configuración dentro de `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,
  },
});
```### Opciones de configuración| Propiedad | Tipo | Valor predeterminado | Descripción |
| - | - | - | - |
| `languageCode` | `string` | Configuración regional del dispositivo | Código de idioma ISO 639-1 (p. ej., `"en"`, `"fr"`, `"ar"`) |
| `showLanguageSelector` | `boolean` | `false` | Muestra el selector de idioma de estilo web en la pantalla de bienvenida |
| `fontFamily` | `string` | Fuente del sistema | Nombre de la familia tipográfica personalizada (debe estar registrada de forma nativa) |
| `loggingEnabled` | `boolean` | `false` | Habilita los registros de depuración del SDK |
| `showCloseButton` | `boolean` | `true` | Muestra el botón de cierre (X) en las pantallas de los pasos de verificación |
| `showExitConfirmation` | `boolean` | `true` | Muestra un diálogo de confirmación cuando el usuario intenta salir |
| `closeOnComplete` | `boolean` | `false` | Cierra automáticamente la interfaz de verificación al completarse |
| `defaultDocumentCamera` | `CameraLens?` | Valor nativo predeterminado (`CameraLens.Back`) | Lente que se usa al abrirse la pantalla de captura del documento |
| `defaultLivenessCamera` | `CameraLens?` | Valor nativo predeterminado (`CameraLens.Front`) | Lente que se usa al abrirse la pantalla de captura facial (prueba de vida) |
| `showDocumentCameraSwitchButton` | `boolean` | `true` | Muestra el selector de cámara durante la captura en la pantalla de captura del documento |
| `showLivenessCameraSwitchButton` | `boolean` | `true` | Muestra el selector de cámara durante la captura en la pantalla de captura facial |### Opciones de cámaraLas opciones de cámara coinciden con las [opciones de cámara del Web SDK](https://docs.didit.me/es/integration/web-sdks/javascript-sdk.md#opciones-de-cámara).
Cada lente es `CameraLens.Front` o `CameraLens.Back`.
Si el dispositivo no tiene la lente solicitada, el SDK usa la primera cámara disponible.
El selector de cámara también se oculta en los dispositivos que tienen una sola cámara.
Establece una opción de selector en `false` para restringir al usuario a la lente predeterminada de ese paso.```tsx theme={null}
import { startVerification, CameraLens } from '@didit-protocol/sdk-react-native';

await startVerification('your-session-token', {
  defaultLivenessCamera: CameraLens.Back,
  showLivenessCameraSwitchButton: false,
});
```> [!NOTE]
>
> **Temas y colores**: los colores, los fondos y la configuración de la pantalla de introducción se definen en tu [configuración de Marca blanca](https://business.didit.me) en la consola de Didit, no en la configuración del SDK. Así se garantiza una imagen de marca coherente en todas las plataformas.***## Idiomas compatiblesEl SDK admite **54 idiomas**. Si no se especifica ningún idioma, el SDK usa la configuración regional del dispositivo, con el inglés como idioma de respaldo.```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 });
```**[Ver todos los idiomas compatibles →](https://docs.didit.me/es/integration/supported-languages.md)*****## Opciones avanzadasEstas opciones solo están disponibles con `startVerificationWithWorkflow`, donde el SDK crea la sesión por ti.### Datos de contacto (autocompletado y notificaciones)Proporciona datos de contacto para autocompletar los formularios de verificación y habilitar las notificaciones por correo electrónico:```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
  },
});
```### Datos esperados (validación cruzada)Proporciona los datos esperados del usuario para validarlos automáticamente con los datos extraídos del documento:```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
  },
});
```Todos los campos de `ExpectedDetails` son opcionales. Consulta [`src/types.ts`](https://github.com/didit-protocol/sdk-react-native/blob/main/src/types.ts) para ver el tipo completo.### Metadatos personalizadosGuarda metadatos JSON personalizados con la sesión (no se muestran al usuario):```tsx theme={null}
const result = await startVerificationWithWorkflow('your-workflow-id', {
  vendorData: 'user-123',
  metadata: '{"internalId": "abc123", "source": "mobile-app"}',
});
```***## Gestión de resultadosTanto `startVerification` como `startVerificationWithWorkflow` devuelven una `Promise<VerificationResult>`. El resultado es una unión discriminada: usa el campo `type` para saber cómo terminó.### Casos de resultado| Caso | Descripción |
| - | - |
| `completed` | El flujo de verificación se completó (consulta `session.status` para conocer el resultado) |
| `cancelled` | El usuario canceló el flujo de verificación |
| `failed` | Se produjo un error durante la verificación |### Propiedades de SessionData| Propiedad | Tipo | Descripción |
| - | - | - |
| `sessionId` | `string` | Identificador único de la sesión |
| `status` | `VerificationStatus` | `Approved`, `Pending` o `Declined` |### Tipos de error| Error | Descripción |
| - | - |
| `sessionExpired` | La sesión ha expirado |
| `networkError` | Problema de conectividad de red |
| `cameraAccessDenied` | No se concedió el permiso de cámara |
| `notInitialized` | El SDK no está inicializado (solo Android) |
| `apiError` | La solicitud a la API falló |
| `unknown` | Otro error, con un mensaje |### Conexión perdidaSi el dispositivo pierde la conexión durante la verificación, el SDK muestra una pantalla "No internet connection" en lugar de dejar un paso cargando.
Sigue comprobando la conexión en segundo plano y cierra la pantalla por sí solo en cuanto se puede volver a conectar con Didit, y el usuario continúa desde el paso en el que estaba.
La pantalla ofrece **Try Again** y, cuando `showCloseButton` es `true` (el valor predeterminado), **Exit Verification**.
Salir termina la verificación con un resultado `failed` cuyo error es `networkError`, para que tu aplicación sepa que el usuario salió debido a la conexión.### Ejemplo completo de gestión de resultados```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;
  }
}
```***## Ejemplo de extremo a extremo (sesión en el backend → SDK de React Native → webhook)La integración lista para producción: tu backend crea la sesión, tu aplicación de RN recibe el `session_token` y el SDK ejecuta el flujo. La decisión final llega a tu backend mediante un webhook: nunca confíes solo en el resultado del lado del cliente.### 1. Backend: crea la sesión```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: intercambia el token e inicia el 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: recibe la decisión final mediante un 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);
});
```Consulta la [guía de webhooks](https://docs.didit.me/es/integration/webhooks.md) para ver los detalles de la verificación de firma HMAC.***## Ejemplo completo```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.