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
| Field | Type | Required | Description |
|---|---|---|---|
document_type | string | Yes | national_id, passport, drivers_license, or voter_id |
country | string | Yes | ISO 3166-1 alpha-2 code |
image_front | string | Yes | Base64-encoded front image |
image_back | string | No | Base64-encoded back image (for IDs with rear data) |
parse_mrz | boolean | No | Parse 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 Type | Typical Fields |
|---|---|
| National ID | Name, ID number, DOB, sex, address |
| Passport | Name, passport number, nationality, DOB, expiry, MRZ |
| Driver's License | Name, license number, class, DOB, expiry |
| Voter ID | Name, 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: falsestrongly suggests a tampered or low-quality scan. - Check
field_confidenceper 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
| Code | HTTP | Description |
|---|---|---|
IMAGE_QUALITY_LOW | 422 | Image too blurry, dark, or cropped to read |
UNSUPPORTED_DOCUMENT | 400 | Document type not supported for that country |
MRZ_UNREADABLE | 422 | MRZ present but could not be parsed |
NO_DOCUMENT_DETECTED | 422 | No document found in the image |
See the error code reference for the full list.
📚 Related Resources
Last Updated: May 2026 | Need help? [email protected]