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 APIGET /v3/session/{sessionId}/decision/ returns id_verifications[] at the top level. See Retrieve session decision.
  • Webhookssession.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

FieldTypeDescription
status"Approved" | "Declined" | "In Review" | "Expired" | "Not Finished"ID-step status.
node_idstring | nullWorkflow graph node that produced this report.
document_type"Passport" | "Identity Card" | "Driver's License" | "Residence Permit" | "Health Insurance Card" | "Tax Card" | nullRecognized top-level document family (human-readable).
document_subtypestring | nullAccepted document subtype code from the workflow document settings. Region-specific documents include the region, for example QUEENSLAND_DRIVER_LICENSE_GENERIC.
document_numberstringOCR’d document number.
personal_numberstringOCR’d personal / national identification number, when distinct from the document number.
portrait_image, front_image, front_video, back_image, back_video, full_front_image, full_back_imagestring (signed URL)Captured media. URLs are signed and time-limited — download promptly, never persist the URL.
front_image_camera_front, back_image_camera_frontstring (signed URL) | nullFrames captured by the user’s front-facing camera during document capture (used for the cross-camera face check).
front_image_camera_front_face_match_score, back_image_camera_front_face_match_scorefloat (0–100) | nullSimilarity score between the front-camera frame and the document portrait.
front_image_quality_score, back_image_quality_scoreobject | nullQuality assessment per side (see Image quality scores).
date_of_birth, expiration_date, date_of_issuestring (YYYY-MM-DD)Document dates.
agenumberHolder age in years computed from date_of_birth.
issuing_statestring (ISO 3166-1 alpha-3)Issuing country code.
issuing_state_namestringLocalized country name.
first_name, last_name, full_namestringHolder name in the script chosen by preferred_characters (see below).
gender"M" | "F" | "U"Gender, when present on the document (U = unknown).
address, formatted_addressstringRaw and geocoded/formatted address strings.
place_of_birthstringOCR’d place of birth.
marital_status"SINGLE" | "MARRIED" | "DIVORCED" | "WIDOWED" | "UNKNOWN"Marital status, when present on the document.
nationalitystring (ISO 3166-1 alpha-3)Holder nationality, when distinct from issuing state.
extra_fieldsobjectDocument-specific extras (DL categories, blood group, alternate-script names, …).
mrzobject | nullParsed MRZ key/value fields.
parsed_addressobject | nullStructured, geocoded address (street_1, street_2, city, region, country, postal_code, address_type, formatted_address, document_location, raw_results, is_best_match).
extra_files[]array of signed URLsAdditional images attached to this document.
matches[]arrayCross-session document matches (see Cross-session matches).
warnings[]arrayModule-level warnings — see ID verification warnings.

Image quality scores

front_image_quality_score and back_image_quality_score each return:
FieldTypeWhat it measures
focus_scorenumber 0–100Sharpness — top-10% local Laplacian variance, robust to uniform backgrounds. Weight 45%.
brightness_scorenumber 0–100Penalizes too-dark or overexposed images. Weight 30%.
brightness_issue"ok" | "too_dark" | "too_bright"Direction of the brightness problem, when brightness_score is low.
resolution_scorenumber 0–100Based on total pixel count of the capture. Weight 25%.
is_document_fully_visibleboolean | nulltrue when all four document corners are visible, false when any corner is cut off, null when corner detection was unavailable.
overall_scorenumber 0–100Weighted composite (focus 45%, brightness 30%, resolution 25%).
Use overall_score as a quick suitability check — scores above 70 generally indicate a capture good enough for reliable verification.

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

StatusMeaningDownstream effect
ApprovedDocument recognized, required fields extracted, all checks passed at the configured thresholds.Counts as a successful ID check.
In ReviewOne or more warnings fired and the workflow routes them to review.Session also moves to In Review until a reviewer acts.
DeclinedAuto-decline condition fired (unsupported document, expired document, portrait missing, blocklist hit, adaptive-age failure) or a warning configured to Decline fired.Session is declined unless another approved branch satisfies the workflow.
ExpiredThe document’s expiration date passed after approval. Set by Didit’s ongoing expiration monitoring (respecting per-country expiration_check_mode exemptions), together with a DOCUMENT_EXPIRED warning.An approved session moves to Kyc Expired.
Not FinishedUser abandoned the capture step.The ID branch did not produce a result.

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:
ValuePopulates top-level fields withOpposite script goes to
latin (default)The Latin transliteration printed on the documentextra_fields.*_non_latin
non_latinThe local-script values printed on the documentextra_fields.*_latin
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.
{
  "first_name": "John",
  "last_name": "Doe",
  "full_name": "John Doe",
  "extra_fields": {
    "first_name_non_latin": "Айна"
  }
}
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)

{
  "id_verifications": [
    {
      "status": "Approved",
      "document_type": "Identity Card",
      "document_subtype": "ID_CARD_GENERIC",
      "document_number": "SAMPLE-DOC-12345",
      "personal_number": "SAMPLE-PER-12345",
      "portrait_image": "https://<media-host>/.../portrait.jpg?signature=...",
      "front_image": "https://<media-host>/.../front.jpg?signature=...",
      "front_video": "https://<media-host>/.../front.mp4?signature=...",
      "back_image": "https://<media-host>/.../back.jpg?signature=...",
      "back_video": "https://<media-host>/.../back.mp4?signature=...",
      "full_front_image": "https://<media-host>/.../full_front.jpg?signature=...",
      "full_back_image": "https://<media-host>/.../full_back.jpg?signature=...",
      "front_image_camera_front": null,
      "back_image_camera_front": null,
      "front_image_camera_front_face_match_score": null,
      "back_image_camera_front_face_match_score": null,
      "front_image_quality_score": {
        "focus_score": 85.3,
        "brightness_score": 92.1,
        "brightness_issue": "ok",
        "is_document_fully_visible": true,
        "resolution_score": 72.4,
        "overall_score": 84.6
      },
      "back_image_quality_score": {
        "focus_score": 79.1,
        "brightness_score": 90.5,
        "brightness_issue": "ok",
        "is_document_fully_visible": true,
        "resolution_score": 72.4,
        "overall_score": 81.5
      },
      "date_of_birth": "1990-01-01",
      "age": 35,
      "expiration_date": "2031-06-02",
      "date_of_issue": "2021-06-02",
      "issuing_state": "ESP",
      "issuing_state_name": "Spain",
      "first_name": "John",
      "last_name": "Doe",
      "full_name": "John Doe",
      "gender": "M",
      "address": "Avda de Madrid 34",
      "formatted_address": "Avda de Madrid 34, Madrid, Madrid 28822, Spain",
      "place_of_birth": "Madrid",
      "marital_status": "SINGLE",
      "nationality": "ESP",
      "extra_fields": {},
      "mrz": {
        "document_number": "SAMPLE-DOC-12345",
        "surname": "DOE",
        "name": "JOHN",
        "birth_date": "900101",
        "expiry_date": "310602"
      },
      "parsed_address": {
        "street_1": "Avda de Madrid 34",
        "street_2": null,
        "city": "Madrid",
        "region": "Madrid",
        "country": "ES",
        "postal_code": "28822",
        "address_type": "Avda",
        "formatted_address": "Avda de Madrid 34, Madrid, Madrid 28822, Spain",
        "document_location": { "latitude": 40.4168, "longitude": -3.7038 },
        "raw_results": {
          "geometry": {
            "location": { "lat": 40.4168, "lng": -3.7038 },
            "location_type": "ROOFTOP"
          }
        },
        "is_best_match": true
      },
      "extra_files": [],
      "warnings": [],
      "node_id": "id_primary",
      "matches": []
    }
  ]
}

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

Abridged — a real response always carries the full field set shown above.
{
  "id_verifications": [
    {
      "status": "In Review",
      "node_id": "id_primary",
      "document_type": "Identity Card",
      "document_subtype": "ID_CARD_GENERIC",
      "document_number": "SAMPLE-DOC-12345",
      "first_name": "John",
      "last_name": "Doe",
      "full_name": "John Doe",
      "warnings": [
        {
          "feature": "ID_VERIFICATION",
          "risk": "QR_NOT_DETECTED",
          "additional_data": null,
          "log_type": "warning",
          "short_description": "QR not detected",
          "long_description": "The system couldn't find or read the QR code on the document. This could be due to poor image quality or an unsupported document type.",
          "node_id": "id_primary"
        }
      ]
    }
  ]
}

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.