# Results

Every module in an onboarding flow reports its outcome through the SDK's listeners or the value returned by the start call. Most modules deliver a dedicated result object through a step completion event; a few signal completion with only a status field. This page describes promise results, listener payloads, and common error codes.

For the full field list of any result type, see the [Modules](react-native-modules.md) reference and the [API Reference](react-native-api-reference.md).

## How results and errors are delivered

- **Per-step results** arrive through step completion events. Register a listener for a specific module with `IncodeSdk.onStepCompleted({ module, listener })`, and the listener receives a `result` object when that module finishes.
- **In-progress updates** arrive through `IncodeSdk.onStepUpdated({ module, listener })` for the modules that emit them (currently `Conference`, `IdScanFront`, `IdScanBack`, and `SelfieScan`).
- **Session-level outcomes** arrive as the resolved value of the start call. `startOnboarding()`, `startFlow()`, and `startWorkflow()` resolve with `{ status: 'success' }` on completion or `{ status: 'userCancelled' }` if the user cancels. `startOnboardingSection()` resolves with a similar object that also includes `sectionTag`.
- **Errors** surface as rejected promises. The start methods reject with `IncodeSdkFlowError`; `IncodeSdk.initialize()` rejects with `IncodeSdkInitError`.
- **Cleanup**: call `IncodeSdk.deleteLocalUserData()` once you are done with a session to remove locally stored onboarding data (Android only - see [Delete Local Session Data](react-native-getting-started/react-native-delete-local-session-data.md)).

## API results

### Error enums

`IncodeSdk.initialize()` can reject with `IncodeSdkInitError`.

```ts
type IncodeSdkInitErrorCode =
  | 'simulatorDetected'
  | 'testModeEnabled'
  | 'invalidInitParams'
  | 'configError'
  | 'unknown';
```

| Code                | When it fires                                                                                                   |
| ------------------- | --------------------------------------------------------------------------------------------------------------- |
| `simulatorDetected` | Running on a simulator without `testMode: true`.                                                                |
| `testModeEnabled`   | Running on a physical device with `testMode: true`; test mode is only for simulators/emulators.                 |
| `invalidInitParams` | The native project isn't configured correctly (for example, a missing or malformed `Incode-Info.plist` on iOS). |
| `configError`       | `apiConfig` is missing or incomplete.                                                                           |
| `unknown`           | An unrecognized initialization failure.                                                                         |

Flow APIs can reject with `IncodeSdkFlowError`.

```ts
type IncodeSdkFlowErrorCode =
  | 'simulatorDetected'
  | 'rootDetected'
  | 'hookDetected'
  | 'virtualEnvDetected'
  | 'permissionsDenied'
  | 'jailbreakDetected'
  | 'faceAuthenticationFailed'
  | 'sslPinningFailed'
  | 'locationUnavailable'
  | 'unknown';
```

| Code                       | When it fires                                                                       |
| -------------------------- | ----------------------------------------------------------------------------------- |
| `simulatorDetected`        | Running on a simulator.                                                             |
| `rootDetected`             | The SDK detected that the device is rooted.                                         |
| `hookDetected`             | The SDK detected a runtime hooking framework on the device.                         |
| `virtualEnvDetected`       | The SDK detected that the app is running in a virtual environment.                  |
| `permissionsDenied`        | The user denied a permission required by the flow (typically camera or microphone). |
| `jailbreakDetected`        | The SDK detected that the device is jailbroken. iOS only.                           |
| `faceAuthenticationFailed` | A face authentication step failed.                                                  |
| `sslPinningFailed`         | SSL pinning validation failed.                                                      |
| `locationUnavailable`      | Required location data could not be obtained.                                       |
| `unknown`                  | Catch-all for unrecognized flow failure.                                            |

### startOnboarding, startFlow, and startWorkflow

Successful completion resolves with:

```json
{ "status": "success" }
```

User cancellation resolves with:

```json
{ "status": "userCancelled" }
```

Some legacy documentation and native payloads may refer to the same state as `user_cancelled`.

### setupOnboardingSession

```ts
{
  interviewId: string;
  token: string;
}
```

### startOnboardingSection

```ts
{
  status: 'success' | 'userCancelled';
  sectionTag: string;
}
```

### startFaceLogin

```ts
{
  faceMatched: boolean;
  spoofAttempt: boolean;
  image?: { pngBase64?: string; encryptedBase64?: string };
  customerUUID?: string;
  interviewId?: string;
  interviewToken?: string;
  token?: string;
  transactionId?: string;
  hasFaceMask?: boolean;
}
```

Example Face Login response:

```json
{
  "faceMatched": true,
  "spoofAttempt": false,
  "image": {
    "pngBase64": "...PNG Base 64 encoded",
    "encryptedBase64": "...PNG Encrypted Base 64 encoded"
  },
  "customerUUID": "exampleCustomerUUID",
  "interviewId": "exampleInterviewID",
  "interviewToken": "exampleInterviewToken",
  "token": "exampleToken",
  "transactionId": "Unique Authentication attempt ID",
  "hasFaceMask": false
}
```

For 1:1 Face Login, `faceMatched` can be `false` when faces do not match or when the user with the supplied customer token and `customerUUID` is not found. For 1:N Face Login, `faceMatched` can be `false` when the captured face is not associated with an approved user in the database.

`hasFaceMask` is available on iOS only; Android forces the user to remove the mask before login is performed.

### getUserScore

Returns the same `UserScore` data that the `UserScore` module provides:

```ts
{
  overallScore: string;
  status: 'ok' | 'warn' | 'unknown' | 'fail' | 'manual';
  facialRecognitionScore: string;
  existingUser: boolean;
  idVerificationScore: string;
  livenessOverallScore: string;
}
```

❗{/* [SME input needed: the `status` values appear to roughly map to session statuses (`ok` = Pass, `warn` = Warn, `fail` = Fail, `manual` = Manual Review), but this mapping is unconfirmed and `unknown` has no obvious equivalent. Confirm whether these SDK values correspond to the session statuses, and define what `unknown` indicates. Note: UserScore does not appear to exist as a module on the native Android or iOS SDKs, so definitions could not be sourced there. Escalation candidate: needs product/scoring-team knowledge.] */}

```ts
await IncodeSdk.getUserScore({ mode: 'accurate' });
```

`accurate` fetches server-side results and can take longer. `fast` uses on-device processing. The `getUserScore({ mode })` method and the `UserScore` module's `mode` parameter behave identically.

### approve

```ts
{
  status: 'approved' | 'failed';
  id: string;
  customerToken: string;
}
```

- `status`: `approved` or `failed`.
- `id`: The customer UUID.
- `customerToken`: The customer's session token.

Use the `forceApproval` argument when calling `approve()`. Some older text called this `forceApprove`.

### faceMatch

Returns a `FaceMatch` completion event payload.

### Methods without a meaningful payload

`finishOnboardingFlow`, `deleteLocalUserData`, `showCloseButton`, `setTheme`, `setUXConfig`, `setString`, `setQuantityStrings`, `setLocalizationLanguage`, `setFaceAuthenticationHint`, and `setSdkMode` are primarily command-style methods.

`checkOnDemandResourcesDownloaded`, `downloadOnDemandResources`, and `removeOnDemandResources` do return a meaningful payload on Android - a `{ status: string }` object (`"true"`/`"false"` for the check, `"success"` for download/remove; see `IncodeSdkModule.kt`). See [Dynamic Delivery Usage Guide](react-native-dynamic-delivery-usage-guide.md) for usage.

## Listener results

The SDK offers several types of listeners:

- user cancellation
- tracking events
- step completion, for each module individually
- step error, for each module individually
- step update, for each module individually

### User cancellation

If the user cancels onboarding, `startOnboarding`, `startFlow`, and `startWorkflow` return `status: 'userCancelled'`.
On both platforms, the user can cancel by pressing the close button that can be enabled using `IncodeSdk.showCloseButton(true)`. On Android, the user can also cancel by pressing the back key.

### Session created

When an onboarding session gets created, the information about the session can be obtained via `IncodeSdk.onSessionCreated`.

```ts
IncodeSdk.onSessionCreated((session) => {
  console.log('Onboarding session created, interviewId: ' + session.interviewId);
});
```

The session event includes:

- `interviewId`: string. Unique identifier of the onboarding session.
- `token`: string. Token created for this onboarding session.

### Tracking events

When onboarding has started, tracking events can be obtained using `onEvents`.

```ts
IncodeSdk.onEvents((eventBatch) => {
  for (const event of eventBatch.events) {
    console.log(event.event, event.data);
  }
});
```

The listener receives:

- `events`: `EventDetails[]`. Array of emitted events.
- `event`: string. Unique identifier of the event.
- `data`: string. JSON string with additional event details.

❗{/* [SME input needed: event names for `onEvents` aren't typed or enumerated in the SDK; they pass through from the native SDKs. Confirm one of: (a) the full set of event names, (b) where customers can find the list, or (c) that these are internal events not intended as a documented contract customers should depend on. Escalation candidate: needs product/SDK-team knowledge.] */}

### Step completion

When a step in the configured onboarding flow is completed, register a listener via `IncodeSdk.onStepCompleted`. The listener config takes the module name and callback.

```ts
const unsubscribe = IncodeSdk.onStepCompleted({
  module: 'SelfieScan',
  listener: (event) => {
    console.log(event.result);
  },
});
```

Step completion events are delivered through `onStepCompleted()`. In-progress events are delivered through `onStepUpdated()`.

### Step error

When a module in the flow emits an error, register a listener via `IncodeSdk.onStepError`. The listener config takes the module name and callback.

```ts
const unsubscribe = IncodeSdk.onStepError({
  module: 'FaceMatch',
  listener: (event) => {
    console.log('FaceMatch error', event);
  },
});
```

`onStepError` currently fires for `Phone`, `DocumentScan`, `Geolocation`, `Signature`, `VideoSelfie`, `IdScan`, `Conference`, `SelfieScan`, `FaceMatch`, `QrScan`, `Captcha`, and `UserScore`.

The event shape isn't fully consistent across modules: most report a flat `status` value, `QrScan` and `Conference` nest it inside a `result` object, and `IdScan` nests separate front/back status values.

### Step update

When a step in the configured flow is updated, register a listener via `IncodeSdk.onStepUpdated`. The listener config takes the module name and callback.

```ts
IncodeSdk.onStepUpdated({
  module: 'IdScanFront',
  listener: (event) => {
    console.log('ID Scan Front Attempt: ', event.result);
    console.log('ID Scan Front Attempt allAttemptsExhausted:', event.result.allAttemptsExhausted);
  },
});
```

`onStepUpdated` currently emits updates for `Conference`, `IdScanFront`, `IdScanBack`, and `SelfieScan`.

## Module callback payloads

### Aes

This module enables an advanced electronic signature to ensure legally binding and compliant document signing with enhanced security and authentication measures.

Example success response:

```json
{
  "status": "success",
  "step": "Aes"
}
```

The field `status` can have one of the following values: `success` or `fail`.

Example failure response:

```json
{
  "status": "fail",
  "error": "noDocuments",
  "step": "Aes"
}
```

❗{/* [SME input needed: source-level review confirmed the Aes module has 2 possible `error` values but only `noDocuments` is currently documented. Confirm the other value and what each indicates. Escalation candidate: needs product/SDK-team knowledge.] */}

### Antifraud

This module gives the ability to compare the current interview with existing interviews and customers to detect anomalies that could be signs of fraud.

Example success response:

```json
{
  "status": "success",
  "step": "Antifraud"
}
```

The field `status` can have one of the following values: `success` or `fail`.

❗{/* [SME input needed: only a success response is documented for Antifraud. Confirm whether a failure response includes any additional fields (such as an `error` field, as the Aes module has), or whether failure is conveyed solely through `status: "fail"` in the same structure. Escalation candidate: needs product/SDK-team knowledge.] */}

### Approve

Adding this module to the flow instructs the Incode server to perform the approval of the user.

Example response:

```json
{
  "result": { "status": "approved", "id": "customerUUID", "customerToken": "customerToken" },
  "step": "Approve"
}
```

The `status` field can be `approved` or `failed`. A `failed` status is a normal, expected outcome, not an error.

### Captcha

This module asks the user to enter an OTP generated for the current session. If the user enters an incorrect OTP too many times, the flow is terminated.

Example success response:

```json
{
  "result": {
    "status": "success",
    "response": "ABCDEF"
  }
}
```

Captcha failure rejects the onboarding promise rather than returning a result. There is no module error listener for this module.

### CombinedConsent

This module asks the user for data sharing consent.

Example success response:

```json
{
  "status": "success",
  "step": "CombinedConsent"
}
```

The `status` field can be `success` or `fail`.

If the user declines to give data sharing consent, the onboarding flow ends with a status of `userCancelled`.

❗{/* [SME input needed: the `status` field can be `success` or `fail`, but the only documented non-success path is the user declining, which ends the flow with `userCancelled` rather than `fail`. Confirm under what circumstances `status: "fail"` occurs versus a `userCancelled` flow outcome. Escalation candidate: needs product/SDK-team knowledge.] */}

### Conference

This module starts a video conference call.

Example success response:

```json
{
  "step": "Conference",
  "result": {
    "status": "success"
  }
}
```

Example failure response:

```json
{
  "step": "Conference",
  "result": {
    "status": "error"
  }
}
```

The `result.status` field can be `success`, `userCancelled`, `invalidSession`, or `error`.

### CURP

This module asks the user to input their CURP information for validation with the RENAPO service. CURP is a personal identifier used in México.

Example success response:

```json
{
  "status": "success",
  "curp": "exampleCurp",
  "step": "CURP"
}
```

The `status` field can be `success` or `fail`.

❗{/* [SME input needed: only a success response is documented for CURP. Confirm whether a failure response includes any additional fields, or whether failure is conveyed solely through `status: "fail"` in the same structure. Escalation candidate: needs product/SDK-team knowledge.] */}

### CustomWatchlist

This module checks whether the user appears on a custom watchlist configured in the Incode Dashboard.

Example success response:

```json
{
  "status": "success",
  "step": "CustomWatchlist"
}
```

The `status` field can be `success` or `fail`. `success` means a match was found on the watchlist, which typically warrants further review. `fail` means no match was found.

### DocumentScan

This module captures a document and attempts to read the address from it.

If the user skips this step, the response contains blank values rather than nil or an error.

Example success response:

```json
{
  "result": {
    "address": { // parsed OCR data
      "city": "Springfield",
      "colony": "Springfield",
      "postalCode": "555555",
      "state": "Serbia",
      "street": "Evergreen terrace"
    },
    "data": {"raw JSON OCR data"},
    "type": "addressStatement",
    "image": {"pngBase64": "/9j/4AAQSkZJRgABAQAAAQABAAD/4..."}
  },
  "step": "DocumentScan"
}
```

The `result` object includes:

- `address`: parsed OCR data from the document.
- `data`: iOS only. A JSON string containing document-specific data, when available. This field is currently untyped in the SDK. On Android, there is no top-level `data` field; medical-document data is nested under `insuranceCard` instead.
- `type`: the document type captured.
- `image`: the captured document image as a base64-encoded PNG.

Example failure response:

```json
{
  "status": "permissionsDenied",
  "step": "DocumentScan"
}
```

The `status` field can be `permissionsDenied`, `simulatorDetected`, or `unknown`.

❗{/* [SME input needed: the `type` field has 6 possible values (confirmed by source review) but the values themselves are not documented. Provide the full list of `type` values. Escalation candidate: needs product/SDK-team knowledge.] */}

❗{/* [SME input needed: the failure example previously showed `status: "userCancelled"`, but `userCancelled` is not in the documented `status` value list. Confirm whether `userCancelled` is a valid `status` value for DocumentScan.] */}

### eKYB

This module validates a business identity using business information. Sources can include business name, addresses, city, state, postal code, and bank account number.

Example success response:

```json
{
  "status": "success",
  "step": "eKYB"
}
```

The `status` field can be `success` or `fail`.

❗{/* [SME input needed: only a success response is documented for eKYB. Confirm whether a failure response includes any additional fields, or whether failure is conveyed solely through `status: "fail"` in the same structure. Escalation candidate: needs product/SDK-team knowledge.] */}

### eKYC

This module validates a user identity using the user's information. Sources can include data obtained from an ID, proof of address, or manual capture.

Example success response:

```json
{
  "status": "success",
  "step": "eKYC"
}
```

The `status` field can be `success` or `fail`.

❗{/* [SME input needed: only a success response is documented for eKYC. Confirm whether a failure response includes any additional fields, or whether failure is conveyed solely through `status: "fail"` in the same structure. Escalation candidate: needs product/SDK-team knowledge.] */}

### Email

This module asks the user to enter their email address.

Example success response:

```json
{
  "result": { "email": "email@example.com", "status": "success" },
  "step": "Email"
}
```

Example failure response:

```json
{
  "status": "fail",
  "step": "Email"
}
```

The `status` field can be `success` or `fail`.

### FaceAuthentication

This module identifies a previously registered user using face recognition. It can be used to grant access to parts of your application or authorize high-value operations with low friction.

Example success response:

```json
{
  "result": {
    "status": "success",
    "customerUUID": "1234567890",
    "selfieBase64": "abcdefg",
    "selfieEncryptedBase64": "abcdefg",
    "error": null
  },
  "step": "FaceAuthentication"
}
```

The `result.status` field can be `success` or `fail`. `result.error` can be one of 21 values: `inactiveSession`, `nonexistentCustomer`, `lensesDetected`, `faceMaskDetected`, `headCoverDetected`, `closedEyesDetected`, `faceTooDark`, `spoofAttemptDetected`, `userIsNotRecognized`, `selfieImageLowQuality`, `hintNotProvided`, `faceNotFound`, `faceCroppingFailed`, `faceTooSmall`, `faceTooBlurry`, `badPhotoQuality`, `processingError`, `badRequest`, `deniedCameraPermissions`, `userCancelled`, or `unknown`.

### FaceMatch

This module checks whether the face from the scanned ID or passport and the face obtained from the SelfieScan module are a match.

Example success response:

```json
{
  "result": {
    "status": "match",
    "confidence": 1,
    "nameMatched": false,
    "existingUser": false,
    "existingInterviewId": "exampleInterviewID",
    "idCategory": "primary"
  },
  "step": "FaceMatch"
}
```

The `result.status` field can be `match` or `mismatch`. FaceMatch uses this same `result` structure for both matches and mismatches.

### Geolocation

This module captures the current location of the user.

Example success response:

```json
{
  "result": {
    "city": "Springfield",
    "colony": "Springfield",
    "postalCode": "555555",
    "state": "Serbia",
    "street": "Evergreen terrace"
  },
  "step": "Geolocation"
}
```

❗{/* [SME input needed: confirm the failure response structure for Geolocation. On failure it can report `permissionsDenied`, `unknownError`, `noLocationExtracted`, or `locationUnavailable`, but it's unconfirmed how the failure response is shaped. Escalation candidate: needs product/SDK-team knowledge.] */}

### GlobalWatchlist

This module checks customer identities against sources of sanctions, Politically Exposed Persons (PEPs), and watchlists.

Example success response:

```json
{
  "status": "success",
  "step": "GlobalWatchlist"
}
```

The `status` field can be `success` or `fail`. `success` means a match was found on the watchlist, which typically warrants further review. `fail` means no match was found.

### GovernmentValidation

This module asks the user to input their information for validation against government services.

Example success response:

```json
{
  "status": "success",
  "step": "GovernmentValidation"
}
```

The `status` field can be `success` or `fail`.

❗{/* [SME input needed: only a success response is documented for GovernmentValidation. Confirm whether a failure response includes any additional fields, or whether failure is conveyed solely through `status: "fail"` in the same structure. Escalation candidate: needs product/SDK-team knowledge.] */}

### IdScan

Adding `{ module: 'IdScan' }` to a `flowConfig` captures both sides of the ID in one combined module. On success, it fires two separate step completion events, `IdScanFront` and `IdScanBack`, rather than a single combined `IdScan` event. `onStepCompleted` does not accept `IdScan` as a `module` value; listen for `IdScanFront` and `IdScanBack` instead.

On error, `IdScan` fires one combined error event covering both sides, distinct from the individual front/back success statuses. Register it with `IncodeSdk.onStepError({ module: 'IdScan', listener })`:

```json
{
  "module": "IdScan",
  "status": {
    "front": "ok",
    "back": "errorGlare"
  },
  "data": {"raw JSON OCR data"}
}
```

`status.front` and `status.back` can each be `ok` or one of several values indicating a scanning issue. The Incode UI informs the user about these errors and attempts the scan several times before responding with an error. Other values: `errorClassification`, `noFacesFound`, `errorCropQuality`, `errorGlare`, `errorReadability`, `errorSharpness`, `errorTypeMismatch`, `userCancelled`, `unknownError`, `shadow`, `errorAddress`, `errorPassportClassification`.

### IdScanBack

Captures the back side of an ID document.

Example success response:

```json
{
  "result": {
    "status": "ok",
    "classifiedIdType": "Voter Identification",
    "chosenIdType": "id",
    "idCategory": "primary",
    "image": { "pngBase64": "..." },
    "croppedFace": { "pngBase64": "..." }
  },
  "step": "IdScanBack"
}
```

❗{/* [SME verify: confirm the example response structure and field placement (particularly whether these fields sit inside a `result` object as shown). The example JSON was constructed by AI using the documented field list, not copied from source.] */}

The `result` object includes:

- `image`: `IncdImage` object containing `pngBase64` of the captured back ID.
- `croppedFace`: `IncdImage` object containing `pngBase64` of the cropped face from the back ID.
- `classifiedIdType`: string. The ID type as classified by Incode, for example `Voter Identification`.
- `chosenIdType`: string. The ID type the user chose to capture: `id` or `passport`.
- `idCategory`: string. The ID category: `primary` or `secondary`.
- `status`: string. The scan outcome. When the value is anything other than `ok`, the scan or validation did not complete successfully. The Incode UI informs the user and retries several times before responding with an error. Possible non-success values: `errorClassification`, `noFacesFound`, `errorGlare`, `errorReadability`, `errorSharpness`, `errorTypeMismatch`, `userCancelled`, `unknownError`, `errorShadow`, `errorPassportClassification`.
- `failReason`: string (optional). The reason for the scan failure, if applicable.
- `issueName`: string (optional). The name of the issuing authority of the document.
- `issueYear`: number (optional). The year the document was issued.
- `countryCode`: string (optional). The country code of the document.
- `allAttemptsExhausted`: boolean (optional). Indicates whether all capture attempts have been exhausted.

### IdScanFront

Captures the front side of an ID document.

Example success response:

```json
{
  "result": {
    "status": "ok",
    "classifiedIdType": "Voter Identification",
    "chosenIdType": "id",
    "idCategory": "primary",
    "image": { "pngBase64": "..." },
    "croppedFace": { "pngBase64": "..." }
  },
  "step": "IdScanFront"
}
```

❗{/* [SME verify: confirm the example response structure and field placement (particularly whether these fields sit inside a `result` object as shown). The example JSON was constructed by AI using the documented field list, not copied from source.] */}

The `result` object includes:

- `image`: `IncdImage` object containing `pngBase64` of the captured front ID.
- `croppedFace`: `IncdImage` object containing `pngBase64` of the cropped face from the front ID.
- `classifiedIdType`: string. The ID type as classified by Incode, for example `Voter Identification`.
- `chosenIdType`: string. The ID type the user chose to capture: `id` or `passport`.
- `idCategory`: string. The ID category: `primary` or `secondary`.
- `status`: string. The scan outcome. When the value is anything other than `ok`, the scan or validation did not complete successfully. The Incode UI informs the user and retries several times before responding with an error. Possible non-success values: `errorClassification`, `noFacesFound`, `errorGlare`, `errorReadability`, `errorSharpness`, `errorTypeMismatch`, `userCancelled`, `unknownError`, `errorShadow`, `errorPassportClassification`.
- `failReason`: string (optional). The reason for the scan failure, if applicable.
- `issueName`: string (optional). The name of the issuing authority of the document.
- `issueYear`: number (optional). The year the document was issued.
- `countryCode`: string (optional). The country code of the document.
- `allAttemptsExhausted`: boolean (optional). Indicates whether all capture attempts have been used.

### MLConsent

This module asks the user for machine learning consent.

Example success response:

```json
{
  "status": "success",
  "step": "MLConsent"
}
```

The `status` field can be `success` or `fail`.

❗{/* [SME input needed: confirm what happens when the user declines machine learning consent. Does the module return `status: "fail"`, or does the flow end with `userCancelled` (as CombinedConsent does)? Escalation candidate: needs product/SDK-team knowledge.] */}

### Name

This module asks the user to enter their name.

Example success response:

```json
{
  "status": "success",
  "name": "exampleName",
  "step": "Name"
}
```

The `status` field can be `success` or `fail`.

❗{/* [SME input needed: only a success response is documented for Name. Confirm whether a failure response includes any additional fields, or whether failure is conveyed solely through `status: "fail"` in the same structure. Escalation candidate: needs product/SDK-team knowledge.] */}

### NFCScan

This module reads and verifies chip data from ePassports or ID cards to validate document authenticity, detect tampering, and enhance anti-spoofing.

Example success response:

```json
{
  "result": {
    "status": "success",
    "birthDate": "900101",
    "compositeCheckDigit": "7",
    "dateOfBirthCheckDigit": "3",
    "documentCode": "TD3",
    "documentNumber": "123456789",
    "documentNumberCheckDigit": "5",
    "expirationDateCheckDigit": "2",
    "expireAt": "300101",
    "gender": "M",
    "issuingStateOrOrganization": "USA",
    "nationality": "USA",
    "optionalData1": "ABCDEFGHI",
    "optionalData2": null,
    "personalNumber": "987654321",
    "personalNumberCheckDigit": "4",
    "primaryIdentifier": "DOE",
    "secondaryIdentifier": "JOHN MICHAEL"
  },
  "step": "NFCScan"
}
```

The `result.status` field can be `success` or `fail`.

❗{/* [SME input needed: only a success response is documented for NFCScan. Confirm whether a failure response includes any additional fields (such as an error code or reason), or whether failure is conveyed solely through `status: "fail"` in the same structure. Escalation candidate: needs product/SDK-team knowledge.] */}

Date fields such as `birthDate` and `expireAt` use `YYMMDD` format on Android. On iOS, they are returned as a native-formatted date string. All other fields are plain strings.

### OCREdit

This module shows the user the parsed OCR data from their ID, which they can optionally edit.

Example success response:

```json
{
  "status": "success",
  "step": "OCREdit"
}
```

The `status` field can be `success` or `fail`.

❗{/* [SME input needed: only a success response is documented for OCREdit. Confirm whether a failure response includes any additional fields, or whether failure is conveyed solely through `status: "fail"` in the same structure. Escalation candidate: needs product/SDK-team knowledge.] */}

### Phone

This module asks the user to enter their phone number.

Example success response:

```json
{
  "result": { "phone": "+15555555555", "resultCode": "success" },
  "step": "Phone"
}
```

The `result.resultCode` field can be `success`.

Example failure response:

```json
{
  "status": "error",
  "step": "Phone"
}
```

The `status` field can be `invalidSession`, `userCancelled`, or `error`.

### ProcessId

Processes the ID after the front and back captures. ProcessId does not have its own status or failure result; success or failure comes from the separate `IdScanFront` and `IdScanBack` events.

Example success response:

```json
{
  "result": {
    "data": {
      "fullAddress": "123 Evergreen Terrace, Springfield",
      "address": {
        "city": "Springfield",
        "colony": "Springfield",
        "postalCode": "555555",
        "state": "Serbia",
        "street": "Evergreen Terrace"
      },
      "birthDate": 631152000,
      "expirationDate": "300101",
      "gender": "M",
      "name": "JOHN DOE",
      "issueDate": "200101",
      "numeroEmisionCredencial": "01"
    },
    "extendedOcrData": "{...}"
  },
  "step": "ProcessId"
}
```

❗{/* [SME verify: confirm the example response structure and field placement. The example JSON was constructed by AI using the documented field list, not copied from source. In particular, confirm the format of `birthDate` (shown as epoch time), `expirationDate`, and `issueDate`, which may use different formats.] */}

The `result` object includes:

- `data`: the `IdScanOcrData` object containing the parsed OCR data. Confirmed identical on iOS and Android:
  - `fullAddress`
  - `address`: nested object with `city`, `colony`, `postalCode`, `state`, `street`
  - `birthDate`
  - `expirationDate`
  - `gender`
  - `name`
  - `issueDate`
  - `numeroEmisionCredencial`
- `extendedOcrData`: string. Raw JSON containing the full OCR data, for example `exteriorNumber`, `interiorNumber`, `typeOfId`, `documentFrontSubtype`.

Notes:

- `result.data.birthDate` is in epoch time.

### QrScan

This module captures the QR code on the back of the ID, extracts the data from it, and sends it to the server.

Example success response:

```json
{
  "result": { "idCic": "exampleIdCic" },
  "step": "QrScan"
}
```

❗{/* [SME verify: the example response was constructed by AI using the confirmed field (`idCic`, a string, no status). Confirm the exact wrapper structure (whether `idCic` sits inside a `result` object and whether a `step` field is included).] */}

The `result` object contains a single field, `idCic` (a string). QrScan does not return a `status`.

### SelfieScan

This module captures a selfie from the user.

Example success response:

```json
{
  "result": { "spoofAttempt": false, "status": "success", "allAttemptsExhausted": false },
  "step": "SelfieScan",
  "image": {
    "pngBase64": "...PNG Base 64 encoded",
    "encryptedBase64": "...PNG Encrypted Base 64 encoded"
  }
}
```

The response includes:

- `result.spoofAttempt`: boolean. Indicates whether a spoof attempt was detected.
- `result.status`: string. The capture outcome.
- `result.allAttemptsExhausted`: boolean (optional). Indicates whether all capture attempts have been exhausted.
- `image.pngBase64`: the captured selfie as a base64-encoded PNG.
- `image.encryptedBase64`: the captured selfie as an encrypted base64-encoded PNG.

Example failure response:

```json
{
  "status": "permissionsDenied",
  "step": "SelfieScan"
}
```

The `status` field can be `none`, `permissionsDenied`, `simulatorDetected`, or `spoofDetected`.

### Signature

This module asks the user to add a digital signature by signing on a canvas.

Example success response:

```json
{
  "result": { "status": "success", "image": "...PNG Base 64 encoded" },
  "step": "Signature"
}
```

Example failure response:

```json
{ "status": "error", "step": "Signature" }
```

The `status` field can be `error` or `invalidSession`.

### UserConsent

This module asks the user to give consent.

Example success response:

```json
{
  "status": "success",
  "step": "UserConsent"
}
```

If the user declines to give consent, the onboarding flow ends with a status of `userCancelled`.

### UserScore

This module displays the user score to the user.

Example success response:

```json
{
  "result": {
    "data": {
      "existingUser": true,
      "facialRecognitionScore": "0.0/100",
      "idVerificationScore": "79.0/100",
      "livenessOverallScore": "95.2/100",
      "overallScore": "0.0/100",
      "status": "fail"
    },
    "extendedUserScoreJsonData": "{..}"
  },
  "step": "UserScore"
}
```

The `result` object includes:

- `data`: the parsed user score data.
- `extendedUserScoreJsonData`: a raw JSON string containing the full user score data.

The `result.data.status` field can be `ok`, `warn`, `unknown`, `manual`, or `fail`.

❗{/* [SME input needed: the `status` values appear to map to session statuses (`ok` = Pass, `warn` = Warn, `fail` = Fail, `manual` = Manual Review), but this mapping is unconfirmed and `unknown` has no obvious equivalent. Confirm whether these SDK values correspond to the session statuses, and define what `unknown` indicates. Note: UserScore does not appear to exist as a module on the native Android or iOS SDKs, so definitions could not be sourced there. Escalation candidate: needs product/scoring-team knowledge.] */}

❗{/* [SME input needed: `extendedUserScoreJsonData` is a raw JSON string with no schema defined in the SDK. Confirm one of: (a) the schema/fields it contains, (b) where customers can find it documented, or (c) that it's not intended as a documented contract customers should depend on. Escalation candidate: needs product/SDK-team knowledge.] */}

### VideoSelfie

This module records the device's screen while the user takes a selfie, presents their ID, answers a series of questions, and accepts the terms and conditions. The recorded video is then uploaded and stored for later use.

❗{/* [SME action needed: VideoSelfie's result type is currently an empty placeholder in the SDK, so there is no result shape to document yet. This is an SDK-side gap, not a documentation gap. Flag to the SDK team to define the result type, then document it here once available.] */}

<br />
