Skip to main content

Overview

The ID verification report captures everything Didit extracted and validated from a government-issued identity document — passports, ID cards, driver’s licenses, and residence permits. It bundles the OCR’d biographical and document fields, signed URLs to the captured media, parsed and geolocated address data, per-side image quality scores, MRZ contents, multi-script (Latin / non-Latin) breakdowns, and cross-session document matches. The report is produced after the user completes the document-capture step in a workflow (or hits the standalone OCR endpoint). Didit identifies the document type, runs OCR, validates the MRZ / barcode / QR code, parses the address, screens for tampering (screen capture, printed copy, portrait manipulation), and compares the document against every other document captured in your application. Each report carries its own status — independent of the overall session status — that reflects how the ID step alone resolved:
  • Approved — document recognized, all required fields extracted, no decline-routed warning fired.
  • In Review — one or more warnings fired and your workflow routes them to review.
  • Declined — an auto-decline condition fired (unsupported document, expired document, portrait missing, blocklist hit, adaptive-age failure) or a warning whose configured action is Decline fired (minimum/maximum age default to Decline).
  • Expired — the document’s expiration_date passed after the verification. Didit’s ongoing expiration monitoring flips the report from Approved to Expired, appends a DOCUMENT_EXPIRED warning, and moves an approved session to the Kyc Expired session status.
  • Not Finished — the user never completed the capture step.

Where it appears in API responses

The ID report ships inside the id_verifications[] array — always a JSON array, never a singular id_verification object. Multiple entries appear when a workflow runs more than one document step (for example a primary ID plus a step-up).
  • Session decision API — GET /v3/session/{sessionId}/decision/ returns id_verifications[] at the top level. See Retrieve session decision.
  • Webhooks — session.status.updated payloads include the same id_verifications[] array once the step has produced data. See Webhooks.
  • Standalone OCR API — direct document submission returns a singular id_verification object with the same fields. See OCR standalone API.
Read response.id_verifications[0] and iterate the array. The singular id_verification shape only exists on the standalone OCR API — it does not exist on the v3 decision endpoint.

Schema

The canonical field-by-field schema lives on the Data models reference page. The fields below come straight from IDVerificationV3Serializer, which extends IDVerificationV2Serializer and adds node_id plus the cross-session matches[] array — 40 fields in total.

Top-level fields

issuing_state is always country-level, never sub-national. For every document type, including driving licences issued by a state or province (Australia, the United States, Canada), issuing_state and issuing_state_name report the country (for example AUS / Australia), not the state. The sub-national value, when the document carries one, is available separately in parsed_address.region (falling back to extra_fields.state on some document types). The Business Console session overview shows this as a Region row underneath Issuing state when present.
Driver’s licences that carry two numbers (Australia). Australian licences print both a licence number, which identifies the holder’s driving entitlement and stays the same when a card is replaced, and a card number, which identifies the physical card and changes with every reissue. For these licences Didit always maps the numbers the same way:
  • personal_number — the licence number
  • document_number — the card number
This applies to every Australian state and territory (NSW, VIC, QLD, WA, SA, TAS, ACT, NT). On some variants the card number is printed only on the back, so it is read only when the back of the licence is captured. When no card number can be read, the licence number is reported as both document_number and personal_number, so document_number always carries an identifier once the verification finishes. personal_number is the licence number either way. On other document types document_number remains the primary OCR’d number and may itself be a holder-level identifier.
The Argentine CUIL is extra_fields.tax_number, never personal_number. Argentine documents print the CUIL — the 11-digit identifier AFIP, ANSES and the credit bureaus are keyed on — in a different place on each document, and the DNI prints a second 11-digit number beside it:
  • on the driving licence, the CUIL is what personal_number carries;
  • on the DNI, personal_number carries the número de trámite, which identifies the card application and is not an identifier for the holder. The DNI’s CUIL is read from its own printed field.
So personal_number is not a reliable CUIL for Argentina: on a DNI it is an 11-digit number that will silently return no result from any registry. Read extra_fields.tax_number instead. Didit reports it only when the value validates as a real CUIL (person prefix plus the modulo-11 check digit), in canonical digits with no separators (27111111117), whichever Argentine document the holder presented. When the card’s CUIL could not be read, the key is absent rather than filled with a number that is not a CUIL — capture the driving licence as a second document, or collect the CUIL through a Questionnaire answer or the session’s metadata, to cover those users.

Image quality scores

front_image_quality_score and back_image_quality_score each return:
Use overall_score as a quick suitability check — scores above 70 generally indicate a capture good enough for reliable verification.

Document liveness scores

document_liveness reports what the document-liveness check measured, whether or not it raised a warning. A warning only exists when a score fell below one of the workflow’s thresholds, so before this field an approved document carried no liveness evidence at all - the field is how you audit a session that passed. It is null when the check did not run (for example a non-document method, or a model outage recorded in the session logs). It carries one object per fraud type - portrait_replace, printed_copy and screen_replay - each with:
For older documents without saved evaluation evidence, stored scores remain visible but both thresholds and bucket are null. Current workflow settings are never used to reconstruct a historical outcome. The same applies to a capture whose document evaluation has not completed yet. The Business Console shows the same three rows in the Document liveness block of the session’s ID Verification section.

Cross-session matches

matches[] lists up to 5 other documents in your application that match this one — same date of birth, same issuing country, and a highly similar full name. Blocklisted documents additionally require an exact document-number match. Sessions belonging to the same user (same vendor_data) are excluded. Each entry includes session_id, session_number, vendor_data, verification_date, user_details (name, document_type, document_number), status, is_blocklisted (true when the document was added to your blocklist), api_service, and a signed front_image_url.

Status values

Multi-script documents (Latin / non-Latin)

Some documents — Kyrgyz, Kazakh, Russian, Japanese, Korean, Chinese, Arabic, Thai, and others — print the holder’s name, address, or place of birth in both a Latin transliteration and the local script. You choose which script powers the top-level response with the workflow (or standalone-API) setting preferred_characters: The alternate-script values live inside extra_fields under suffixed keys: first_name_non_latin, last_name_non_latin, middle_name_non_latin, full_name_non_latin, address_non_latin, place_of_birth_non_latin (or the matching _latin variants).

When alternate-script fields appear

  • Only when both scripts are actually present on the document. If an OCR field nominally labelled “Surname-Kyrgyz (Cyrillic)” is extracted as Latin-script text (homoglyphs or a Latin transliteration), it does not qualify as a non-Latin alternate and that key is omitted.
  • full_name_non_latin (and full_name_latin) are always reconstructed from the individual first-, middle-, and last-name components when both are available — the raw “Full Name” field from OCR is ignored for consistency.
  • When preferred_characters=latin but the document carries only non-Latin text (so the top-level fields end up non-Latin), Didit runs a transliteration pass and exposes first_name_latin, last_name_latin, middle_name_latin, full_name_latin, place_of_birth_latin, and address_latin as a Latin fallback.
last_name_non_latin is absent because the document’s “Surname (Cyrillic)” field came back as Latin characters on this sample — there was no genuine non-Latin surname to extract.

Examples

Approved — clean Spanish identity card (all fields)

In Review — QR not detected on a document that should have one

Abridged — a real response always carries the full field set shown above.

Security note

The signed URLs returned for document images and videos are temporary — they expire after a limited validity window. Treat them as short-lived: download what you need promptly and do not cache or surface them publicly. Typically your application only needs status, a handful of biographical fields, and the warnings — store as little as possible to minimize the surface for any future breach.