> For the complete documentation index, see [llms.txt](https://valify.gitbook.io/valify-ios-sdk-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://valify.gitbook.io/valify-ios-sdk-documentation/document-capture/android-native-sdk/sdk-response.md).

# SDK Response

### SDK Listener

Use the following code snippet to receive SDK callbacks

<pre class="language-java"><code class="lang-java"><strong>VIDVOCRListener vidvOcrListener= new VIDVOCRListener() {
</strong>            @Override
            public void onOCRResult(VIDVOCRResponse response) {
                if (response instanceof Success) {
                   
                     
                     
                     //an example code to use the response in your app : 
                     String firstName = ((Success) response).getData().getOcrResult().getFirstName();
                     //firstName variable will hold the first name of the scanned National ID
                     
                     
                     // Add your own code
                     
                     
                } else if (response instanceof CapturedImages) {
                
               
                         // Add your own code  
                                       
                } else if (response instanceof UserExit) {
                
                      // Add your own code
                
                } else if (response instanceof ServiceFailure) {
                
                        // Add your own code
                
                } else if (response instanceof BuilderError) {
                
                      // Add your own code
                
                }
            }
        };
</code></pre>

### Document verification plus - Case Handling

When using `VIDVOCRResult.getData()`, the returned `ocrResult` may include a `documentVerificationPlus`object.\
This object contains validation flags and quality signals that help you determine whether the document should be accepted, reviewed, recaptured, or rejected.

***

#### Fields Returned Under `documentVerificationPlus`

| Field               | Type          | Meaning                                                                           |
| ------------------- | ------------- | --------------------------------------------------------------------------------- |
| `frontDataValidity` | boolean       | Overall validity of the front side based on greyscale flags + invalid fields list |
| `backDataValidity`  | boolean       | Overall validity of the back side based on greyscale flags + invalid fields list  |
| `isFrontGreyscale`  | boolean       | Indicates whether the front side is greyscale                                     |
| `isBackGreyscale`   | boolean       | Indicates whether the back side is greyscale                                      |
| `expired`           | boolean       | Whether the document is recognized as expired                                     |
| `reviewRequired`    | List\<String> | Fields that require attention (e.g. Nid, gender, expirydate…)                     |

***

#### How to Read These Values

* `frontDataValidity` and `backDataValidity` act as **parent flags**\
  → You can take action directly based on them if you want a simple validation flow.
* For more control, you can check detailed signals:
  * use greyscale flags if you want to **reject black-and-white copies**
  * use `reviewRequired`to apply different logic per field\
    e.g. reject if nid is invalid but allow if *gender* is inconsistent

This allows fully customizable decision logic depending on your business rules.

#### **Example Handling Logic**

```kotlin
//Note that all decisions taken in this code are just an example of how you can handle
//the logic and that you can take the preferred action according to your business needs
val flags = result.data?.ocrResult?.documentVerificationPlus
when {
// --------------------- GENERIC VALIDATION RESULTS --------------------- //

// Quick validation using global parent flags
flags?.frontDataValidity == false || flags?.backDataValidity == false -> {
     AlertDialog(
                onDismissDialog = {showRetryOCRSDKDialog.value = false}, onClick = {
                // start ocr sdk
                }
            }, title = "The document failed validation checks." ,"Retry")
}

// Greyscale document detection
flags?.isFrontGreyscale == true || flags?.isBackGreyscale == true -> {
    requestRecapture("Document appears to be black & white.")  // Developer replaces with custom retry logic
}

// Document is expired
flags?.isExpired == true -> {
    AlertDialog(
                onDismissDialog = {showRetryOCRSDKDialog.value = false}, onClick = {
                // start ocr sdk
                }
            }, title = "OCR", "Expired ID, Please try again with your recent National ID." ,"Retry")
}

 // One or more fields require review
    flags?.reviewRequired.isNotEmpty() == true -> {
        showError("Some fields require manual review.")   // Replace with custom handling
    }


// --------------------- FIELD-LEVEL CASES (HANDLE INDIVIDUALLY) --------------------- //

"serial_number" in flags?.reviewRequired.orEmpty() -> {
    AlertDialog(
                onDismissDialog = {showRetryOCRSDKDialog.value = false}, onClick = {
                // start ocr sdk
                }
            }, title = "OCR", "Serial number is incorrect. Please try again" ,"Retry")}
}

"back_nid" in flags?.reviewRequired.orEmpty() ||
"front_nid" in flags?.reviewRequired.orEmpty() -> {
    requestRecapture("NID Mismatch") // Developer replaces with custom retry logic
}
"date_of_birth" in flags?.reviewRequired.orEmpty() -> showError("Date of birth could not be verified.") // Replace with custom handling
"street" in flags?.reviewRequired.orEmpty() -> showError("Street address is empty.") // Replace with custom handling
"police_station" in flags?.reviewRequired.orEmpty() -> showError("Police station field needs review.") // Replace with custom handling
"governorate" in flags?.reviewRequired.orEmpty() -> showError("Governorate value could not be verified.") // Replace with custom handling
"birth_governorate" in flags?.reviewRequired.orEmpty() -> showError("Birth governorate requires review.") // Replace with custom handling
"expiry_date" in flags?.reviewRequired.orEmpty() -> showError("Expiry date is missing or invalid.") // Replace with custom handling
"release_date" in flags?.reviewRequired.orEmpty() -> showError("Release date did not pass validation.") // Replace with custom handling

else -> {
}
}

```

### Advance confidence  - Case Handling

When using `VIDVOCRResult.getData()`, the returned `ocrResult` may include a `advancedConfidence` object.\
This object contains manipulation flags that help you determine whether the document should be accepted, reviewed, recaptured, or rejected.

***

#### Fields Returned Under `advanceConfidence`

| Field                      | Type | Meaning                                                          |
| -------------------------- | ---- | ---------------------------------------------------------------- |
| fraudDetectionZone         | int  | Parent zone flag → Result of face + image manipulation combined  |
| faceFraudZone              | int  | Fraud confidence specifically related to face physical tampering |
| frontImageManipulationZone | int  | Indicates signs of front image physical manpulation              |

#### Zone Meaning

| Value | Color  | Meaning                                   |
| ----- | ------ | ----------------------------------------- |
| 0     | Green  | No manipulation detected                  |
| 1     | Yellow | Requires human review (suspicious)        |
| 2     | Red    | Strong indicators of fraud / manipulation |

***

#### **Example Handling Logic**

```kotlin
//Note that all decisions taken in this code are just an example of how you can handle
//the logic and that you can take the preferred action according to your business needs
val fraud = result.data?.ocrResult?.advancedConfidence

// Generic Handling
when (fraud?.fraudDetectionZone) {
    1 -> showWarning("Document may be manipulated — review recommended") // Replace with custom handling
    2 -> requestRecapture("Possible fraud detected — please retry with clear document")
}

// Detailed Handling
when {
    fraud?.faceFraudZone == 1 || fraud?.faceFraudZone == 2 -> 
        showError("Face area appears manipulated")

    fraud?.frontImageManipulationZone == 1 || fraud?.frontImageManipulationZone == 2 -> 
        showError("Front side image shows manipulation traces")

    else -> { /* Accept normally */ }
}
```

### Response Instances

`Success` : Process finished successfully

`CapturedImages`: Images captured are returned in real-time

{% hint style="info" %}
Note: For`CapturedImages`instance, images are not processed yet
{% endhint %}

`BuilderError` : Process terminated due to an error in the builder

{% hint style="info" %}
Note: Check your configurations
{% endhint %}

`ServiceFailure` : Process finished with the user's failure to pass the service requirements

`UserExit` : Process terminated by the user with no errors

### Primary Response Object

`VIDVOCRResult`&#x20;

{% hint style="info" %}
Note: This is the first-level object that contains all the second-level objects.\
It is present in these type of response and holds data related to the responses, including`Success`,`ServiceFailure`, and `UserExit`.
{% endhint %}

Here is the attributes of `VIDVOCRResult`class that represents the data that could be retrived from the response object `VIDVOCRResponse` using getData() method that returns`VIDVOCRResult`object like in the example code above showing a use of `Success` response.

* captures :  \<Captures>
* documentVerificationResult : \<DocumentVerificationResult>
* ocrResult : \<VIDVOCRData>
* decryptionKeys : \<VIDVDecryptionKeys>
* hmacDataList : \<List\<HmacData>>
* sessionID : \<String>

### Object Body

* `sessionID` \<string>

<details>

<summary><code>ocrResult</code> &#x3C;sub-object></summary>

* `firstName` \<string>
* `fullName` \<string>
* `religion` \<string>
* `gender` \<string>
* `dateOfBirth` \<string>
* `age` \<int>
* `maritalStatus` \<string>
* `husbandName` \<string>
* `street` \<string>
* `birthGovernorate` \<string>
* `policeStation` \<string>
* `governorate` \<string>
* `profession` \<string>
* `releaseDate` \<string>
* `expiryDate` \<string>&#x20;
* `expired` \<boolean> : indicates whether the NID is past its expiry date.
* `serialNumber` \<string>
* `frontNid` \<string>
* `backNid` \<string>
* `frontDataValidity` \<boolean> : data on the front side is valid or not.
* `backDataValidity` \<boolean> : data on the back side is valid or not.
* `frontConfidence` \<int> : indicates if the front of the document is real or fake.
* `backConfidence` \<int> : indicates if the back of the document is real or fake.
* `isRootOfTrustCompatible` \<boolean>
* `transactionIdFront` \<string> : This could be used in face match in liveness sdk.
* `transactionIdBack` \<string>
* `combinationID` \<string>
* documentVerificationPlus \<object>
  * `frontDataValidity` \<boolean> : data on the front side is valid or not based on the greyscale flags & the review required list.
  * `backDataValidity` \<boolean> : data on the back side is valid or not based on the greyscale flags & the review required list.
  * `isFrontGreyscale`\<boolean>
  * `backConfidence` \<int>
  * `isBackGreyscale`\<boolean>&#x20;
  * `expired` \<boolean>
  * `reviewRequired`ArrayList\<string> : an ArrayList of the names of fields that is invalid.
  *
* advanced\_confidence \<object>
  * fraud\_detection\_zone \<int>
  * fraud\_detection\_details \<object>
    * is\_cracked \<boolean>
    * is\_cracked\_confidence \<float>
    * face\_fraud\_zone \<int>
    * face\_fraud\_confidence \<float>
    * front\_image\_manipulation\_zone \<int>
    * front\_image\_manipulation\_confidence \<float>
  * anomaly\_detection\_zone \<int>
  * anomaly\_detection\_details \<object>
    * front\_image\_anomaly\_zone \<int> (Detects any anomaly or obstruction on the front NID)
    * front\_image\_anomaly\_confidence \<float>
    * front\_text\_manipulation \<boolean> (Detects any anomaly or obstruction affecting the **text** of the front NID)
    * back\_image\_anomaly\_zone \<int> (Detects any anomaly or obstruction on the back NID)
    * back\_image\_anomaly\_confidence \<float>
    * back\_text\_manipulation \<boolean> (Detects any anomaly or obstruction affecting the **text** of the front NID)

</details>

<details>

<summary><code>documentVerificationResult</code> &#x3C;sub-object></summary>

* `success` \<boolean>

</details>

<details>

<summary><code>captures</code> &#x3C;sub-object></summary>

* `nationalIdFront` \<base64-string>
* `nationalIdBack` \<base64-string>

</details>

<details>

<summary><code>hmacDataList</code> &#x3C;list></summary>

* `serviceID` : ocr
* `hmacDigest` \<string>
* `rawResponse` \<string>

</details>

<details>

<summary><code>decryptionKeys</code> &#x3C;sub-object></summary>

* `nationalIdFrontRequestKey` \[UInt8]
* `nationalIdBackRequestKey` \[UInt8]
* `combineResponseKey` \[UInt8]

</details>

{% hint style="info" %}
The raw response in `hmacDataList` should be mapped to the result object as per the [HMAC validation documentation ](https://valify.gitbook.io/documentation/response-data-validation)
{% endhint %}

### Instance Responses

<mark style="color:blue;">`Success`</mark>

* `VIDVOCRResult` \<object>&#x20;

<mark style="color:blue;">`CapturedImages`</mark>&#x20;

<details>

<summary><code>CapturedImageData</code> &#x3C;object></summary>

* `nationalIDLabel` \<string>
* `nationalIdImage` \<base64-string>

</details>

<mark style="color:blue;">`UserExit`</mark>

* `VIDVOCRResult` \<object>
* `step` \<string>

{% hint style="info" %}
Note: step \<string> identifies the point where the user chose to exit the SDK
{% endhint %}

<mark style="color:red;">`ServiceFailure`</mark>

* `VIDVOCRResult` \<object>
* `code` \<string>
* `message` \<string>

<mark style="color:red;">`BuilderError`</mark>

* `code` \<string>
* `message` \<string>
