Unstructured Docs

Prev Next

Available via API

Available via SDK

Needs configuration on Veriff’s side

Needs a separate integration

Needs a separate webhook

Unstructured Docs (also known as “uDocs”) is an intelligent document processing solution that allows the classification, data extraction, and validation of non-standardized documents such as bank statements, utility bills, and insurance policies. The system extracts structured data and performs advanced tampering checks to verify the end-user and detect fraud.

Unstructured Docs is currently available only via API. SDK integration is not possible.

You need a separate integration for this solution, meaning existing IDV or PoA or other integrations cannot be used.

Unstructured Docs can be:

All session-related info is returned via decision webhook and can be polled from different API endpoints. The results of the verification can also be viewed in the Veriff Customer Portal, in the All verifications > session > Webhooks tab.

If any data was extracted from the document, this data is provided in the decision webhook payload and GET /decision endpoint’s response payload.

Contact your solutions engineer for info and configuration.


Prerequisites

  • You have an integration set up with Veriff

  • The feature is configured for that integration by your Solutions Engineer

  • You have configured the decision webhook to get responses from Veriff

  • You are ready to collect and send Veriff your end-user’s data

  • Because the solution is available only via API:

    • Veriff strongly recommends you collect and send additional device/session data for improved fraud mitigation

    • Veriff strongly recommends that you create and send us the endUserId or vendorData

Key terminology

Term

Description

Add-on

A solution/feature that can be enabled for the Unstructured Docs’ integration for additional data verification.

Address Matching

A feature that compares addresses from two different sources (end-user’s documents and customer-provided initial data) to verify they belong to the same location.

Outputs data in additionalVerifiedData.addressMatching object. See the Address Matching documentation for more info.

Address Validation

A feature that validates the address extracted from the end-user’s document.

Outputs data in additionalVerifiedData.proofOfaddress.addressValidationResult object. See the Address Validation documentation for more info.

Classification

Process to identify document type (e.g., bank_statement, car_insurance_policy, tax_statement).

Outputs data in additionalVerifiedData.udocs.classification object in decision webhook payload and GET /decision API response.

Core feature

A feature that is part of the Unstructured Document's solution, required to ensure the solutions’ functionality.

Document Expiration

Data validation process that checks the validity of the document based on its expiration date or its issue date.

Outputs data in additionalVerifiedData.udocs.documentExpiration object in decision webhook payload and GET /decision API response.

Extraction

Process to extract specific data fields from the document (e.g., full name, address).

Outputs data in additionalVerifiedData.udocs.extraction object in decision webhook payload and GET /decision API response.

Feature

In uDocs context, an umbrella term for “add-on”, “classification”, “extraction”, “core feature”, “validations”

InitData Matching

Data validation process, where the extracted data fields will be matched against the data sent through as initial data on session creation. For name, bank account number and occupation title matching.

Outputs data in additionalVerifiedData.udocs.matchingResults object in the decision webhook payload and GET /decision API response.

Data fields to be extracted

Data field that can be extracted from end-user’s document.

If set to be “mandatory”, the success or failure of this field’s extraction will impact your session result. You can chose which data fields are considered mandatory.

Supported document type

Document type that can be used to perform a use case-specific verification.

Tampering Check

Fraud detection feature that analyzes documents for signs of tampering.

Outputs data in additionalVerifiedData.udocs.fraud object in the decision webhook payload and GET /decision API response.

See below for more info.

uDocs

Abbreviation of Unstructured Docs

Use case

A specific real-life scenario where a unstructured document is used for end-user verification.

Validations

Process where the input data (either extracted from end-user’s document or gathered from initData) is compared against some data point, e.g., against same data from another source, against a specific threshold or rule.


End-user data sources

The “end-user data sources” refer to different origins from which the end-user’s information can be collected for database verification. There are two data sources: document data and initData.

InitData

This is data that you provide when creating a verification session, i.e. the parameters you specify in the POST /sessions request.

Parameters that can be sent via initData, all are optional:

  • Full name via verification.person.fullName (e.g., for InitData Matching validation)

  • Bank account number via verification.document.number (e.g., for InitData Matching validation)

  • Full address via verification.address.fullAddress (for Address Matching and Address Validation add-ons)

  • Occupation via verification.person.occupation (e.g., for InitData Matching validation)

Document data

This is data that is extracted from the end-user’s document. Includes information like names, addresses, or account numbers extracted from bank statements, utility bills, vehicle registration forms etc.


uDocs use cases and flow setup rules

Veriff strongly suggest to have only one use case per integration.

Contact your solutions engineer for info and configuration.

Unstructured Docs can be used to flexibly solve document verification for different use cases. However, there are some rules when setting up the use case:

  • each use case supports only certain document types,

  • and allows the extraction of specific document data fields.

Supported document types and extractable data fields mapping is shown in the table below.

Also, each use case supports validation checks that can be configured to work with certain add-ons. Working combinations are shown in the table below.

Note about the data fields to be extracted

  • The table below shows the maximum list of data fields. You can enable only the ones needed.

  • None, some or all of them can be set to be mandatory, in which case the success or failure to extract that data will impact your session result.

Note that you need your Solution Engineer’s help to set up the document types, extractable data fields and validation check/add-on combinations. You cannot do this in Customer Portal or via initData.

Use case

Supported document types

Data fields to be extracted

Supported validations and optional supported add-ons

Bank account ownership verification

  • bank_statement

  • proof_of_bank_account

  • bank_account_number

  • issue_date

  • full_address

  • full_name

Source of income verification

  • bank_statement

  • certificate_of_non_taxation

  • employer_payslip

  • p60_tax_certificate

  • tax_assessment

  • tax_bill

  • tax_return

  • tax_statement

  • income

  • issue_date

  • issuer

  • full_address

  • full_name

  • occupation (mandatory if “employer_payslip” document type is enabled)

Vehicle ownership verification

  • car_ownership_certificate

  • vehicle_registration

  • full_address

  • full_name

  • vehicle_identification_number

  • vehicle_registration_number

Vehicle insurance policy verification

  • vehicle_insurance_policy

  • document_number

  • expiry_date

  • full_address

  • full_name

  • vehicle_identification_number

  • vehicle_registration_number

  • Document Expiration check: enables only “document not expired” check

  • InitData Matching: enables  full name match check

  • Tampering Check add-on


Tampering Check aka fraud validation

If the fraud validation has been enabled for your solution, then you will see the additionalVerifiedData.udocs.fraud object in the payload.

The fraud object shows the document's risk level and gives additional details about the factors that influenced this risk assessment. Veriff passes the data unaltered in webhooks and API payloads.

{
  ...
  "additionalVerifiedData": {
      "udocs": {
          "fraud": {
              "riskLevel": "HIGH_RISK",
              "reason": "PDF_PROCESSED_BY_EDITOR",
              "reasonDescription": "Document was processed using editing software",
              "indicators": []
          }
      },
      ...
  }
}

Note that:

  • The session will be declined if the riskLevel: HIGH_RISK.

  • The decision webhook and API examples further below in this document contain limited info about the possible values of the keys in the fraud object.

Veriff recommends you do not build any logic on top of the fraud.indicators array, as possible values may be altered without prior notice to provide better insights. However, structure of entries will stay backwards compatible.


Flow overview

Unstructured Docs is currently available only via API.

You are responsible for the document capture interface and image quality.

Unstructured Docs verification (with initData validation)

  1. Generate a verification session using the API keys and the baseURL of your Unstructured Docs integration.

    1. Include the initData you want it to be matched against the data on the document.

    2. Veriff strongly recommends you create and send the endUserId or vendorData.

    3. Veriff strongly recommends you collect and send additional session/device data via POST sessions/{sessionid}/collected-data[↗] for improved fraud detection.

Session creation bash example (with all possible initData fields)

curl --request POST \
  --url https://exampleURL.com/v1/sessions/ \
  --header 'content-type: application/json' \
  --header 'x-auth-client: your-api-key' \
  --data '{
    "verification": {
      "document": {
        "number": "847293651024738569"
      },
      "person": {
        "fullName": "JUAN MARTINEZ",
        "occupation": "Driver"
      },
      "address": {
        "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100"
      },
      "endUserId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
    }
  }'

Session creation json example (with all possible initData fields)

{
  "verification": {
    "document": {
      "number": "847293651024738569"
    },
    "person": {
      "fullName": "JUAN MARTINEZ",
      "occupation": "Driver"
    },
    "address": {
      "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100"
    },
    "endUserId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  }
}
    

  1. Upload the end-user's media via POST /sessions/{sessionId}/media[↗] call.

    1. Use your image-capturing method, or send previously collected document image(s).

    2. Unstructured Docs supports JPEG, PNG, and multi-page PDFs (see the POST /sessions/{sessionId}/media[↗] documentation for more info about how to upload the image or PDF files).

    3. Specify the image.context as generic-document-front for the document.

    4. This endpoint requires endpoint level authentication via x-hmac-signature header. See  HMAC Authentication and Endpoint Security article for general info about signature creation.

Media upload bash example

curl -X POST \
  --url 'https://exampleURL.com/v1/sessions/{sessionId}/media' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: your-api-key' \
  -H 'X-HMAC-SIGNATURE: your-hmac-signature' \
  -d '{
    "image": {
      "data": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAA...",
      "context": "generic-document-front"
    }
  }'

Media upload json example

{
        "image": {
        "data": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAA...",
        "context": "generic-document-front"
        }
        }
    

  1. Patch session status to submitted status using PATCH /sessions/{sessionId}[↗] call

    1. This endpoint requires endpoint level authentication via x-hmac-signature header. See  HMAC Authentication and Endpoint Security article for general info about signature creation.

Session update bash example

curl -X PATCH \
  --url 'https://exampleURL.com/v1/sessions/{sessionId}' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: your-api-key' \
  -H 'X-HMAC-SIGNATURE: your-hmac-signature' \
  -d '{
    "status": "submitted"
  }'

Session update json example

{
  "status": "submitted"
}
    

  1. Check the decision data and/or session related info from the decision webhook and/or query the data from the GET sessions/{sessionId}/decision[↗] endpoint. Solution-specific overview of what to expect is provided below in the Find decision and/or session related info > Solution-specific parameters section.

Unstructured Docs with document extraction (no initData validation)

  1. Generate a verification session using the API keys and the baseURL of your Unstructured Docs integration.

    1. If no initData is sent, the payload can be an empty verification object

    2. Veriff strongly recommends you create and send the endUserId or vendorData

    3. Veriff strongly recommends you collect and send additional session/device data via POST sessions/{sessionid}/collected-data[↗] for improved fraud detection

Session creation bash example (empty verification object)

curl --request POST \
  --url https://exampleURL.com/v1/sessions/ \
  --header 'content-type: application/json' \
  --header 'x-auth-client: your-api-key' \
  --data '{
    "verification": {}
  }'

Session creation json example (empty verification object)

{
  "verification": {}
}
    

  1. Upload the end-user's media via POST /sessions/{sessionId}/media[↗] call.

    1. Use your image-capturing method, or send previously collected document image(s).

    2. Unstructured Docs supports JPEG, PNG, and multi-page PDFs (see the POST /sessions/{sessionId}/media[↗] documentation for more info about how to upload the image or PDF files).

    3. Specify the image.context as generic-document-front for the document.

    4. This endpoint requires endpoint level authentication via x-hmac-signature header. See  HMAC Authentication and Endpoint Security article for general info about signature creation.

Media upload bash example

curl -X POST \
  --url 'https://exampleURL.com/v1/sessions/{sessionId}/media' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: your-api-key' \
  -H 'X-HMAC-SIGNATURE: your-hmac-signature' \
  -d '{
    "image": {
      "data": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAA...",
      "context": "generic-document-front"
    }
  }'

Media upload json example

{
  "image": {
    "data": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAA...",
    "context": "generic-document-front"
  }
}

  1. Patch session status to submitted status using PATCH /sessions/{sessionId}[↗] call.

    1. This endpoint requires endpoint level authentication via x-hmac-signature header. See  HMAC Authentication and Endpoint Security article for general info about signature creation.

Session update bash example

curl -X PATCH \
  --url 'https://exampleURL.com/v1/sessions/{sessionId}' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: your-api-key' \
  -H 'X-HMAC-SIGNATURE: your-hmac-signature' \
  -d '{
    "status": "submitted"
  }'
    

Session update json example

{
  "status": "submitted"
}
    

  1. Check the decision data and/or session related info from the decision webhook and/or query the data from the GET sessions/{sessionId}/decision[↗] endpoint. Solution-specific overview of what to expect is provided below in the Find decision and/or session related info > Solution-specific parameters section.


Find decision and/or session related info

You can get the data from three sources:

Solution-specific parameters

The info related to Unstructured Docs is returned in additionalVerifiedData.udocs array. This array contains data objects with info about different aspects (e.g.,  document classification, data extraction, data matching, document tampering) performed during the session.

Object

Description

Needs enablement by the SE?

Used in

udocs.classification

Identifies document type, country, and issuer. Core feature; always present, though nested fields are omitted if confidence is low.

No

Core feature, classification

udocs.documentExpiration

Checks the validity of the document based on either:

  • if document is not expired:  returns isWithinValidityPeriod boolean; or

  • if its issue date is within allowed range: returns isIssueDateInRange boolean. This is skipped and the key omitted when the document has expiry date and expiry date-based validation is enabled.

Yes

Document validity period check, validation

udocs.extraction

Extracted data fields (e.g., name, address). Keys appearing here depend on the use case and document type used. Keys are optional and can have an empty value or be completely omitted, depending on the use case configuration and data availability on document.

No

Core feature, extraction

udocs.fraud

Tampering and risk analysis. Omitted if feature is disabled. Returns riskLevel, though nested properties like indicatorsDescriptions may return as an empty array if no specific tampering markers are detected.

riskLevel: high results in declined status.

Yes

Tampering Check, add-on

udocs.matchingResults

Compares initData to extracted data. Omitted if feature is disabled or initData was not provided.

Invalid data results in declined status.

Yes

Name matching

Bank account number matching

Occupation info matching

udocs.metadata

A generic object, containing meta info about the document and verification process. Always present.

No

N/A

Note about object and field visibility

All objects and fields within the additionalVerifiedData.udocs array are optional. You should expect that any key may be omitted from the payload or return an empty or null value.

A field is included in the response only when:

  • The specific feature or add-on (e.g., Tampering Check or InitData Matching) has been configured for your integration by a solutions engineer

  • The use case setup defines which data fields need to be extracted

  • The system successfully extracts that specific data point from the end-user's document

Because the response schema is dynamic and based on both your specific configuration and the quality of the document provided, your application logic must account for omitted keys and null values as a standard part of the verification workflow.

Note on session outcomes

An approved session is identified by a verification.status of approved. The indicators of a “clean” session are found within the specific features’ and/or add-on’s objects.

Depending on your configuration, a session is approved when, for example:

  • fraud.riskLevel is LOW_RISK (if Tampering Check is enabled),

  • matchinResults.match is true  (if InitData Matching validation is enabled and initData was provided),

  • documentExpiration.isWithinValidityPeriod is true (if Document Expiration validation is enabled and the document has an expiry date that cleared the range threshold).

If these features/add-ons are not enabled, their respective objects/keys are omitted from the payload and do not impact the approved status.

Sample payload of udocs object

The following is a sample response for a declined session with all possible additionalVerifiedData.udocs object parameters.

All strings and IDs (e.g., fullName, documentType) are placeholder values used for illustrative purposes only. Your production payload will contain real-time data extracted from the end-user's document.

See the Request properties explained section below for info about the properties.

{
  "additionalVerifiedData": [
    {
      "udocs": {
        "metadata": {
          "pageCount": 2
        },
        "extraction": {
          "fullName": "JUAN MARTINEZ",
          "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100",
          "bankAccountNumber": "84532345",
          "issueDate": "2024-05-28",
          "expiryDate": "2025-05-28",
          "documentNumber": "847293651024738569",
          "vehicleIdentificationNumber": "1HGBH41JXMN109186",
          "vehicleRegistrationNumber": "ABC-1234",
          "occupation": "Driver",
          "income": "45000",
          "issuer": "Skrill Limited",
          "currency": "USD"
        },
        "classification": {
          "documentType": "financial",
          "documentSubType": "bank_statement",
          "countryCode": "mx",
          "language": "es",
          "issuer": "skrill_limited"
        },
        "matchingResults": [
          {
            "type": "full_name",
            "match": true,
            "originalValue": "JUAN MARTINEZ",
            "extractedValue": "JUAN MARTINEZ",
            "matchThreshold": 80,
            "matchPercentage": 100
          },
          {
            "type": "occupation",
            "match": true,
            "originalValue": "Driver",
            "extractedValue": "Driver",
            "matchThreshold": 80,
            "matchPercentage": 100
          }
        ],
        "fraud": {
          "riskLevel": "HIGH_RISK",
          "reason": "DIGITAL_MODIFICATION_HIGH_CONFIDENCE",
          "reasonDescription": "Document contains traces of digital modification, likely with fraudulent intent",
          "indicators": [
            "This document's metadata shows a creation time: 2023-03-31T12:04:01+00:00 and a modification time: 2024-05-29T11:30:26+00:00, suggesting the file was updated after it was first created. The time gap between creation and modification is 424 days, 23:26:25."
          ]
        },
        "documentExpiration": {
          "isIssueDateInRange": false,
          "isWithinValidityPeriod": false
        }
      }
    }
  ]
}

Sample payload with Address Matching and Address Validation info

The following is a sample response for a declined session showing objects that are sent when Address Matching and Address Validation add-ons have been enabled for the use case.

All strings and IDs (e.g., fullName, documentType) are placeholder values used for illustrative purposes only. Your production payload will contain real-time data extracted from the end-user's document.

See the Address Matching and Address Validation documentation for more info about the properties.

{
  "status": "success",
  "verification": {
    "acceptanceTime": "2026-02-18T13:39:54.401658Z",
    "submissionTime": "2026-02-18T13:40:22.784253Z",
    "decisionTime": "2026-02-18T13:41:47.173826Z",
    "code": 9102,
    "id": "f3a8b7c2-d4e1-4f92-a8b3-c5d6e7f8a9b0",
    "vendorData": null,
    "endUserId": null,
    "status": "declined",
    "reason": "Addresses do not match",
    "reasonCode": 573,
    "person": {
      "firstName": "JUAN MARTINEZ",
      "lastName": null,
      "fullName": "JUAN MARTINEZ",
      "citizenship": null,
      "idNumber": null,
      "gender": null,
      "dateOfBirth": null,
      "yearOfBirth": null,
      "placeOfBirth": null,
      "nationality": null,
      "addresses": [
        {
          "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100"
        }
      ],
      "pepSanctionMatch": null
    },
    "document": {
      "number": null,
      "type": "BANK_STATEMENT",
      "country": "MX",
      "validFrom": "2025-12-09",
      "validUntil": null,
      "state": null
    },
    "comments": [],
    "additionalVerifiedData": {
      "proofOfAddress": {
        "addressValidationResult": {
          "components": {
            "plausibleFullAddress": "CALLE MADERO 415 INT 5 COL CENTRO CUAUHTÉMOC CIUDAD DE MÉXICO MÉXICO CP 06000",
            "street": "CALLE MADERO",
            "city": "CUAUHTÉMOC",
            "state": "CIUDAD DE MÉXICO",
            "postcode": "06000",
            "country": "MÉXICO",
            "houseNumber": "415",
            "unit": "INT 5"
          },
          "addressType": "residential",
          "validations": {
            "countryExists": {
              "result": "skipped"
            }
          }
        }
      },
      "addressMatching": {
        "matchPercentage": 0,
        "matchThreshold": 80,
        "result": false,
        "addresses": [
          {
            "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100",
            "parsedAddress": {
              "street": "AV INSURGENTES SUR",
              "city": "BENITO JUAREZ",
              "state": "CIUDAD DE MEXICO",
              "postcode": "03100",
              "country": "MEXICO",
              "houseNumber": "2847",
              "unit": "PISO 3"
            }
          },
          {
            "fullAddress": "CALLE MADERO 415 INT 5 COL CENTRO CUAUHTÉMOC CIUDAD DE MÉXICO MÉXICO CP 06000",
            "parsedAddress": {
                "street": "CALLE MADERO",
                "city": "CUAUHTÉMOC",
                "state": "CIUDAD DE MÉXICO",
                "postcode": "06000",
                "country": "MÉXICO",
                "houseNumber": "415",
                "unit": "INT 5"
            }
          }
        ]
      },
      "udocs": {
        "metadata": {
          "pageCount": 1
        },
        "extraction": {
          "fullName": "JUAN MARTINEZ",
          "fullAddress": "CALLE MADERO 415 INT 5 COL CENTRO CUAUHTÉMOC CIUDAD DE MÉXICO MÉXICO CP 06000",
          "bankAccountNumber": "014180012345678902",
          "issueDate": "2025-12-09",
          "occupation": "",
          "income": "",
          "issuer": "Santander",
          "currency": "MXN"
        },
        "classification": {
          "documentType": "financial",
          "documentSubType": "bank_statement",
          "countryCode": "MX",
          "language": "ES",
          "issuer": "Santander"
        },
        "matchingResults": [
          {
            "type": "full_name",
            "match": true,
            "originalValue": "JUAN MARTINEZ",
            "extractedValue": "JUAN MARTINEZ",
            "matchThreshold": 80,
            "matchPercentage": 100
          },
          {
            "type": "occupation",
            "match": false,
            "originalValue": "Engineer",
            "extractedValue": "",
            "matchThreshold": 80,
            "matchPercentage": 0
          }
        ],
        "fraud": {
          "riskLevel": "HIGH_RISK",
          "reason": "ILLEGIBILITY",
          "reasonDescription": "Unreadable document",
          "indicators": [
            "This image appears to have been generated directly from a digital PDF. This is unusual and may suggest an attempt to conceal edits. Some organizations have policies restricting the acceptance and use of digital prints."
          ]
        },
        "documentExpiration": {
          "isIssueDateInRange": true
        }
      }
    },
    "attemptId": "b9c8d7e6-f5a4-4b32-9c8d-7e6f5a4b3c2d"
  },
  "technicalData": {
    "ip": null
  }
}

Webhook payload

The example below uses placeholder data to show all mandatory parameters and possible uDocs fields. While mandatory fields are always present, solution-specific keys are omitted if a feature is disabled or data extraction fails. Depending on your integration’s configuration, your production payload may contain additional parameters; for info on fields from other solutions, see the decision webhook documentation.

Sample request

The following features have been enabled for the session: Classification, Extraction, InitData Matching, Tampering Check, Document Expiration.

{
  "status": "success",
  "verification": {
    "acceptanceTime": "2026-02-04T11:57:36.495752Z",
    "submissionTime": "2026-02-04T11:57:43.127728Z",
    "decisionTime": "2026-02-04T11:58:15.073712Z",
    "code": 9102,
    "id": "f3a8b7c2-d4e1-4f92-a8b3-c5d6e7f8a9b0",
    "vendorData": null,
    "endUserId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "declined",
    "reason": "Name in initData does not match the document name",
    "reasonCode": 541,
    "person": {
      "firstName": null,
      "lastName": null,
      "fullName": "JUAN MARTINEZ",
      "citizenship": null,
      "idNumber": null,
      "gender": null,
      "dateOfBirth": null,
      "yearOfBirth": null,
      "placeOfBirth": null,
      "nationality": null,
      "addresses": [
        {
          "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100"
        }
      ],
      "pepSanctionMatch": null
    },
    "document": {
      "number": null,
      "type": null,
      "country": null,
      "validFrom": null,
      "validUntil": null,
      "state": null
    },
    "comments": [],
    "additionalVerifiedData": {
      "udocs": {
        "metadata": {
          "pageCount": 2
        },
        "extraction": {
          "fullName": "JUAN MARTINEZ",
          "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100",
          "bankAccountNumber": "84532345",
          "issueDate": "2024-05-28",
          "expiryDate": "2025-05-28",
          "documentNumber": "847293651024738569",
          "vehicleIdentificationNumber": "1HGBH41JXMN109186",
          "vehicleRegistrationNumber": "ABC-1234",
          "occupation": "Driver",
          "income": "45000",
          "issuer": "Skrill Limited",
          "currency": "USD"
        },
        "classification": {
          "documentType": "financial",
          "documentSubType": "bank_statement",
          "countryCode": "mx",
          "language": "es",
          "issuer": "skrill_limited"
        },
        "matchingResults": [
          {
            "type": "full_name",
            "match": true,
            "originalValue": "JUAN MARTINEZ",
            "extractedValue": "JUAN MARTINEZ",
            "matchThreshold": 80,
            "matchPercentage": 100
          },
          {
            "type": "occupation",
            "match": true,
            "originalValue": "Driver",
            "extractedValue": "Driver",
            "matchThreshold": 80,
            "matchPercentage": 100
          },
          {
            "type": "bank_account_number",
            "match": true,
            "originalValue": "AB123456789012345",
            "extractedValue": "AB123456789012345",
            "matchThreshold": 100,
            "matchPercentage": 100
          }
        ],
        "fraud": {
          "riskLevel": "HIGH_RISK",
          "reason": "DIGITAL_MODIFICATION_HIGH_CONFIDENCE",
          "reasonDescription": "Document contains traces of digital modification, likely with fraudulent intent",
          "indicators": [
            "This document's metadata shows a creation time: 2023-03-31T12:04:01+00:00 and a modification time: 2024-05-29T11:30:26+00:00, suggesting the file was updated after it was first created. The time gap between creation and modification is 424 days, 23:26:25."
          ]
        },
        "documentExpiration": {
          "isIssueDateInRange": false,
          "isWithinValidityPeriod": false
        }
      }
    },
    "attemptId": "b9c8d7e6-f5a4-4b32-9c8d-7e6f5a4b3c2d"
  },
  "technicalData": {
    "ip": null
  }
}

Request properties explained

  • status: string Status of the response

  • verification: object | null Verification request decision object. null if decision is not available yet

    • id: string UUID v4 which identifies the verification session

    • attemptId: string UUID v4 of the attempt which received a status (as shown in verification.status field)

    • vendorData: string | null The unique identifier that you created for your end-user. null if not specified

    • endUserId: string | null The UUID that you created for your end-user. null if not specified

    • status: string Verification status, one of approved, declined, expired, abandoned

    • code: integer Verification session decision code, one of 9001, 9102, 9103, 9104, 9121. For more info, see the verification session decision codes

    • reason: string | null Reason why the verification failed

    • reasonCode: integer | null Reason code of the failed verification. For more info, see the possible codes for a failed verification

    • acceptanceTime: string Timestamp of the session generation, represented as UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset (ISO 8601)

    • submissionTime: string Timestamp of when the session was submitted, represented as UTC YYYY-MM-DDTHH:MM:SS.SSSSSS+Timezone Offset (ISO 8601)

    • decisionTime: string | null Timestamp of the decision, represented as UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset (ISO 8601)

    • person: object Data about the verified person

      • firstName: string | null Person's first name as written on the document

      • lastName: string | null Person's last name as written on the document

      • fullName: string | null Full name of the person

      • citizenship: null Deprecated, always returns null

      • idNumber: string | null National identification number

      • gender: string | null Person's gender, represented as M or F, or null if not present

      • dateOfBirth: string | null Person's date of birth, represented as YYYY-MM-DD

      • yearOfBirth: string | null Person's year of birth, represented as YYYY

      • placeOfBirth: string | null Person's place of birth

      • nationality: string | null Person's nationality, represented as ISO 3166 alpha-2 or alpha-3 number

      • addresses: array A map with keys for fullAddress

        • fullAddress: string | null Address as single string

    • document: object Verified document

      • number: string | null Document number, [a-zA-Z0-9] characters only

      • type: string | null Document type

      • country: string | null Document issuing country, represented as ISO 3166 alpha-2 code

      • validFrom: string | null Document is valid from date, represented as YYYY-MM-DD. Optional, must be configured for your integration by the Solutions Engineer

      • validUntil: string | null Document is valid until date, represented as YYYY-MM-DD. Optional, must be configured for your integration by the Solutions Engineer

      • state: string | null Document issuing state, represented as ISO 3166 alpha-2 or alpha-3 code

    • additionalVerifiedData: object Data that has been optionally verified for the session

      • udocs: object Container for the features’ and add-ons’ results

        • metadata: object Contains meta info about the document and verification process

          • pageCount: integer Indicates how many pages were processed

        • extraction: object Returning info about all the data that was extracted

          • fullName: string Person’s full name data from document

          • fullAddress: string Person’s full address data from document

          • bankAccountNumber: string Person’s bank account number from document

          • issueDate: string Document issue date data from document

          • expiryDate: string Document expiry date data from document

          • documentNumber: string Document number from document, e.g., policy number, certificate number, document reference number

          • vehicleIdentificationNumber: string The unique 17-character VIN of the vehicle, as present on document

          • vehicleRegistrationNumber: string Vehicles registration number data, as present on document

          • occupation: string Person’s occupation data from document

          • income: string Person’s income amount from document

          • issuer: string Document issuer name from document

          • currency: string Currency as shown on document

        • classification: object Contains data about document’s type, country code, language and issuer

          • documentType: string Document types’ grouping, one of financial, government, housing, insurance, legal, tax, utility, other

          • documentSubType: string Document’s type (see possible values in Supported document types section)

          • countryCode: string Document’s country, represented as ISO 3166 alpha-2

          • language: string Document’s language, represented as ISO 3166 alpha-2

          • issuer: string Document issuing entity

        • matchingResults: array Returns info about how initData matched to document data. Available only when the initData matching validation was enabled for your uDocs integration.

          • type: string Indicates the initData field that was matched to extracted data

          • match: boolean Indicates if match was true or false

          • originalValue: string Echoes the initData value

          • extractedValue: string Returns the value extracted form document

          • matchThreshold: integer Shows the match threshold set for the specific field

          • matchPercentage: integer Returns the match percentage

        • fraud: object Returns data about document integrity. Available only if Tampering check is enabled for your uDocs integration.

          • riskLevel: string Indicates the risk level of the document, possible values LOW_RISK, MEDIUM_RISK, HIGH_RISK . null if the check was not executed or failed.

          • reason: string  Short description indicating the reason behind the risk level. null if the check was not executed or failed.

          • reasonDescription: string Human readable explanation of the data in the reason field. null if the check was not executed or failed.

          • indicators: array Array strings listing the factors that influenced the risk assessment. Empty if the check was not executed or failed.

        • documentExpiration: object Returns data about document expiration. Available only if Document Expiration check is enabled for your uDocs integration.

          • isIssueDateInRange: boolean Checks if document’s issue date clears the allowed range threshold (days since issue date). Skipped if the document has an expiry date and and expiry date check has been enabled.

          • isWithinValidityPeriod: boolean Checks if document’s expiration date clears the range threshold (days before expiration date)

    • pepSanctionMatch: string | null Legacy field, may return incorrect result, should be ignored

    • comments: array (Deprecated) Always returns empty []

  • technicalData: object Technical data object

    • ip: string | null IP of the device from which the verification was made

API call

The example below uses placeholder data to show all mandatory parameters and possible uDocs fields. While mandatory fields are always present, solution-specific keys are omitted if a feature is disabled or data extraction fails. Depending on your configuration, the payload may contain additional parameters; for info on fields from other solutions, see the GET sessions/{sessionId}/decision[↗] API documentation.

Sample response

The following features have been enabled for the session: Classification, Extraction, InitData Matching, Tampering Check, Document Expiration.

{
  "status": "success",
  "verification": {
    "acceptanceTime": "2026-02-04T11:57:36.495752Z",
    "submissionTime": "2026-02-04T11:57:43.127728Z",
    "decisionTime": "2026-02-04T11:58:15.073712Z",
    "code": 9102,
    "id": "f3a8b7c2-d4e1-4f92-a8b3-c5d6e7f8a9b0",
    "vendorData": null,
    "endUserId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "declined",
    "reason": "Name in initData does not match the document name",
    "reasonCode": 541,
    "person": {
      "firstName": null,
      "lastName": null,
      "fullName": "JUAN MARTINEZ",
      "citizenship": null,
      "idNumber": null,
      "gender": null,
      "dateOfBirth": null,
      "yearOfBirth": null,
      "placeOfBirth": null,
      "nationality": null,
      "addresses": [
        {
          "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100"
        }
      ],
      "pepSanctionMatch": null
    },
    "document": {
      "number": null,
      "type": null,
      "country": null,
      "validFrom": null,
      "validUntil": null,
      "state": null
    },
    "comments": [],
    "additionalVerifiedData": {
      "udocs": {
        "metadata": {
          "pageCount": 2
        },
        "extraction": {
          "fullName": "JUAN MARTINEZ",
          "fullAddress": "AV INSURGENTES SUR 2847 PISO 3 COL DEL VALLE BENITO JUAREZ CIUDAD DE MEXICO MEXICO CP 03100",
          "bankAccountNumber": "84532345",
          "issueDate": "2024-05-28",
          "expiryDate": "2025-05-28",
          "documentNumber": "847293651024738569",
          "vehicleIdentificationNumber": "1HGBH41JXMN109186",
          "vehicleRegistrationNumber": "ABC-1234",
          "occupation": "Driver",
          "income": "45000",
          "issuer": "Skrill Limited",
          "currency": "USD"
        },
        "classification": {
          "documentType": "financial",
          "documentSubType": "bank_statement",
          "countryCode": "mx",
          "language": "es",
          "issuer": "skrill_limited"
        },
        "matchingResults": [
          {
            "type": "full_name",
            "match": true,
            "originalValue": "JUAN MARTINEZ",
            "extractedValue": "JUAN MARTINEZ",
            "matchThreshold": 80,
            "matchPercentage": 100
          },
          {
            "type": "occupation",
            "match": true,
            "originalValue": "Driver",
            "extractedValue": "Driver",
            "matchThreshold": 80,
            "matchPercentage": 100
          },
          {
            "type": "bank_account_number",
            "match": true,
            "originalValue": "AB123456789012345",
            "extractedValue": "AB123456789012345",
            "matchThreshold": 100,
            "matchPercentage": 100
          }
        ],
        "fraud": {
          "riskLevel": "HIGH_RISK",
          "reason": "DIGITAL_MODIFICATION_HIGH_CONFIDENCE",
          "reasonDescription": "Document contains traces of digital modification, likely with fraudulent intent",
          "indicators": [
            "This document's metadata shows a creation time: 2023-03-31T12:04:01+00:00 and a modification time: 2024-05-29T11:30:26+00:00, suggesting the file was updated after it was first created. The time gap between creation and modification is 424 days, 23:26:25."
          ]
        },
        "documentExpiration": {
          "isIssueDateInRange": false,
          "isWithinValidityPeriod": false
        }
      }
    },
    "attemptId": "b9c8d7e6-f5a4-4b32-9c8d-7e6f5a4b3c2d"
  },
  "technicalData": {
    "ip": null
  }
}

Response properties explained

  • status: string Status of the response

  • verification: object | null Verification request decision object. null if decision is not available yet

    • id: string UUID v4 which identifies the verification session

    • attemptId: string UUID v4 of the attempt which received a status (as shown in verification.status field)

    • vendorData: string | null The unique identifier that you created for your end-user. null if not specified

    • endUserId: string | null The UUID that you created for your end-user. null if not specified

    • status: string Verification status, one of approved, declined, expired, abandoned

    • code: integer Verification session decision code, one of 9001, 9102, 9103, 9104, 9121. For more info, see the verification session decision codes

    • reason: string | null Reason why the verification failed

    • reasonCode: integer | null Reason code of the failed verification. For more info, see the possible codes for a failed verification

    • acceptanceTime: string Timestamp of the session generation, represented as UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset (ISO 8601)

    • submissionTime: string Timestamp of when the session was submitted, represented as UTC YYYY-MM-DDTHH:MM:SS.SSSSSS+Timezone Offset (ISO 8601)

    • decisionTime: string | null Timestamp of the decision, represented as UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset (ISO 8601)

    • person: object Data about the verified person

      • firstName: string | null Person's first name as written on the document

      • lastName: string | null Person's last name as written on the document

      • fullName: string | null Full name of the person

      • citizenship: null Deprecated, always returns null

      • idNumber: string | null National identification number

      • gender: string | null Person's gender, represented as M or F, or null if not present

      • dateOfBirth: string | null Person's date of birth, represented as YYYY-MM-DD

      • yearOfBirth: string | null Person's year of birth, represented as YYYY

      • placeOfBirth: string | null Person's place of birth

      • nationality: string | null Person's nationality, represented as ISO 3166 alpha-2 or alpha-3 number

      • addresses: array A map with keys for fullAddress

        • fullAddress: string | null Address as single string

    • document: object Verified document

      • number: string | null Document number, [a-zA-Z0-9] characters only

      • type: string | null Document type

      • country: string | null Document issuing country, represented as ISO 3166 alpha-2 code

      • validFrom: string | null Document is valid from date, represented as YYYY-MM-DD. Optional, must be configured for your integration by the Solutions Engineer

      • validUntil: string | null Document is valid until date, represented as YYYY-MM-DD. Optional, must be configured for your integration by the Solutions Engineer

      • state: string | null Document issuing state, represented as ISO 3166 alpha-2 or alpha-3 code

    • additionalVerifiedData: object Data that has been optionally verified for the session

      • udocs: object Container for the features’ and add-ons’ results

        • metadata: object Contains meta info about the document and verification process

          • pageCount: integer Indicates how many pages were processed

        • extraction: object Returning info about all the data that was extracted

          • fullName: string Person’s full name data from document

          • fullAddress: string Person’s full address data from document

          • bankAccountNumber: string Person’s bank account number from document

          • issueDate: string Document issue date data from document

          • expiryDate: string Document expiry date data from document

          • documentNumber: string Document number from document, e.g., policy number, certificate number, document reference number

          • vehicleIdentificationNumber: string The unique 17-character VIN of the vehicle, as present on document

          • vehicleRegistrationNumber: string Vehicles registration number data, as present on document

          • occupation: string Person’s occupation data from document

          • income: string Person’s income amount from document

          • issuer: string Document issuer name from document

          • currency: string Currency as shown on document

        • classification: object Contains data about document’s type, country code, language and issuer

          • documentType: string Document types’ grouping, one of financial, government, housing, insurance, legal, tax, utility, other

          • documentSubType: string Document’s type (see possible values in Supported document types section)

          • countryCode: string Document’s country, represented as ISO 3166 alpha-2

          • language: string Document’s language, represented as ISO 3166 alpha-2

          • issuer: string Document issuing entity

        • matchingResults: array Returns info about how initData matched to document data. Available only when the initData matching validation was enabled for your uDocs integration.

          • type: string Indicates the initData field that was matched to extracted data

          • match: boolean Indicates if match was true or false

          • originalValue: string Echoes the initData value

          • extractedValue: string Returns the value extracted form document

          • matchThreshold: integer Shows the match threshold set for the specific field

          • matchPercentage: integer Returns the match percentage

        • fraud: object Returns data about document integrity. Available only if Tampering check is enabled for your uDocs integration.

          • riskLevel: string Indicates the risk level of the document, possible values LOW_RISK, MEDIUM_RISK, HIGH_RISK . null if the check was not executed or failed.

          • reason: string  Short description indicating the reason behind the risk level. null if the check was not executed or failed.

          • reasonDescription: string Human readable explanation of the data in the reason field. null if the check was not executed or failed.

          • indicators: array Array strings listing the factors that influenced the risk assessment. Empty if the check was not executed or failed.

        • documentExpiration: object Returns data about document expiration. Available only if Document Expiration check is enabled for your uDocs integration.

          • isIssueDateInRange: boolean Checks if document’s issue date clears the allowed range threshold (days since issue date). Skipped if the document has an expiry date and and expiry date check has been enabled.

          • isWithinValidityPeriod: boolean Checks if document’s expiration date clears the range threshold (days before expiration date)

    • pepSanctionMatch: string | null Legacy field, may return incorrect result, should be ignored

    • comments: array (Deprecated) Always returns empty []

  • technicalData: object Technical data object

    • ip: string | null IP of the device from which the verification was made

Veriff Customer Portal

You can find the verification session related info, including the decision, in the Veriff Customer Portal, in the All Verifications > session > Webhooks tab.

See Review verification in Veriff Customer Portal about how to view the session info in the Veriff Customer portal


Status and reason codes

For an approved session, see:

  • verification.code about verification session decision code, one of 9001

  • verification.status about verification status, one of approved

If the Unstructured Docs session was declined, you can find additional information by checking:

  • verification.reason for the reason why the verification failed

  • verification.reasonCode for reason code of the failed verification and cross-reference it with Granular reason codes (table)

verification.status

verification.reasonCode

verification.reason

What does it mean?

declined

510

Document type not supported

Document type not in accepted list or classified as "OTHER"

declined

511

Document expired / issued too long ago

Document is expired or beyond validity period

declined

541

Name on document does not match session data

Extracted name match score is below required threshold

declined

566

System processing error

Internal system error or processing timeout

declined

568

Invalid Input / Mandatory fields failed

Mandatory fields could not be extracted or initData is missing

declined

572

Document number mismatch

Extracted number (e.g. bank account) does not match initData

declined

628

Unable to collect issue date

The issue date could not be extracted from the document

declined

629

Unable to collect expiry date

The expiry date could not be extracted from the document

The table above aims to list the most common reasons why you may see the decline reason for an Unstructured Docs session. However, the session may be declined due to a reason that is not inherently Unstructured Docs verification related (e.g. uploaded document’s quality is low). In that case, to find info about the codes you are seeing, refer to:


Additional information

Best Practices

  • Document image quality: ensure that end-user’s document image is of good quality. This will reduce the possibility of session being declined or extraction failures happening.

  • Error handling: implement proper error handling for all possible validation results. For processing timeouts (566), implement retry logic with exponential backoff.

  • Session declined due to third-party provider issues: implement proper session handling flow when possibly legitimate end-user’s session is declined due to internal system errors, as indicated by session code 566.

  • Webhook security: secure your webhook endpoint and verify request signatures.

  • Ensure backwards-compatible-changes for webhooks and API connections


Changelog

Date

Description

Feb 20, 2026

Sample payload with Address Matching and Address Validation info added

Feb 19, 2026

Documentation published