---
title: "Proof of Address"
slug: "proof-of-address-verification"
description: "Verify your end-users' addresses to comply with your Know Your Customer (KYC) and due diligence obligations"
tags: ["Address Matching", "Address Validation", "Address Verification", "Fraud Validation", "Name Matching", "Proof of Address"]
updated: 2026-04-22T07:13:34Z
published: 2026-04-22T07:13:34Z
---

> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.veriff.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Proof of Address

| Available via API | Available via SDK | Needs configuration on Veriff’s side | Needs a separate integration | Needs a separate webhook |
| --- | --- | --- | --- | --- |
| ✅ | ✅ | ✅ | ✅ | ❌ |

The Proof of Address (PoA) solution automates the verification of end-user addresses by capturing and extracting data from documents such as bank statements and utility bills, matching name data, and by checking the integrity of the document.

The core solution validates document type and issue date, extracts name and address information. It is possible to improve the solution further by enabling address validation and address matching, name matching, fraud validation to check document integrity, and document expiration check.

All the extracted and checked data is provided via API or Veriff Customer Portal.

The automatic Proof of Address solution is available via API, web flow, and native SDKs. The flow is set up via **Workflows** in the Veriff Customer Portal.

> [!NOTE]
> Contact your **solutions engineer** for info and configuration.

## Prerequisites

- You have an [integration set up](/v1/docs/how-to-create-an-integration) with Veriff
- The Proof of Address **check is configured** **by your Solutions Engineer**
- You have configured the [decision webhook](/v1/docs/decision-webhook) to get responses from Veriff (see the how-to in webhooks’ [Set up webhooks](https://devdocs.veriff.com/docs/webhooks-guide#set-up-webhooks) section)
- If using the **API**, you are ready to collect and **send** Veriff your **end-user’s data and document images**
- Veriff **strongly recommends** that you **create and send** us the endUserId or vendorData

### Key terminology

| Term | Description |
| --- | --- |
| 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 [below](/v1/docs/proof-of-address-verification#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 [below](/v1/docs/proof-of-address-verification#address-validation) documentation for more info. |
| Document Expiration | Data validation process that checks the validity of the document based on its its issue date. Outputs data in `udocs.validations.documentExpiration.isWithinValidityPeriod` string in decision webhook payload and GET /decision API response. See [below](/v1/docs/proof-of-address-verification#document-expiration) for more info. |
| Supported document type | Document type that can be used to perform the verification. See [below](/v1/docs/proof-of-address-verification#define-acceptable-document-types-optional) for more info. |
| Tampering Check | Fraud detection feature that analyzes documents for signs of tampering. Outputs data in `additionalVerifiedData.proofOfAddress.fraud` object in the decision webhook payload and GET /decision API response. See [below](/v1/docs/proof-of-address-verification#note-about-the-tampering-check) for more info. |
| 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. |

### Define acceptable document types (optional)

> [!CAUTION]
> **Not available by default.**
> 
> Contact your **solutions engineer** for info and configuration.

To add more flexibility to the solution, you have the option to define which document types are accepted to perform the verification. Note that this option is not available by default.

When enabled for your solution, you can pass the document types when creating a session with POST /sessions, using the `proofOfAddress.acceptableTypes` array.

Example request to start a session:

```json
{
  "verification": {
    "proofOfAddress": {
      "acceptableTypes": [
        {"name": "MOBILE_BILL"},
        {"name": "PHONE_BILL"}
      ]
    }
  }
}
```

*→ See the*[*Supported document types*](https://devdocs.veriff.com/v1/docs/supported-document-types#proof-of-address-verification)*article for**a list of document types*

---

## Flow overview

The flow is a bit different, depending on the Proof of Address related solutions you are using, and wether you are using Veriff through SDK or via API.

Available solutions:

- [Proof of Address Extraction](/v1/docs/proof-of-address-verification#proof-of-address-extraction) (via SDK and API)
- [Address Validation](/v1/docs/proof-of-address-verification#address-validation) (via SDK and API)
- [Address Matching](/v1/docs/proof-of-address-verification#address-matching) (via SDK and API)

### Proof of Address Extraction

This solution is used to **extract data from the end-user’s document**.

#### Create session and send end-user data

SDKAPI

1. Generate a session using the API keys and the BaseURL of your PoA integration (see the <meta charset="utf-8">[API Documentation and API Reference](https://devdocs.veriff.com/apidocs)[↗] how to find these)
  1. You can use the `proofOfAddress.acceptableTypes` array to define which types of PoA documents the integration accepts (note available by default, needs configuration on Veriff’s side)
2. Capture end-user’s document images with Veriff’s SDKs
  1. Send the end-user through the verification flow to capture the image (using the preferred Veriff SDK)
  2. You need the session URL generated in step 1 to use the SDKs (found in response payload as verification.url)
3. Session will be submitted automatically once the end-user takes and submits necessary images of their document
4. Receive the results from Veriff via decision webhook

**1. Create a session using the POST /sessions call**

**1.1 Include the API URL and mandatory headers**

```plaintext
POST {baseURL}/v1/sessions
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       Content-Type: application/json
```

**1.2 Add the following data (minimum payload)**

- `verification`: `object` Verification object*. You can send an empty object, or:
  - define the acceptable document types** with:
    - `proofOfAddress.acceptableTypes` array, defining them in the `name` string(s)
  - include the following to improve the results:
    - `vendorData`: `string`
    - `endUserId:` `string`
  - include the `person.firstName` and `person.lastName` to do the name match

*Mandatory parameter

**Option not available by default, must be enabled on Veriff’s side

**Request payload sample**

```bash
curl -X POST \
  --url '/v1/sessions/' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -d '{
    "verification": {
        "person": {
            "firstName": "John",
            "lastName": "Smith"
        },
        "proofOfAddress": {
            "acceptableTypes": [
                {"name": "UTILITY_BILL"},
                {"name": "TAX_DOCUMENT"},
                {"name": "PHONE_BILL"}
            ]
        },
        "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4"
    }
}'
```

*→ See the <meta charset="utf-8">[POST /sessions](https://veriff-dev-documentation.document360.io/apidocs/v1sessions)[↗] endpoint documentation for further details about how to start a session*

**2. Make a POST /sessions/{sessionId}/media request**

Send only **one image per verification session**. Make sure that the value of `image.context` parameter of the image is `document-front`.

**2.1 Include the API URL and mandatory headers**

```plaintext
POST {baseURL}/v1/sessions/{sessionId}/media
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       X-HMAC-SIGNATURE: string (required) = sessionId signed with the shared secret key
       Content-Type: application/json
```

**2.2 Add the following data into the minimum payload**

- `image`: `object`*
  - `context`: `string`* In this case, it must be `document-front`
  - `content`: `string`* Base64 encoded image (.jpg, .jpeg, .png, .heif, .heic, .webp and .pdf formats are supported)

*Required parameter

**Request payload sample**

```bash
curl -X POST \
  --url '/v1/sessions/aea9ba6d-1b47-47fc-a4fc-f72b6d3584a7/media' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -H 'X-HMAC-SIGNATURE: 034c6da2bb31fd9e6892516c6d7b90ebe10f79b47cfb3d155d77b4d9b66e1d53' \
  -d '{
    "image": {
        "context": "document-front",
        "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII="
    }
}'
```

*→ See the <meta charset="utf-8">[POST /sessions/{sessionId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsidmedia-3)[↗] endpoint documentation for further details about how to send media files*

**3. Update the session status to `submitted` using the PATCH /sessions/{sessionId} call**

**3.1 Include the API URL and mandatory headers**

```plaintext
PATCH {baseURL}/v1/sessions/{sessionId}
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       X-HMAC-SIGNATURE: string (required) = sessionId signed with the shared secret key
       Content-Type: application/json
```

**3.2 Add the following data (minimum payload)**

- `verification`: `object`*
  - `status`: `string`* Status of the verification session you are patching the session into, always `submitted`

*Required parameter

**Request payload sample**

```bash
curl -X PATCH \
  --url '/v1/sessions/fd5c1563-1d23-4b1a-ae46-7ba429927ed8' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -H 'X-HMAC-SIGNATURE: dd994f70b1150ae012f9c1d6d20adf7ed69780044835d39de20b00ffae0660a0' \
  -d '{
    "verification": {
      "status": "submitted"
    }
}'
```

Once done, an [event webhook](/v1/docs/event-webhook) with `submitted` status will be sent.

1. Wait for the session to be approved and decision webhook to send response (see the webhook payload subsection below)
2. Now you can use the following API calls to query the document info:

- <meta charset="utf-8">[GET /sessions/{sessionId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsidmedia-2)[↗] to get a list of media objects and address media with the sessionId
- <meta charset="utf-8">[GET /attempts/{attemptId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1attemptsidmedia-1)[↗] to get a list of media objects and address media with the attempt ID
- <meta charset="utf-8">[GET /media/{mediaId}](https://veriff-dev-documentation.document360.io/apidocs/v1mediaid-1)[↗] to get a media file with the mediaId

#### Find session and/or decision related data

You can get the data from three sources:

- Receive the decision webhook
- Query the results via GET sessions/{sessionId}/decision
- View the session in Veriff Customer Portal (see [below](/v1/docs/proof-of-address-verification#find-decision-andor-session-related-info-in-veriff-customer-portal) for more info)

*****Click to open decision webhook example*****

> [!NOTE]
> Below are a **sample** and an **explanation** of a **decision webhook payload for a minimal****Proof of Address Verification**.
> 
> Depending on your solution, the payload may contain additional parameters. To find more info about it, see the [decision webhook](/v1/docs/decision-webhook)documentation.

**Sample request**

```json
{
    "status": "success",
    "verification": {
        "id": "ab1c2345-678d-4e3b-98a3-a75b00b715kj",
        "attemptId": "c6cab5b0-c506-47a6-922d-6ae3b72ca172",
        "code": 9001,
        "person": {
            "gender": null,
            "idNumber": null,
            "lastName": null,
            "addresses": [
                {
                    "fullAddress": "Jaan Koorti 777, 99999 Tallinn, Estonia"
                }
            ],
            "firstName": "Jane Doe",
            "citizenship": null,
            "dateOfBirth": null,
            "nationality": null,
            "yearOfBirth": null,
            "placeOfBirth": null,
            "pepSanctionMatch": null
        },
        "reason": null,
        "status": "approved",
        "comments": [],
        "document": {
            "type": null,
            "number": null,
            "country": null,
            "validFrom": "2023-11-25",
            "validUntil": null
        },
        "reasonCode": null,
        "vendorData": null,
        "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",
        "decisionTime": "2024-01-23T10:31:05.293000Z",
        "acceptanceTime": "2024-01-23T10:25:40.026Z",
        "additionalVerifiedData": {
            "proofOfAddress": {
                "documentType": "UTILITY_BILL",
                "nameMatch": true,
                "nameMatcPercentage": 100.00,
                "fraud": {
                    "riskLevel": "HIGH_RISK",
                    "reason": "PDF_PROCESSED_BY_EDITOR",
                    "reasonDescription": "Document was processed using editing software",
                    "indicators": []
                }
            },
         },
    }
    "technicalData": {
        "ip": null
}
```

**Request properties explained**

*Required field

- `status`: `string`* Status of the response
- `verification`: `object`* 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`, `resubmission_requested`, `review`, `expired`,` abandoned`
  - `code`: `integer`* Verification session decision code, one of `9001`, `9102`, `9103`, `9104`, `9121`. For more info, see the [verification session decision codes](/v1/docs/verification-session-decision-codes-table)
  - `reason`: `string | null` Reason why the verification failed, only sent when the verification failed
  - `reasonCode`: `integer | null` Reason code of the failed verification, only sent when the verification failed. For more info, see the [possible codes for a failed verification](/v1/docs/verification-session-decision-codes-table)
  - `decisionTime`: `string | null`* Timestamp of the decision, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601)
  - `acceptanceTime`: `string`* Timestamp of the session generation, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601)
  - **`person`: `object`* Data about the verified person**

    - `gender`: `string | null`* Person’s gender, represented as M or F, or `null` if not present
    - `idNumber`: `string | null`* National identification number
    - `lastName`: `string | null`* `null`, unless prefilled by the customer
    - `addresses`: `array`* Array of person's addresses
      - `fullAddress`: `string` Address as a single string
    - `firstName`: `string | null`* Person's first name as written on the document, if available
    - `dateOfBirth`: `string`* Person’s date of birth, represented as `YYYY-MM-DD`
    - `nationality`: `string | null`* Person's nationality
    - `yearOfBirth`: `string | null`* Person’s year of birth, represented as `YYYY`
    - `placeOfBirth`: `string | null`* Person's place of birth
    - `pepSanctionMatch`*:*`string | null`****Legacy field, may return incorrect result, should be ignored*
    - `citizenship`: `string | null`* *Deprecated, always returns null*
  - **`document`: `object`*** Verified document**

    - `type`: `string | null `Document type
    - `number`: `string | null` Document number, `[a-zA-Z0-9]` characters only
    - `country`: `string | null` Document issuing country, represented as ISO 3166 `alpha-2` code
    - `validUntil`: `string | null` Document is valid until date, represented as `YYYY-MM-DD`. Optional, must be configured for your integration by the Solutions Engineer
    - `validFrom`: `string | null`* Document is valid from date, represented as `YYYY-MM-DD`
  - **`additionalVerifiedData`: `object`*** Data which has been optionally verified for session**

    - `proofOfAddress`: `object`* Proof of address data. Optional, available only if the name match check has been enabled for the integration
      - `documentType` : `string`* Indicates the type of the document. `null` if the check could not be completed.
      - `nameMatch`: `boolean | null` Indicates if the name on the document matches the name from the initial request data. `null` if the check could not be completed. Sent only when the name match check was enabled.
      - `nameMatchPercentage`: `float| null` Indicates the level of similarity the matched names have, in the range of 0.00-100.00. `null` if the check could not be completed. Sent only when the name match check was enabled.
      - `fraud`: `object` Returns data about document integrity. Available only if the [Tampering Check](/v1/docs/proof-of-address-verification#note-about-the-tampering-check) has been enabled for your integration.
        - `riskLevel`: `string | null` Indicates the risk level, possible values `LOW_RISK`, `MEDIUM_RISK`, `HIGH_RISK` . `null` if the check was not executed or failed.
        - `reason`: `string | null` Short description indicating the reason behind the risk level. `null` if the check was not executed or failed.
        - `reasonDescription`: `string | null` 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.
  - `comments`*:*`array`****(Deprecated)*
- `technicalData`: `object`*** Technical data
  - `ip`: `string | null` IP of the device from which the verification was made

*****Click to open API GET sessions/sessionId/decision endpoint example*****

> [!NOTE]
> Below are a **sample** and an **explanation** of a **API call payload for a minimal****Proof of Address Verification**.
> 
> Depending on your solution, the payload may contain additional parameters. To find more info about it, see the <meta charset="utf-8">[GET sessions/{sessionId}/decision](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsiddecision-1)[↗] documentation.

**Sample response**

```json
{
    "status": "success",
    "verification": {
        "id": "ab1c2345-678d-4e3b-98a3-a75b00b715kj",
        "attemptId": "c6cab5b0-c506-47a6-922d-6ae3b72ca172",
        "code": 9001,
        "person": {
            "gender": null,
            "idNumber": null,
            "lastName": null,
            "addresses": [
                {
                    "fullAddress": "Jaan Koorti 777, 99999 Tallinn, Estonia"
                }
            ],
            "firstName": "Jane Doe",
            "citizenship": null,
            "dateOfBirth": null,
            "nationality": null,
            "yearOfBirth": null,
            "placeOfBirth": null,
            "pepSanctionMatch": null
        },
        "reason": null,
        "status": "approved",
        "comments": [],
        "document": {
            "type": null,
            "number": null,
            "country": null,
            "validFrom": "2023-11-25",
            "validUntil": null
        },
        "reasonCode": null,
        "vendorData": null,
        "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4",
        "decisionTime": "2024-01-23T10:31:05.293000Z",
        "acceptanceTime": "2024-01-23T10:25:40.026Z",
        "additionalVerifiedData": {
            "proofOfAddress": {
                "documentType": "UTILITY_BILL",
                "nameMatch": true,
                "nameMatcPercentage": 100.00,
                "fraud": {
                    "riskLevel": "HIGH_RISK",
                    "reason": "PDF_PROCESSED_BY_EDITOR",
                    "reasonDescription": "Document was processed using editing software",
                    "indicators": []
                }
            },
         },
    }
    "technicalData": {
        "ip": null
}
```

**Response properties explained**

#### 

- `status`: `string` Status of the response
- `verification`: `object` 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`, `resubmission_requested`, `review`, `expired`,` abandoned`
  - `code`: `integer` Verification session decision code, one of `9001`, `9102`, `9103`, `9104`, `9121`. For more info, see the [verification session decision codes](/v1/docs/verification-session-decision-codes-table)
  - `reason`: `string | null` Reason why the verification failed, only sent when the verification failed
  - `reasonCode`: `integer | null` Reason code of the failed verification, only sent when the verification failed. For more info, see the [possible codes for a failed verification](/v1/docs/verification-session-decision-codes-table)
  - `decisionTime`: `string` Timestamp of the decision, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601)
  - `acceptanceTime`: `string` Timestamp of the session generation, represented as `UTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset` (ISO 8601)
  - **`person`: `object` Data about the verified person**

    - `gender`: `string | null` Person’s gender, represented as M or F, or `null` if not present
    - `idNumber`: `string | null` National identification number
    - `lastName`: `string | null` `null`, unless prefilled by the customer
    - `addresses`: `array` Array of person's addresses
      - `fullAddress`: `string` Address as a single string
    - `firstName`: `string | null` Person's first name as written on the document, if available
    - `dateOfBirth`: `string` Person’s date of birth, represented as `YYYY-MM-DD`
    - `nationality`: `string | null` Person's nationality
    - `yearOfBirth`: `string | null` Person’s year of birth, represented as `YYYY`
    - `placeOfBirth`: `string | null` Person's place of birth
    - `pepSanctionMatch`*:*`string | null`*Legacy field, may return incorrect result, should be ignored*
    - `citizenship`: `string | null` *Deprecated, always returns null*
  - **`document`: `object` Verified document**

    - `type`: `string | null `Document type
    - `number`: `string | null` Document number, `[a-zA-Z0-9]` characters only
    - `country`: `string | null` Document issuing country, represented as ISO 3166 `alpha-2` code
    - `validUntil`: `string | null` Document is valid until date, represented as `YYYY-MM-DD`. Optional, must be configured for your integration by the Solutions Engineer
    - `validFrom`: `string | null` Document is valid from date, represented as `YYYY-MM-DD`
  - **`additionalVerifiedData`: `object` Data which has been optionally verified for session**

    - `proofOfAddress`: `object` Proof of address data. Optional, available only if the name match check has been enabled for the integration
      - `documentType` : `string` Indicates the type of the document. `null` if the check could not be completed.
      - `nameMatch`: `boolean | null` Indicates if the name on the document matches the name from the initial request data. `null` if the check could not be completed. Sent only when the name match check was enabled.
      - `nameMatchPercentage`: `float| null` Indicates the level of similarity the matched names have, in the range of 0.00-100.00. `null` if the check could not be completed. Sent only when the name match check was enabled.
      - `fraud`: `object` Returns data about document integrity. Available only if the [Tampering Check](/v1/docs/proof-of-address-verification#note-about-the-tampering-check) has been enabled for your integration.
        - `riskLevel`: `string | null` Indicates the risk level, possible values `LOW_RISK`, `MEDIUM_RISK`, `HIGH_RISK` . `null` if the check was not executed or failed.
        - `reason`: `string | null` Short description indicating the reason behind the risk level. `null` if the check was not executed or failed.
        - `reasonDescription`: `string | null` 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.
  - `comments`*:*`array`*(Deprecated)*
- `technicalData`: `object` Technical data
  - `ip`: `string | null` IP of the device from which the verification was made

### Address Validation

Address Validation is used to **validate the address extracted from the end-user’s document**. It has the following components:

- Address Validation and
- Required Country.

Address ValidationRequired Country

Address Validation can be used to determine if found addresses exist, i.e. perform their validity confirmation.

The address extracted from the document is matched against the info in a third-party provider (e.g., Google maps). Initially extracted data is not changed in any way. If any data is found, it is added to the webhook, to `addressValidationResult` object.

Address Validation function also populates the `addressType` string to indicate whether the address belongs to a residential, business, or PO Box entity.

The Address Validation result is indicated by the `addressValidationResult.status` field.

Levels of confirmation:

- full confirmation = address validated to building-level
- partial confirmation = address validated to street-level
- not confirmed = parts of address data can be found, but not enough to perform validation
- not found = no address data is found

If the provided address is confirmed:

- the `addressValidationResult.status` field shows `CONFIRMED` , and
- validated address data is displayed in `addressValidationResult.components` object.

This means that the address is confirmed down to the building/unit level and is highly likely to exist.

If the provided address is partially confirmed:

- the `addressValidationResult.status` field shows `CONFIRMED_PARTIAL` , and
- validated address data is displayed in `addressValidationResult.components` object.

This means that address data down to street info is valid and exists, but it is missing specific unit/apartment details or building-level confirmation.

If the provided address is not confirmed:

- the `addressValidationResult.status` field shows `NOT_CONFIRMED`
- found address data is displayed in `addressValidationResult.components` object.

This means that the address may exist, but it is not confirmed. And the result provided is the closest match found on the list of addresses identified by the supplier.

If the provided address is not found:

- the `addressValidationResult.status` field shows `NOT_FOUND` , and
- `addressValidationResult.components` object returns `null` .

This means that the provided address could neither be validated or found via third-party provider(s) because it likely does not exist or is severely malformed.

With this feature you can set the session to automatically fail if no valid country is found.

Relevant parameters are `addressValidationResult.components.country` and `countryExists.result` .

`countryExists.result` parameter indicates whether the `components.country` is filled.

#### Create a session and send end-user data

SDKAPI

1. Generate a session using the API keys and the BaseURL of your integration (see the <meta charset="utf-8">[API Documentation and API Reference](https://devdocs.veriff.com/apidocs)[↗] how to find these)
  1. You can use the `proofOfAddress.acceptableTypes` array to define which types of documents the integration accepts (note available by default, needs configuration on Veriff’s side)
2. Capture end-user’s document images with Veriff’s SDKs
  1. Send the end-user through the verification flow to capture the image (using the preferred [Veriff SDK](/v1/docs/sdk-guide))
  2. You need the session URL generated in step 1 to use the SDKs (found in response payload as `verification.url`)
3. Session will be submitted automatically once the end-user takes and submits necessary images of their document
4. Receive the results from Veriff via [decision webhook](/v1/docs/decision-webhook)

**1. Create a session using the POST /sessions call**

**1.1 Include the API URL and mandatory headers**

```plaintext
POST {baseURL}/v1/sessions
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       Content-Type: application/json
```

**1.2 Add the following data (minimum payload)**

- `verification`: `object` Verification object*. You can send an empty object, or:
  - define the acceptable document types** with:
    - `proofOfAddress.acceptableTypes` array, defining them in the `name` string(s)
  - include the following to improve the results:
    - `vendorData`: `string`
    - `endUserId:` `string`
  - include the `person.firstName` and `person.lastName` to do the name match

*Mandatory parameter

**Option not available by default, must be enabled on Veriff’s side

**Request payload sample**

```bash
curl -X POST \
  --url '/v1/sessions/' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -d '{
    "verification": {
        "person": {
            "firstName": "John",
            "lastName": "Smith"
        },
        "proofOfAddress": {
            "acceptableTypes": [
                {"name": "UTILITY_BILL"},
                {"name": "TAX_DOCUMENT"},
                {"name": "PHONE_BILL"}
            ]
        },
        "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4"
    }
}'
```

*→ See the <meta charset="utf-8">[POST /sessions](https://veriff-dev-documentation.document360.io/apidocs/v1sessions)[↗] endpoint documentation for further details about how to start a session*

**2. Make a POST /sessions/{sessionId}/media request**

Send only **one image per verification session**. Make sure that the value of `image.context` parameter of the image is `document-front`.

**2.1 Include the API URL and mandatory headers**

```plaintext
POST {baseURL}/v1/sessions/{sessionId}/media
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       X-HMAC-SIGNATURE: string (required) = sessionId signed with the shared secret key
       Content-Type: application/json
```

**2.2 Add the following data into the minimum payload**

- `image`: `object`*
  - `context`: `string`* In this case, it must be `document-front`
  - `content`: `string`* Base64 encoded image (.jpg, .jpeg, .png, .heif, .heic, .webp and .pdf formats are supported)

*Required parameter

**Request payload sample**

```bash
curl -X POST \
  --url '/v1/sessions/aea9ba6d-1b47-47fc-a4fc-f72b6d3584a7/media' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -H 'X-HMAC-SIGNATURE: 034c6da2bb31fd9e6892516c6d7b90ebe10f79b47cfb3d155d77b4d9b66e1d53' \
  -d '{
    "image": {
        "context": "document-front",
        "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII="
    }
}'
```

*→ See the <meta charset="utf-8">[POST /sessions/{sessionId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsidmedia-3)[↗] endpoint documentation for further details about how to send media files*

**3. Update the session status to `submitted` using the PATCH /sessions/{sessionId} call**

**3.1 Include the API URL and mandatory headers**

```plaintext
PATCH {baseURL}/v1/sessions/{sessionId}
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       X-HMAC-SIGNATURE: string (required) = sessionId signed with the shared secret key
       Content-Type: application/json
```

**3.2 Add the following data (minimum payload)**

- `verification`: `object`*
  - `status`: `string`* Status of the verification session you are patching the session into, always `submitted`

*Required parameter

**Request payload sample**

```bash
curl -X PATCH \
  --url '/v1/sessions/fd5c1563-1d23-4b1a-ae46-7ba429927ed8' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -H 'X-HMAC-SIGNATURE: dd994f70b1150ae012f9c1d6d20adf7ed69780044835d39de20b00ffae0660a0' \
  -d '{
    "verification": {
      "status": "submitted"
    }
}'
```

Once done, an [event webhook](/v1/docs/event-webhook) with `submitted` status will be sent.

1. Wait for the session to be approved and decision webhook to send response (see the [webhook payload](/v1/docs/proof-of-address-extraction#webhook-payload) subsection below)
2. Now you can use the following API calls to query the document info:

- <meta charset="utf-8">[GET /sessions/{sessionId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsidmedia-2)[↗] to get a list of media objects and address media with the `sessionId`
- <meta charset="utf-8">[GET /attempts/{attemptId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1attemptsidmedia-1)[↗] to get a list of media objects and address media with the attempt ID
- <meta charset="utf-8">[GET /media/{mediaId}](https://veriff-dev-documentation.document360.io/apidocs/v1mediaid-1)[↗] to get a media file with the `mediaId`

#### Find session and/or decision related data

You can get the data from three sources:

- Receive the decision webhook
- Poll results via GET sessions/{sessionId}/decision
- View the session in Veriff Customer Portal (see [below](/v1/docs/proof-of-address-verification#veriff-customer-portal) for more info)

*****Click to open decision webhook example*****

**Sample response**

> [!NOTE]
> Below are an example and explanation of the **Address Validation related payload** using placeholder data. Depending on your solution, the payload may contain additional parameters. To find more info about it, see the [decision webhook](/v1/docs/decision-webhook#request-properties-explained) documentation.

**Address Validation enabled, address CONFIRMED**

```json
{
    "verification": {
        "additionalVerifiedData": {
            "proofOfAddress": {
                "documentType": "ELECTRICITY_BILL",
                "nameMatch": null,
                "nameMatchPercentage": null,
                "addressValidationResult": {
                    "status": "CONFIRMED",
                    "components": {
                        "plausibleFullAddress": "23 Willowbrook Lane, Ashford, Kent CT19 8NP, UK",
                        "city": "Ashford",
                        "unit": null,
                        "state": null,
                        "street": "Willowbrook Lane",
                        "country": "UK",
                        "postcode": "CT19 8NP",
                        "houseNumber": "23"
                    },
                    "addressType": "residential",
                    "validations": {
                        "countryExists": {
                        "result": "skipped"
                        }
                    }
                }
            }
        }
    }
}
```

**Address Validation enabled****,****address NOT_FOUND**

```json
{
    "verification": {
        "additionalVerifiedData": {
            "proofOfAddress": {
                "documentType": "ELECTRICITY_BILL",
                "nameMatch": null,
                "nameMatchPercentage": null,
                "addressValidationResult": {
                    "status": "NOT_FOUND",
                    "components": null,
                    "addressType": null,
                    "validations": {
                        "countryExists": {
                        "result": "skipped"
                        }
                    }
                }
            }
        }
    }
}
```

**Request properties explained**

- `verification`: `object` Root container for verification session data
  - `additionalVerifiedData`: `object` Data that has been optionally verified for the session
  - `proofOfAddress`: `object` Proof of address data
    - `documentType`: `string | null` Indicates the type of the document. `null` if the check could not be completed.
    - `nameMatch`: `boolean | null` Indicates if the name on the document matches the name from the initial request data. `null` if the check could not be completed.
    - `nameMatchPercentage`: `float | null` Indicates the level of similarity the matched names have, in the range of 0.00-100.00. `null` if the check could not be completed.
    - `addressValidationResult`: `object` Contains data that has been found about the extracted address
      - `status`: `string` Shows the level of address validity confirmation. One of `CONFIRMED`, `CONFIRMED_PARTIAL`, `NOT_CONFIRMED`, `NOT_FOUND`.
      - `components`: `object` Contains address components. Displays `null` if address data was `NOT_FOUND`.
        - `plausibleFullAddress`: `string | null` Full address as a string, containing extracted and found data
        - `city`: `string | null` Any human settlement, including cities, towns, villages, hamlets, localities, etc.
        - `unit`: `string | null` An apartment, unit, office, lot, or other secondary unit designator
        - `state`: `string | null` A first-level administrative division
        - `street`: `string | null` Street name
        - `country`: `string | null` Sovereign nations and their dependent territories (ISO 3166)
        - `postcode`: `string | null` Postal codes used for mail sorting
        - `houseNumber`: `string | null` External (street-facing) building number
      - `addressType`: `string | null` Indicates if the address is of a residential or business premise, or it is a PO box. One of `residential` , `business` , `poBox`. `null` if the address validation feature was has not been enabled, or if no data was sent.
      - `validations`: `object` Contains country validation result data
        - `countryExists`: `object` Indicates if the validation was able to verify the country
          - `result`: `string | null` Indicates the result of country validation, or if it was skipped. One of `success`, `failure`, `skipped`

*****Click to open API GET sessions/sessionId/decision endpoint example*****

**Sample response**

> [!NOTE]
> Below are an example and explanation of the **Address Validation related payload** using placeholder data. Depending on your solution, the payload may contain additional parameters. To find more info about it, see the <meta charset="utf-8">[GET sessions/{sessionId}/decision](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsiddecision-1)[↗] documentation.

**Address Validation enabled, address CONFIRMED**

```json
{
    "verification": {
        "additionalVerifiedData": {
            "proofOfAddress": {
                "documentType": "ELECTRICITY_BILL",
                "nameMatch": null,
                "nameMatchPercentage": null,
                "addressValidationResult": {
                    "status": "CONFIRMED",
                    "components": {
                        "plausibleFullAddress": "23 Willowbrook Lane, Ashford, Kent CT19 8NP, UK",
                        "city": "Ashford",
                        "unit": null,
                        "state": null,
                        "street": "Willowbrook Lane",
                        "country": "UK",
                        "postcode": "CT19 8NP",
                        "houseNumber": "23"
                    },
                    "addressType": "residential",
                    "validations": {
                        "countryExists": {
                        "result": "skipped"
                        }
                    }
                }
            }
        }
    }
}
```

**Address Validation enabled****, address NOT_FOUND**

```json
{
    "verification": {
        "additionalVerifiedData": {
            "proofOfAddress": {
                "documentType": "ELECTRICITY_BILL",
                "nameMatch": null,
                "nameMatchPercentage": null,
                "addressValidationResult": {
                    "status": "NOT_FOUND",
                    "components": null,
                    "addressType": null,
                    "validations": {
                        "countryExists": {
                        "result": "skipped"
                        }
                    }
                }
            }
        }
    }
}
```

**Request properties explained**

- `verification`: `object` Root container for verification session data
  - `additionalVerifiedData`: `object` Data that has been optionally verified for the session
  - `proofOfAddress`: `object` Proof of address data
    - `documentType`: `string | null` Indicates the type of the document. `null` if the check could not be completed.
    - `nameMatch`: `boolean | null` Indicates if the name on the document matches the name from the initial request data. `null` if the check could not be completed.
    - `nameMatchPercentage`: `float | null` Indicates the level of similarity the matched names have, in the range of 0.00-100.00. `null` if the check could not be completed.
    - `addressValidationResult`: `object` Contains data that has been found about the extracted address
      - `status`: `string` Shows the level of address validity confirmation. One of `CONFIRMED`, `CONFIRMED_PARTIAL`, `NOT_CONFIRMED`, `NOT_FOUND`.
      - `components`: `object` Contains address components. Displays `null` if address data was `NOT_FOUND`.
        - `plausibleFullAddress`: `string | null` Full address as a string, containing extracted and found data
        - `city`: `string | null` Any human settlement, including cities, towns, villages, hamlets, localities, etc.
        - `unit`: `string | null` An apartment, unit, office, lot, or other secondary unit designator
        - `state`: `string | null` A first-level administrative division
        - `street`: `string | null` Street name
        - `country`: `string | null` Sovereign nations and their dependent territories (ISO 3166)
        - `postcode`: `string | null` Postal codes used for mail sorting
        - `houseNumber`: `string | null` External (street-facing) building number
      - `addressType`: `string | null` Indicates if the address is of a residential or business premise, or it is a PO box. One of `residential` , `business` , `poBox`. `null` if the address validation feature was has not been enabled, or if no data was sent.
      - `validations`: `object` Contains country validation result data
        - `countryExists`: `object` Indicates if the validation was able to verify the country
          - `result`: `string | null` Indicates the result of country validation, or if it was skipped. One of `success`, `failure`, `skipped`

### Address Matching

Address Matching is used to compare addresses from two different sources (end-user documents and customer-provided initial data) to verify they belong to the same location. The solution enables automated address verification for compliance and fraud prevention, reduces manual review overhead, improves KYC accuracy by cross-referencing address data from multiple sources, helps detect address discrepancies during onboarding flows.

Address Matching cannot performed for you sessions if you are located in restricted countries: China, Vietnam, Crimea, Cuba, Donetsk People's Republic, Iran, Luhansk People's Republic, North Korea, Syria.

> [!NOTE]
> Ensure that at minimum the following parts of the address are identified and present on the document used for verification and in the initData:
> 
> - street name
> - postal code
> - city
> - country
> 
> If all of these are not present or identifiable, the solution does not work.

#### Create a session and send end-user data

SDKAPI

1. Generate a session using the API keys and the BaseURL of your integration (see the <meta charset="utf-8">[API Documentation and API Reference](https://devdocs.veriff.com/apidocs)[↗] how to find these)
  1. You must provide address data in session initData in `verification.address` field
2. Capture end-user’s document images with Veriff’s SDKs
  1. End-user’s document must include extractable address information
  2. Send the end-user through the verification flow to capture the image (using the preferred [Veriff SDK](/v1/docs/sdk-guide))
  3. You need the session URL generated in step 1 to use the SDKs (found in response payload as `verification.url`)
3. Session will be submitted automatically once the end-user takes and submits necessary images of their document
4. Receive the results from Veriff via [decision webhook](/v1/docs/decision-webhook)

**1. Create a session using the POST /sessions call**

**1.1 Include the API URL and mandatory headers**

```plaintext
POST {baseURL}/v1/sessions
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       Content-Type: application/json
```

**1.2 Add the following data (minimum payload)**

- `verification`: `object` Verification object*. You can send an empty object, or:
  - include the address data in `verification.address`
  - define the document info with `document.type` and `document.country`
  - include the following to improve the results:
    - `vendorData`: `string`
    - `endUserId:` `string`
  - include the `person.firstName` and `person.lastName` to do the name match

*Mandatory parameter

**Request payload sample**

```bash
curl -X POST \
  --url '/v1/sessions/' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -d '{
    "verification": {
        "person": {
            "firstName": "John",
            "lastName": "Smith"
        },
        "address": {
            "fullAddress": "123 Main Street, New York, NY 10001, USA"
        },
        "document": {
            "type": "PROOF_OF_ADDRESS",
            "country": "US"
        },
        "endUserId": "a1b2c35d-e8f7-6d5e-3cd2-a1b2c35db3d4"
    }
}'
```

*→ See the <meta charset="utf-8">[POST /sessions](https://veriff-dev-documentation.document360.io/apidocs/v1sessions)[↗] endpoint documentation for further details about how to start a session*

**2. Make a POST /sessions/{sessionId}/media request**

Send only **one image per verification session**. Make sure that the value of `image.context` parameter of the image is `document`.

**2.1 Include the API URL and mandatory headers**

```plaintext
POST {baseURL}/v1/sessions/{sessionId}/media
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       X-HMAC-SIGNATURE: string (required) = sessionId signed with the shared secret key
       Content-Type: application/json
```

**2.2 Add the following data into the minimum payload**

- `image`: `object`*
  - `context`: `string`* In this case, it must be `document`
  - `content`: `string`* Base64 encoded image (.jpg, .jpeg, .png, .heif, .heic, .webp and .pdf formats are supported)

*Required parameter

**Request payload sample**

```bash
curl -X POST \
  --url '/v1/sessions/aea9ba6d-1b47-47fc-a4fc-f72b6d3584a7/media' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -H 'X-HMAC-SIGNATURE: 034c6da2bb31fd9e6892516c6d7b90ebe10f79b47cfb3d155d77b4d9b66e1d53' \
  -d '{
    "image": {
        "context": "document",
        "content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII="
    }
}'
```

*→ See the <meta charset="utf-8">[POST /sessions/{sessionId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsidmedia-3)[↗] endpoint documentation for further details about how to send media files*

**3. Update the session status to `submitted` using the PATCH /sessions/{sessionId} call**

**3.1 Include the API URL and mandatory headers**

```plaintext
PATCH {baseURL}/v1/sessions/{sessionId}
Type: object
Headers:
       X-AUTH-CLIENT: string (required) = API key
       X-HMAC-SIGNATURE: string (required) = sessionId signed with the shared secret key
       Content-Type: application/json
```

**3.2 Add the following data (minimum payload)**

- `verification`: `object`*
  - `status`: `string`* Status of the verification session you are patching the session into, always `submitted`

*Required parameter

**Request payload sample**

```bash
curl -X PATCH \
  --url '/v1/sessions/fd5c1563-1d23-4b1a-ae46-7ba429927ed8' \
  -H 'Content-Type: application/json' \
  -H 'X-AUTH-CLIENT: API-KEY' \
  -H 'X-HMAC-SIGNATURE: dd994f70b1150ae012f9c1d6d20adf7ed69780044835d39de20b00ffae0660a0' \
  -d '{
    "verification": {
      "status": "submitted"
    }
}'
```

Once done, an [event webhook](/v1/docs/event-webhook) with `submitted` status will be sent.

1. Wait for the session to be approved and decision webhook to send response (see the [webhook payload](/v1/docs/proof-of-address-extraction#webhook-payload) subsection below)
2. Now you can use the following API calls to query the document info:

- <meta charset="utf-8">[GET /sessions/{sessionId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsidmedia-2)[↗] to get a list of media objects and address media with the `sessionId`
- <meta charset="utf-8">[GET /attempts/{attemptId}/media](https://veriff-dev-documentation.document360.io/apidocs/v1attemptsidmedia-1)[↗] to get a list of media objects and address media with the attempt ID
- <meta charset="utf-8">[GET /media/{mediaId}](https://veriff-dev-documentation.document360.io/apidocs/v1mediaid-1)[↗] to get a media file with the `mediaId`

#### Find session and/or decision related data

You can get the data from three sources:

- Receive the decision webhook
- Poll results via GET sessions/{sessionId}/decision
- View the session in Veriff Customer Portal (see [below](/v1/docs/proof-of-address-verification#veriff-customer-portal) for more info)

*****Click to open decision webhook example*****

**Sample response**

> [!NOTE]
> Below are an example and explanation of the **Address Matching related payload**. Depending on your solution, the payload may contain additional parameters. To find more info about it, see the [decision webhook](/v1/docs/decision-webhook#request-properties-explained) documentation.

```json
{
    "verification": {
        "additionalVerifiedData": {
            "proofOfAddress": {
                "documentType": "UTILITY_BILL",
                "fullName": "John Smith",
                "fullAddress": "123 Main Street, New York, NY 10001, USA",
                "issueDate": "2025-09-01",
                "nameMatch": null,
                "nameMatchPercentage": null
            },
            "addressMatching": {
                "addresses": [
                {
                    "fullAddress": "123 Main Street, New York, NY 10001, USA",
                    "parsedAddress": {
                    "city": "New York",
                    "unit": null,
                    "state": "NY", 
                    "street": "Main Street",
                    "country": "USA",
                    "postcode": "10001",
                    "houseNumber": "123"
                    }
                },
                {
                    "fullAddress": "123 Main St, New York, New York 10001, United States",
                    "parsedAddress": {
                    "city": "New York",
                    "unit": null,
                    "state": "New York",
                    "street": "Main St", 
                    "country": "United States",
                    "postcode": "10001",
                    "houseNumber": "123"
                    }
                }
                ],
                "result": true,
                "matchThreshold": 80,
                "matchPercentage": 90
            }
        }
    }
}
```

**Request properties explained**

- `verification`: `object` Root container for verification session data
  - `additionalVerifiedData`: `object` Data that has been optionally verified for the session
    - `proofOfAddress`: `object` Proof of address data
      - `documentType`: `string | null` Indicates the type of the document. `null` if the check could not be completed.
      - `fullName`: `string` Person’s name as a single string
      - `fullAddress`: `string` Full address as a single string
      - `issueDate`: `string` Document issue date, in `YYYY-MM-DD` format
      - `nameMatch`: `boolean | null` Indicates if the name on the document matches the name from the initial request data. `null` if the check could not be completed.
      - `nameMatchPercentage`: `float | null` Indicates the level of similarity the matched names have, in the range of 0.00-100.00. `null` if the check could not be completed.
    - `addressMatching`: `object` Contains all address matching validation results
      - `addresses`: `array` Array of exactly 2 address objects - first from initData, second from the end-user’s document
        - `fullAddress`: `string` Original full address string as provided/extracted
        - `parsedAddress`: `object` Google Maps API parsed address components
          - `city`: `string | null` Parsed city name
          - `unit`: `string | null` Parsed apartment/unit number
          - `state`: `string | null` Parsed state/province
          - `street`: `string | null` Parsed street name (premise)
          - `country`: `string | null` Parsed country name
          - `postcode`: `string | null` Parsed postal/ZIP code
          - `houseNumber`: `string | null `Parsed house/building number
      - `result`: `boolean` Indicates whether addresses match based on threshold
      - `matchThreshold`: `integer` Configured matching percentage threshold
      - `matchPercentage`: `integer` Indicates matching percentage

*****Click to open API GET sessions/sessionId/decision endpoint example*****

**Sample response**

> [!NOTE]
> Below are an example and explanation of the **Address Matching related payload**. Depending on your solution, the payload may contain additional parameters. To find more info about it, see the <meta charset="utf-8">[GET sessions/{sessionId}/decision](https://veriff-dev-documentation.document360.io/apidocs/v1sessionsiddecision-1)[↗] documentation.

```json
{
    "verification": {
        "additionalVerifiedData": {
            "proofOfAddress": {
                "documentType": "UTILITY_BILL",
                "fullName": "John Smith",
                "fullAddress": "123 Main Street, New York, NY 10001, USA",
                "issueDate": "2025-09-01",
                "nameMatch": null,
                "nameMatchPercentage": null
            },
            "addressMatching": {
                "addresses": [
                {
                    "fullAddress": "123 Main Street, New York, NY 10001, USA",
                    "parsedAddress": {
                    "city": "New York",
                    "unit": null,
                    "state": "NY", 
                    "street": "Main Street",
                    "country": "USA",
                    "postcode": "10001",
                    "houseNumber": "123"
                    }
                },
                {
                    "fullAddress": "123 Main St, New York, New York 10001, United States",
                    "parsedAddress": {
                    "city": "New York",
                    "unit": null,
                    "state": "New York",
                    "street": "Main St", 
                    "country": "United States",
                    "postcode": "10001",
                    "houseNumber": "123"
                    }
                }
                ],
                "result": true,
                "matchThreshold": 80,
                "matchPercentage": 90
            }
        }
    }
}
```

**Request properties explained**

- `verification`: `object` Root container for verification session data
  - `additionalVerifiedData`: `object` Data that has been optionally verified for the session
    - `proofOfAddress`: `object` Proof of address data
      - `documentType`: `string | null` Indicates the type of the document. `null` if the check could not be completed.
      - `fullName`: `string` Person’s name as a single string
      - `fullAddress`: `string` Full address as a single string
      - `issueDate`: `string` Document issue date, in `YYYY-MM-DD` format
      - `nameMatch`: `boolean | null` Indicates if the name on the document matches the name from the initial request data. `null` if the check could not be completed.
      - `nameMatchPercentage`: `float | null` Indicates the level of similarity the matched names have, in the range of 0.00-100.00. `null` if the check could not be completed.
    - `addressMatching`: `object` Contains all address matching validation results
      - `addresses`: `array` Array of exactly 2 address objects - first from initData, second from the end-user’s document
        - `fullAddress`: `string` Original full address string as provided/extracted
        - `parsedAddress`: `object` Google Maps API parsed address components
          - `city`: `string | null` Parsed city name
          - `unit`: `string | null` Parsed apartment/unit number
          - `state`: `string | null` Parsed state/province
          - `street`: `string | null` Parsed street name (premise)
          - `country`: `string | null` Parsed country name
          - `postcode`: `string | null` Parsed postal/ZIP code
          - `houseNumber`: `string | null `Parsed house/building number
      - `result`: `boolean` Indicates whether addresses match based on threshold
      - `matchThreshold`: `integer` Configured matching percentage threshold
      - `matchPercentage`: `integer` Indicates matching percentage

### Document expiration

> [!CAUTION]
> **Not available by default.**
> 
> Contact your **solutions engineer** for info and configuration.

The feature checks document’s validity based on a set threshold of how many days have passed since issue date.

Default value is 90 days, but it is possible to define custom issue date thresholds for different document types within a single integration. This allows for granular validation logic tailored to the document's type. For example:

- tax returns: 365 days of validity
- utility bills: 90 days of validity
- bank statements: 30 days of validity

If a document's issue date falls outside its specific window, the session will be `declined`. To configure these periods for your integration, please contact your Solutions Engineer.

If the Document Expiration check has **been enabled for your integration,** the check result is returned in `verification.udocs.validations.documentExpiration.isWithinValidityPeriod` boolean.

`isWithinValidityPeriod`:

- `true` indicates that the document’s issue date is within the set threshold
- `false` indicates that that the document’s issue date is not within the set threshold

If `false` , the session will result in `declined` decision.

```json
{
  "verification": {
    "udocs": {
      "validations": {
        "documentExpiration": {
          "isWithinValidityPeriod": true
        }
      }
    }
  }
}
```

**Parameters explained**

- `verification`: `object` Root container for verification result
  - `udocs`: `object` Container for the validations’ results
    - `validations`: `object` Validations results
      - `documentExpiration`: `object` Returns data about document expiration. Available only if Document Expiration check is enabled for your uDocs integration.
        - `isWithinValidityPeriod`: `boolean` Checks if document’s expiration date clears the range threshold (days before expiration date)

### Note about the Tampering Check

> [!CAUTION]
> **Not available by default.**
> 
> Contact your **solutions engineer** for info and configuration.

This check indicates the document's risk level and gives additional details about the factors that influenced this risk assessment.

If the **Tampering Check aka fraud validation has been enabled for your integration**, you will see the `additionalVerifiedData.proofOfAddress.fraud` object in the payload.

Veriff passes the data unaltered in webhooks and API payloads.

```json
{
    "verification": {
        "additionalVerifiedData": {
            "proofOfAddress": {
                "fraud": {
                    "riskLevel": "HIGH_RISK",
                    "reason": "PDF_PROCESSED_BY_EDITOR",
                    "reasonDescription": "Document was processed using editing software",
                    "indicators": []
                }
            }
        }
    }
}
```

**Parameters explained**

- `verification`: `object` Root container for verification result
  - `additionalVerifiedData` : `object` Data that has been optionally verified for the session
    - `proofOfAddress` : `object` Proof of address data
      - `fraud`: `object` Data about document integrity
        - `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.

> [!WARNING]
> 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.

---

## Find decision and/or session related info in Veriff Customer Portal

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

<meta charset="utf-8">

→ *See*[*Review verification in Veriff Customer Portal*](/v1/docs/how-to-review-verification-in-veriff-customer-portal)*about how to view the session info in the Veriff Customer portal*

---

## Proof of Address Capture

This is a separate solution which is used to just capture end-user’s document. No further analysis is done.

Refer to the [Proof of Address Capture](/v1/docs/proof-of-address-capture) documentation.

---

## Non-document Proof of Address

It is possible to perform Proof of Address verification without sending document data. This, however, is not part of the classic Proof of Address solution. Instead, it can be done by passing the end-user’s name and address data when creating a session with Veriff, and configuring the integration to include a registry check. Veriff passes the data to the database verification service provider, who verifies the name and address data, and returns relevant info.

Currently, the solution is available only for [US Database Verification](/v1/docs/us-database-verification) check.

---

## Status and reason codes

For an `approved` session, see:

- `verification.code` about verification session decision code, one of `9001`, `9102`, `9103`, `9104`, `9121`
- `verification.status` about verification status, one of `approved`, `declined`, `resubmission_requested`, `review`, `expired`, `abandoned`

If the session was `declined` or `resubmission_requested`, 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)](/v1/docs/granular-reason-codes)

#### Most common decline reasons for the Proof of Address solution

| `verification.status` | `verification.reasonCode` | `verification.reason` | What does it mean? |
| --- | --- | --- | --- |
| `declined` | 510 | Presented document type is not supported | The uploaded document type is not on the list of supported document types for the integration. Try altering the list of supported documents. |
| `declined` | 511 | Document expired / issued too long ago | The presented PoA document is older than the set validity threshold. |
| `declined` | 527 | Unable to collect proof of address data | System was unable to collect pieces of document data from the presented document. This can occur when the document itself or its image is of low quality. |
| `declined` | 566 | System processing failure | There was an error when processing the request due to service error, incorrect configuration, etc. Check with your Solutions Engineer or Veriff Customer Support. |
| `declined` | 568 | Invalid input | The full address is missing in either the document, initData, or both. |
| `declined` | 573 | Address on document does not match with address in session initialisation data | Session was declined because the addresses do not match |
| `declined` | 574 | Address provided is missing mandatory fields | Ensure that all the required fields are part of the initData |
| `declined` | 580 | Address matching failed due to regional restrictions | You seem to be operating from a restricted country |

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

- [Granular reason codes (table)](/v1/docs/granular-reason-codes)
- [Verification session status codes (table)](/v1/docs/verification-session-status-codes-table)
- [Verification session decision codes (table)](/v1/docs/verification-session-decision-codes-table)

---

## Changelog

| Date | Description |
| --- | --- |
| Apr 22, 2026 | Issue date threshold customization info added to [Document expiration](/v1/docs/proof-of-address-verification#document-expiration) feature |
| Apr 15, 2026 | [Key terminology](/v1/docs/proof-of-address-verification#key-terminology) table added [Document Expiration](/v1/docs/proof-of-address-verification#document-expiration) info added [Tampering Check](/v1/docs/proof-of-address-verification#note-about-the-tampering-check) section expanded with parameters’ explanation |
| Mar 30, 2026 | - [Address Validation](/v1/docs/proof-of-address-verification#address-validation) description and payload examples/explanations updated - Minimum required input data info added to [Address Matching](/v1/docs/proof-of-address-verification#address-matching) |
| Feb 20, 2026 | “Note about fraud check” renamed to “Note about Tampering Check” |
| Feb 19, 2026 | Intro text in [Address Matching](/v1/docs/proof-of-address-verification#address-matching) and [Address Validation](/v1/docs/proof-of-address-verification#address-validation) updated |
| Dec 12, 2025 | Broken links fixed |
| Nov 12, 2025 | Address Matching session generation payload example fixed |
| Nov 7, 2025 | - [Address Validation](/v1/docs/proof-of-address-verification#address-validation) section added - [Address Matching](/v1/docs/proof-of-address-verification#address-matching) section added - Organization of the article slightly changed |
| Jul 22, 2025 | Updated the [Define acceptable document types](/v1/docs/proof-of-address-verification#define-acceptable-document-types) section with a note that this solution is not available by default. Also added an example of session creation payload to the section. |
| Jul 18, 2025 | `decisionTime` updated in webhook section, to indicate that it can also be `null` |
| Jun 6, 2025 | Heading “Article versioning” changed to “Changelog” |
| May 28, 2025 | Corrected the format of acceptable document types array of objects in **Flow** **overview** > **API** > **1.2 Add the following data (minimum payload)** example |
| May 19, 2025 | Article updated with info about the Proof of Address fraud check |
| May 2, 2025 | Documentation published |

Veriff customer back-office, a dashboard where you can see your end-users' verification data.

Depending on your setup, you may be required to access the environment via station.veriff.com or hub.veriff.com. Always **check your sign-up email** and make sure that you **log in via correct address**.

A UUID-format unique identifier ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}) created by you for your end-user to link an end-user to their session(s). Cannot be resolved outside your environment.

Veriff stores it only for identity verification and returns it unchanged in webhooks/API responses or as `null` if not provided.

Strongly recommended if you already use UUID identifiers. Works as an alternative to `vendorData` in Biometric Authentication solution.

A custom unique identifier (max 1,000 characters) created by you, containing only non-semantic data that can't be resolved outside your systems.

Veriff returns it unchanged in webhooks/API responses or as `null` if not provided.

It's referred to as "unique identifier" in Customer Portal and cannot be changed once set.

Required for Fraud solutions (Cross Links check and Velocity Abuse check) and serves as an alternative to `endUserId` in Biometric Authentication when using non-UUID identifiers.

A **unique identifier of an integration.**

A **required parameter for authentication: i**t is used to create the `X-AUTH-CLIENT header` value for **API requests**.

Occasionally, referred to as the "API public key" or "Publishable key".

You can find it in**Veriff Customer Portal**> **API keys** page (you need to be logged in).

A "base address" for the specific API that you are using. **Used to create the API URL** value for API requests.

You can find it in**Veriff Customer Portal**> **All** **Integrations >***Integration name***> API keys** tab (you need to be logged in).

An environment created according to customer's needs to carry out, manage and observe verifications.

You can find the list of your integrations in **Veriff Customer Portal**> **All** **Integrations**page (you need to be logged in).

This where the end-user is directed to go through the verification flow, and it is **unique for each verification session**.

It is a combination of the `base URL` and the `sessionToken`, created as soon as a verification session is created. You can find its value in the response payload of your POST /sessions call, as `verification.url`.

The data that you send when you make an API request, or that you receive when you get a response.

An **address** that allows you to access an API and its various features. It consists of a `BaseURL` and an `endpoint`.

Occasionally, also referred to as the "API URL path".

**Mandatory elements**in the **API requests**, containing the metadata.

An **UUID v4** of a specific **attempt**, found in decision webhook as `attemptId` parameter, or in **GET /sessions/{sessionId}/attempts** response as `verification.id` parameter.

An **"attempt" is one step inside a verification session**, e.g., uploading required data and getting a decision. An **"attempt" can be made several times** during a verification session. This means that calling the GET /sessions/{sessionId}/attempts can return several `verification` objects, each one with a unique `id` value.

## Related

- [Integrations](/how-to-create-an-integration.md)
- [Create verification session](/how-to-generate-sessions-manually.md)
- [Decision webhook](/decision-webhook.md)
- [Codes](/codes.md)
- [Proof of Address Capture](/proof-of-address-capture.md)
