Skip to main content

Document Scanning (OCR)

Extract structured fields from a photographed identity document without running a full verification. Use this when you only need the data on the document — for pre-filling forms or capturing reference details — and will handle authenticity, face match, and risk separately.

For full KYC with authenticity and face matching, use ID Document Verification instead.

🚀 Quick Start​

curl -X POST https://api.afriroute.ai/api/v1/identity/scan-document \
-H "Authorization: Bearer $AFRIROUTE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"document_type": "passport",
"country": "NG",
"image_front": "<base64-encoded-image>"
}'

📡 Endpoint​

Scan Document​

POST /v1/identity/scan-document

Parameters​

FieldTypeRequiredDescription
document_typestringYesnational_id, passport, drivers_license, or voter_id
countrystringYesISO 3166-1 alpha-2 code
image_frontstringYesBase64-encoded front image
image_backstringNoBase64-encoded back image (for IDs with rear data)
parse_mrzbooleanNoParse the Machine Readable Zone if present (default true)

💻 Code Samples​

Node.js
const fs = require('fs');
const res = await fetch('https://api.afriroute.ai/api/v1/identity/scan-document', {
method: 'POST',
headers: { 'Authorization': 'Bearer $AFRIROUTE_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
document_type: 'passport',
country: 'NG',
image_front: fs.readFileSync('passport.jpg', 'base64')
})
});
const { fields } = await res.json();
console.log(fields.full_name, fields.document_number);
Python
import base64, requests

with open('passport.jpg', 'rb') as f:
img = base64.b64encode(f.read()).decode()

res = requests.post(
'https://api.afriroute.ai/api/v1/identity/scan-document',
headers={'Authorization': 'Bearer $AFRIROUTE_API_KEY'},
json={'document_type': 'passport', 'country': 'NG', 'image_front': img}
)
print(res.json()['fields'])

📊 Response​

{
"scan_id": "scan_8h2k9",
"document_type": "passport",
"country": "NG",
"fields": {
"full_name": "CHINEDU OKAFOR",
"document_number": "A01234567",
"date_of_birth": "1988-11-02",
"sex": "M",
"nationality": "NGA",
"issue_date": "2021-03-01",
"expiry_date": "2031-03-01"
},
"mrz": {
"present": true,
"valid": true,
"raw": "P<NGAOKAFOR<<CHINEDU<<<<<<<<<<<<<<<<<<<<<<<<"
},
"field_confidence": {
"full_name": 99.1,
"document_number": 99.5,
"date_of_birth": 98.7
}
}

🗂️ Extracted Fields by Document​

Document TypeTypical Fields
National IDName, ID number, DOB, sex, address
PassportName, passport number, nationality, DOB, expiry, MRZ
Driver's LicenseName, license number, class, DOB, expiry
Voter IDName, voter number, DOB

💡 Best Practices​

  • Fill the frame with the document and avoid angled shots to maximize field confidence.
  • Validate the MRZ — a mrz.valid: false strongly suggests a tampered or low-quality scan.
  • Check field_confidence per field and prompt a re-capture when any critical field is below 90.
  • Don't treat OCR as proof of authenticity — pair it with verification for KYC decisions.
  • Strip the document image from your store after extraction unless retention is legally required.

⚠️ Error Handling​

CodeHTTPDescription
IMAGE_QUALITY_LOW422Image too blurry, dark, or cropped to read
UNSUPPORTED_DOCUMENT400Document type not supported for that country
MRZ_UNREADABLE422MRZ present but could not be parsed
NO_DOCUMENT_DETECTED422No document found in the image

See the error code reference for the full list.


Last Updated: May 2026 | Need help? [email protected]