The response of the SDK will return in the following delegate
funconOCRResult(result: VIDVOCRResponse)
It will return an enum result of type VIDVOCRResponse
VIDVOCRResponse Cases
Success : Process finished successfully
CapturedImages: Images captured are returned in real-time
Note: For theCapturedImagesinstance, images are not processed yet
UserExit : Process terminated by the user with no errors
ServiceFailure : Process finished with the user's failure to pass the service requirements
BuilderError : Process terminated due to an error in the builder
Example
switch result {case .success(let data): // data of type VIDVOCRResultcase .builderError(let code, let message): // builder error code & error messagecase .serviceFailure(let code, let message, let data): // service faluire error code & error message & data of type VIDVOCRResultcase .userExit(let step, let data): // last step in the SDK & data of type VIDVOCRResultcase .capturedImages(capturedImageData:let capturedImageData): // capturedImageData of type CapturedImageData}
Document verification plus - Case Handling
When using VIDVOCRResult.getData(), the returned ocrResult may include a documentVerificationPlusobject.
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 reviewRequiredto 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
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
Primary Response Object
VIDVOCRResult
Note: This is the first-level object that contains all the second-level objects
//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
if let flags = result.data?.ocrResult?.documentVerificationPlus {
// --------------------- GENERIC VALIDATION RESULTS --------------------- //
// Quick validation using global parent flags
if flags.frontDataValidity == false || flags.backDataValidity == false {
showRetryDialog(
title: "Document failed validation checks.",
message: "Please try again."
) {
startOCR() // Developer function — implement your restart flow
}
}
// Greyscale document detection
else if flags.isFrontGreyscale == true || flags.isBackGreyscale == true {
requestRecapture(reason: "Document appears to be black & white.")
// requestRecapture() is an example recapture function — implement your flow
}
// Document expired
else if flags.isExpired == true {
showRetryDialog(
title: "OCR",
message: "Expired ID, please try again with your recent National ID."
) {
startOCR() // Custom restart logic
}
}
// One or more fields require review
else if !(flags.reviewRequired?.isEmpty ?? true) {
showError("Some fields require manual review.")
// showError() is a custom function — for UI alerts/log display
}
// --------------------- FIELD-LEVEL REVIEW CASES --------------------- //
if let review = flags.reviewRequired {
if review.contains("serial_number") {
showRetryDialog(
title: "OCR",
message: "Serial number is incorrect. Please try again."
) { startOCR() }
}
if review.contains("back_nid") || review.contains("front_nid") {
requestRecapture(reason: "NID Mismatch") // Example recapture action
}
if review.contains("date_of_birth") { showError("Date of birth could not be verified.") }
if review.contains("street") { showError("Street address is empty.") }
if review.contains("police_station") { showError("Police station field needs review.") }
if review.contains("governorate") { showError("Governorate value could not be verified.") }
if review.contains("birth_governorate") { showError("Birth governorate requires review.") }
if review.contains("expiry_date") { showError("Expiry date is missing or invalid.") }
if review.contains("release_date") { showError("Release date did not pass validation.") }
}
else {
// Default Case — No flags triggered
// Document is valid and accepted
}
}
//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
if let fraud = result.data?.ocrResult?.advancedConfidence {
// Parent Fraud Status
switch fraud.fraudDetectionZone {
case 1: showWarning("Suspicious document — review needed") // Replace with custom handling
case 2: requestRecapture(reason: "Fraud suspected — please retry with a valid ID") // Replace with custom handling
default: break
}
// Detailed Breakdown
if fraud.faceFraudZone > 0 {
showError("Face region manipulation detected") // Replace with custom handling
}
if fraud.frontImageManipulationZone > 0 {
showError("Possible document editing found") // Replace with custom handling
}
}
}