Skip to main content

ID Verification

The ID Verification API performs OCR on identity documents (passports and national ID cards) and returns the parsed data as a clean, grouped result. It is a standalone service — it does not require a KYC submission or any onboarding state.

Try it in the playground →

Overview

Use this endpoint to verify an identity document on its own — for example, to embed Azakaw's ID parsing in your own portal without going through Azakaw's onboarding UI.

For each request the API will:

  • Run OCR on the uploaded document (image or PDF).
  • Extract the document, holder, date, and verification fields.
  • Return an overall document status and the holder portrait/signature.

At a glance

You send a document image; you get back structured data plus the holder's cropped photo (returned as base64).

Uploaded passport
1. Document you upload
Extracted portrait
2. Extracted portrait
(images.portrait, base64)

Authentication

All requests require a bearer token in the Authorization header:

Authorization: Bearer your-token-here

See Authentication. This endpoint requires an application token (issued via GetAppToken / AppSessionManager), not an interactive user/portal session. Application tokens automatically include the services: External claim the gateway enforces — here External is just the platform's marker for an app-integration token; it has nothing to do with your API's end users. A token without that claim is rejected with 403.

Verify an ID Document

POST {base_url}/ExtDocumentVerification/Verify

Request

Sent as multipart/form-data.

FieldTypeRequiredDescription
FileContentFileYesThe document. Supported formats: JPG, PNG, BMP, TIFF, and PDF (including multi-page). The document type is auto-detected — no type hint is needed.

Example

curl --location '{base_url}/ExtDocumentVerification/Verify' \
--header 'Authorization: Bearer your-token-here' \
--form 'FileContent=@"/path/to/passport.pdf"'

Response

{
"version": null,
"statusCode": 200,
"messages": [
"Processed successfully"
],
"result": {
"document": {
"name": "United Kingdom - Passport (2015)",
"description": "Passport",
"format": "TD3",
"year": "2015",
"issuingCountry": "GB",
"number": "123456789",
"personalNumber": null,
"authority": "HMPO",
"placeOfIssue": null,
"chipPresent": true,
"typeMatchScore": 0.86,
"mrz": "P<GBRDOE<<JANE<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n1234567897GBR9001011F3001012<<<<<<<<<<<<<<00"
},
"holder": {
"nativeSurname": null,
"nativeGivenName": null,
"gender": "F",
"nationality": "GB",
"dateOfBirth": "1990-01-01",
"placeOfBirth": null
},
"sources": {
"mrz": {
"surname": { "value": "DOE", "confidence": 100 },
"givenName": { "value": "JANE", "confidence": 99 },
"middleName": null
},
"visual": {
"surname": { "value": "DOE", "confidence": 98 },
"givenName": { "value": "JANE", "confidence": 96 },
"middleName": { "value": "MARGARET", "confidence": 94 }
}
},
"dates": {
"issue": null,
"expiry": "2030-01-01"
},
"verification": {
"overallStatus": "OK",
"documentNumber": "OK",
"dateOfBirth": "OK",
"expiry": "OK",
"personalNumber": null,
"finalChecksum": "OK"
},
"authenticity": {
"imageQuality": "OK",
"mrzVisualMatchScore": 1.0,
"checks": {
"documentType": "OK",
"mrz": "OK",
"expiry": "OK",
"security": "NotChecked",
"text": "OK"
}
},
"images": {
"portrait": "/9j/4AAQSkZJRgABAQAAAQ... (base64)",
"signature": "/9j/4AAQSkZJRgABAQAAAQ... (base64)",
"ghostPortrait": "/9j/4AAQSkZJRgABAQAAAQ... (base64)",
"documentImage": "/9j/4AAQSkZJRgABAQAAAQ... (base64)"
}
}
}

Any field not present on the document — or not extractable — is returned as null.

Response Fields

document

FieldTypeDescription
namestringSpecific document name detected by the parser (e.g. United Kingdom - Passport (2015)).
descriptionstringDocument type/description detected by the parser (e.g. Passport). Auto-detected — not caller-supplied.
formatstringICAO MRZ family: TD1, TD2, or TD3. null when the document has no MRZ.
yearstringDocument edition/year from the parser's template DB.
issuingCountrystringIssuing country, ISO 3166-1 alpha-2 (e.g. GB).
numberstringDocument / passport number.
personalNumberstringPersonal/national number from the MRZ optional-data field, when present.
authoritystringIssuing authority, when printed.
placeOfIssuestringPlace of issue, when printed.
chipPresentbooleantrue when the document has an RFID/NFC chip.
typeMatchScorenumberConfidence that the document matches the detected template, scale 0–1 (note: this differs from sources.*.confidence, which is 0–100).
mrzstringFull raw machine-readable zone, lines joined by \n.

holder

Latin given/surname/middle are not here; they're under sources so you can choose the reading. holder carries the unambiguous fields.

FieldTypeDescription
nativeSurnamestringSurname in the document's native non-Latin script. null for Latin-script documents.
nativeGivenNamestringGiven name in the document's native non-Latin script. null for Latin-script documents.
genderstringM, F, or X (unspecified / other, per ICAO 9303). null when the document leaves it blank.
nationalitystringNationality, ISO 3166-1 alpha-2 (e.g. GB).
dateOfBirthstring (YYYY-MM-DD)Date of birth.
placeOfBirthstringPlace of birth, when printed.

sources

The holder's Latin name is returned as two independent readings — mrz (machine-readable zone) and visual (printed/photo zone) — each with the parser's confidence. We don't pick a winner; choose the source you trust (MRZ is the authoritative transliteration; Visual can be more complete but is more prone to OCR slips like O0). Either source, or any field, is null when not read.

FieldTypeDescription
mrz.surname / visual.surname{ value, confidence }Family name from that source. null if the source carries no surname.
mrz.givenName / visual.givenName{ value, confidence }Given name(s) from that source.
mrz.middleName / visual.middleName{ value, confidence }Middle name when present as a separate field (e.g. Philippine passports); usually only on visual.

value is the cleaned string; confidence is the parser's read score 0–100.

dates

FieldTypeDescription
issuestring (YYYY-MM-DD)Date of issue, when printed.
expirystring (YYYY-MM-DD)Expiry date.

verification

Every field is a check result with one of these values (also used by authenticity):

ValueMeaning
OKCheck passed.
FailedCheck failed.
NotCheckedNot performed / not applicable. Common for checks that need the chip or physical document — e.g. security is NotChecked on an uploaded image (no RFID/UV/IR available), even for a clear passport.
nullThe parser didn't return this check.
FieldTypeDescription
overallStatusstringOverall verdict across all checks (optical, RFID, …).
documentNumberstringMRZ check-digit result for the document number.
dateOfBirthstringMRZ check-digit result for the date of birth.
expirystringMRZ check-digit result for the expiry date.
personalNumberstringMRZ check-digit result for the optional/personal number.
finalChecksumstringMRZ final/composite check-digit result.

Note: NotChecked means "couldn't be run," not "failed." Several checks (notably security) need the RFID chip or the physical document, so they come back NotChecked on an image upload regardless of quality — treat NotChecked differently from Failed.

authenticity

Quality/authenticity signals. imageQuality and every checks.* field use the same OK / Failed / NotChecked / null values as verification above.

FieldTypeDescription
imageQualitystringOverall image-quality verdict.
mrzVisualMatchScorenumberGraded agreement between the printed (Visual) data and the MRZ on the compared identity fields — average per-field string similarity, 0–1 (1 = identical). Tolerates OCR noise (an O0 slip still scores ~0.9) while flagging genuine disagreement (a different name scores low). null if not comparable. Apply your own threshold.
checks.documentTypestringDocument-type recognition check.
checks.mrzstringMRZ integrity check.
checks.expirystringExpiry/validity check.
checks.securitystringSecurity-features check.
checks.textstringText-consistency check.

images

All image fields are raw Base64-encoded JPEG (no data: URI prefix). Returned inline; never stored server-side. Any field is null when the document doesn't carry that image.

FieldTypeDescription
portraitstringBase64-encoded holder portrait, when extracted. Returned inline; not stored server-side.
signaturestringBase64-encoded signature image, when extracted.
ghostPortraitstringBase64-encoded ghost portrait (faint security duplicate), when present.
documentImagestringBase64-encoded full document image (front side), when present.

Supported Documents

The document type is detected automatically — you don't pass it. Best results are with MRZ documents:

DocumentNotes
PassportInternational passport (TD3 / ID-3).
National ID cardSubmit the side containing the MRZ.

For best results submit the side of the document that contains the MRZ.

Rate Limit

Rate-limited at 5 requests per second. Excess requests return HTTP 429.

Error Handling

StatusMeaning
200Processed. Inspect result.verification.overallStatus.
400Validation failure — e.g. FileContent missing or empty.
401Missing or invalid Bearer token.
403Token lacks the required services: External claim.
413File exceeds the configured size limit.
429Rate limit exceeded.
500Unexpected server error.

Error responses use the standard envelope:

{
"version": null,
"statusCode": 400,
"messages": [
"FileContent is empty."
],
"result": null
}

Best Practices

  • Image quality. Submit clear, well-lit images with all four corners visible; avoid glare on the MRZ.
  • PDFs are fine. Upload PDFs (including multi-page) directly — no need to convert them to images first.
  • Idempotency. Each call is independent; retry the full request if needed.
  • Status interpretation. Treat verification.overallStatus = OK as success. NotChecked means the document couldn't be verified (common for plain photos) — not a failure; only Failed indicates a check that didn't pass. Inspect the per-field results under verification / authenticity for stricter handling.