Response Events
During the OCR flow, the SDK posts events as the user scans the front and back of a CNIC card. On Android, events are delivered via a broadcast receiver; on iOS, they are delivered through the OcrControllerDelegate methods.
On-device text recognition and field parsing run inside the SDK: once both sides are captured, the SDK recognizes the text on the front card and parses it into structured fields, returned as extractedData on the final result. This runs for new (chip-based) CNICs only — old cards have no machine-readable text fields, so they always return an empty object. Recognition and parsing never raise errors — if they fail, extractedData is simply an empty object and the flow still completes normally.
Each event follows a common envelope structure:
| Key | Type | Description |
|---|---|---|
type | String | Event identifier. One of the values listed in the events table below. |
payload | Object | Event-specific data. Empty or omitted when the event has no payload. |
Events
| Event Identifier | Payload | Description | Behavior After Post |
|---|---|---|---|
LAUNCH_FAILURE | none | The SDK failed to start, usually because required initialization parameters are missing or invalid. | Activity exits. No further events are sent. |
FRONT_SUCCESS | frontImage | The front of the CNIC was captured successfully. | Flow continues to back-card capture. |
FRONT_FAILURE | none | The device could not capture the front card image (e.g. camera error). | Activity exits. |
BACK_SUCCESS | backImage | The back of the CNIC was captured successfully. | Loading UI is shown while OCR extraction runs. |
BACK_FAILURE | none | The device could not capture the back card image. | Activity exits. |
OCR_SUCCESS | See OCR_SUCCESS payload | The identity number was extracted from both images and the full result is available. | Activity exits. |
OCR_FAILURE | none | OCR could not recognize a valid identity number from the captured images. | User is prompted to re-scan the back card only. |
Event Payloads
FRONT_SUCCESS Payload
| Key | Type | Description |
|---|---|---|
frontImage | String | Local file URL of the captured front CNIC image, saved at the image width specified at launch. Use this path to display a preview or upload the image. |
BACK_SUCCESS Payload
| Key | Type | Description |
|---|---|---|
backImage | String | Local file URL of the captured back CNIC image, saved at the same width as the front image. The same URL is included again in the final OCR_SUCCESS payload. |
OCR_SUCCESS Payload
Returned when both card images are captured and on-device OCR completes successfully. This is the final result object for a completed flow.
| Key | Type | Description |
|---|---|---|
identityNumber | String | The CNIC number extracted from the scanned card. Compare this against the identity number you provided at launch to verify the document matches the expected holder. |
frontImage | String | Local file URL of the captured front image. Same value as sent in the earlier FRONT_SUCCESS event. |
backImage | String | Local file URL of the captured back image. Same value as sent in the earlier BACK_SUCCESS event. |
documentType | "new" | "old" | Detected CNIC format. "new" indicates the chip-based card; "old" indicates the legacy format. Use this to branch UI or validation logic if your app handles both card types differently. |
distance | Float | Distance of the extracted CNIC number from the CNIC number provided at launch, ranging from 0.0 (exact match) to 1.0 (maximum divergence). A lower value means the extracted number is closer to the provided CNIC. Define your acceptance threshold based on your verification requirements. |
extractedData | Object | Structured fields parsed from the front card by on-device text recognition. See extractedData object. Empty ({}) for old cards, or when nothing could be recognized or parsed — this never produces a failure event. |
extractedData object
The SDK runs on-device text recognition (Apple Vision on iOS, ML Kit on Android) on the captured front image and parses the recognized text into the fields below. This happens for new (chip-based) CNICs only; old cards have no machine-readable text fields and always return an empty object. Every parsed field is optional — only fields that were confidently parsed are present, and a field that cannot be found is omitted entirely. Alongside the parsed fields, the object also carries raw: the full unparsed text exactly as recognized, included whenever any text was recognized (so you can re-parse or audit it even when individual fields are missing). If recognition produces no text for the whole card, extractedData is an empty object {} and the flow still completes normally.
| Key | Type | Description |
|---|---|---|
name | String | Cardholder's name as printed on the front of the card. |
fatherName | String | Father's name as printed on the card. |
identityNumber | String | CNIC number parsed from the printed text (#####-#######-# or 13 digits). May differ from the top-level identityNumber, which is read from the back-card barcode. |
dateOfBirth | String | Date of birth, formatted DD.MM.YYYY. |
dateOfIssue | String | Card issue date, formatted DD.MM.YYYY. |
dateOfExpiry | String | Card expiry date, formatted DD.MM.YYYY. |
gender | "M" | "F" | "X" | Cardholder's gender code as printed on the card: M (male), F (female), or X (transgender). |
country | String | Country of stay. |
raw | String | The complete unparsed text recognized on the front card, exactly as returned by on-device text recognition (may contain line breaks). Present whenever any text was recognized — even if none of the structured fields above could be parsed. Absent only for old cards, or when recognition produced no text. |
On Android, extractedData is delivered as a nested Bundle under the extractedData key of the OCR_SUCCESS extras — read it with payload.getBundle("extractedData"). On iOS it is delivered as a native ExtractedData value on the handleResponse delegate callback.
Example Responses
FRONT_SUCCESS
{
"type": "FRONT_SUCCESS",
"payload": {
"frontImage": "file:///path/to/front_image.jpg"
}
}
BACK_SUCCESS
{
"type": "BACK_SUCCESS",
"payload": {
"backImage": "file:///path/to/back_image.jpg"
}
}
OCR_SUCCESS
{
"type": "OCR_SUCCESS",
"payload": {
"identityNumber": "12345-1234567-1",
"frontImage": "file:///path/to/front_image.jpg",
"backImage": "file:///path/to/back_image.jpg",
"documentType": "new",
"distance": 0.02,
"extractedData": {
"name": "John Doe",
"fatherName": "Richard Doe",
"identityNumber": "12345-1234567-1",
"dateOfBirth": "01.01.1990",
"dateOfIssue": "01.01.2020",
"dateOfExpiry": "01.01.2030",
"gender": "M",
"country": "Pakistan",
"raw": "Pakistan\nNational Identity Card\nName\nJohn Doe\nFather Name\nRichard Doe\nGender\nM\nCountry of Stay\nPakistan\nIdentity Number\n12345-1234567-1\nDate of Birth\n01.01.1990\nDate of Issue\n01.01.2020\nDate of Expiry\n01.01.2030"
}
}
}
For old cards, or when recognition or parsing yields nothing, extractedData is an empty object:
{
"type": "OCR_SUCCESS",
"payload": {
"identityNumber": "12345-1234567-1",
"frontImage": "file:///path/to/front_image.jpg",
"backImage": "file:///path/to/back_image.jpg",
"documentType": "new",
"distance": 0.02,
"extractedData": {}
}
}
Events With No Payload
LAUNCH_FAILURE, FRONT_FAILURE, BACK_FAILURE, and OCR_FAILURE are posted with a type only and no payload:
{
"type": "OCR_FAILURE"
}