This is a legacy solution. If you are interested in Veriff’s Proof of Address solution, please refer to Proof of Address Verification documentation
Veriff’s Proof of Address Extraction (PoA Extraction) feature captures the submitted document and extracts the firstName, fullAddress , documentType and document.validFrom data from it.
It is available via API, web flow, and native SDKs.
Contact your solutions engineer for info and configuration.
It is possible to get the additional name match check enabled for your integration. See the Optional Proof of Address name match check section below for more info.
Prerequisites
You have an integration set up with Veriff
Your Solutions Engineer has enabled the PoA Extraction for the integration
You have set up the decision webhook
If using the API, you are ready to send Veriff images of the end-user’s proof of address document
Flow overview
The flow is a bit different, depending on the method you are using to verify your end-users with Veriff.
Use via SDKs
Generate a verification session using the authentication integration tokens (check the POST /sessions[↗] endpoint in the API reference)
Capture end-user’s PoA document images with Veriff’s SDKs
Send the end-user through the verification flow to capture the image (using the preferred Veriff SDK)
You need the session URL generated in step 1 to use the SDKs (found in response payload as
verification.url)
Session will be submitted automatically once the end-user takes and submits necessary images of their face
Receive the results from Veriff via decision webhook
Use via API
1. Create a session using the POST /sessions call
1.1 Include the API URL and mandatory headers
POST {baseURL}/v1/sessions
Type: object
Headers:
X-AUTH-CLIENT: string (required) = API key
Content-Type: application/json1.2 Add the following data (minimum payload)
verification:objectVerification object*. You can send an empty object, or include the following to improve the results:vendorData:
stringendUserId:
string
*Mandatory parameter
Request payload sample
curl -X POST \
--url '/v1/sessions/' \
-H 'Content-Type: application/json' \
-H 'X-AUTH-CLIENT: API-PUBLIC-KEY' \
-d '{
"verification": {
"vendorData": "11111111"
}
}'→ See the POST /sessions[↗] endpoint documentation for further details about how to start a session
2. Make a POST /sessions/{sessionId}/media request
You can use this endpoint to send several images, but you need to upload them one at a time.
Also, if you post several image files, make sure that the value of image.context parameter of the image relevant to the PoA Extraction flow is document-front, otherwise the PoA Extraction flow will not work.
2.1 Include the API URL and mandatory headers
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/json2.2 Add the following data into the minimum payload
image:object*context:string* In this case, it must bedocument-frontcontent:string* Base64 encoded image (.jpg, .jpeg, .png, .heif, .heic, .webp and .pdf formats are supported)
*Required parameter
Request payload sample
curl -X POST \
--url '/v1/sessions/aea9ba6d-1b47-47fc-a4fc-f72b6d3584a7/media' \
-H 'Content-Type: application/json' \
-H 'X-AUTH-CLIENT: API-PUBLIC-KEY' \
-H 'X-HMAC-SIGNATURE: 034c6da2bb31fd9e6892516c6d7b90ebe10f79b47cfb3d155d77b4d9b66e1d53' \
-d '{
"image": {
"context": "document-front",
"content": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+.../9fgAEAKcxisFjVfn0AAAAASUVORK5CYII="
}
}'→ See the POST /sessions/{sessionId}/media[↗] endpoint documentation for further details about how to send media files
3. Update the session status to submitted using the PATCH /sessions/{sessionId} call
submitted using the PATCH /sessions/{sessionId} call3.1 Include the API URL and mandatory headers
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/json3.2 Add the following data (minimum payload)
verification:object*status:string* Status of the verification session you are patching the session into, alwayssubmitted
*Required parameter
Request payload sample
curl -X PATCH \
--url '/v1/sessions/fd5c1563-1d23-4b1a-ae46-7ba429927ed8' \
-H 'Content-Type: application/json' \
-H 'X-AUTH-CLIENT: API-PUBLIC-KEY' \
-H 'X-HMAC-SIGNATURE: dd994f70b1150ae012f9c1d6d20adf7ed69780044835d39de20b00ffae0660a0' \
-d '{
"verification": {
"status": "submitted"
}
}'Once done, an event webhook with submitted status will be sent.
Wait for the session to be approved and decision webhook to send response (see the webhook payload subsection below)
Now you can use the following API calls to query the document info:
GET /sessions/{sessionId}/media[↗] to get a list of media objects and address media with the
sessionIdGET /attempts/{attemptId}/media[↗] to get a list of media objects and address media with the attempt ID
GET /media/{mediaId}[↗] to get a media file with the
mediaId
Find the decision and see verified 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
Webhook payload
As soon as the session is approved, the decision webhook will send an approved response. This response will include the session status, as well as all the data that was extracted from the PoA document.
Below is an explanation and a sample of a decision webhook payload for a PoA Extraction session. The decision webhook is used for many purposes, to find more info about it, see the decision webhook documentation.
Sample request
{
"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": "2022-11-25",
"validUntil": null
},
"reasonCode": null,
"vendorData": "11111111",
"endUserId": null,
"decisionTime": "2023-01-23T10:31:05.293000Z",
"acceptanceTime": "2023-01-23T10:25:40.026Z",
"additionalVerifiedData": {
"proofOfAddress": {
"nameMatch": true,
"nameMatcPercentage": 100.00,
"documentType": "UTILITY_BILL"
},
},
}
"technicalData": {
"ip": null
}Request properties explained
*Required field
status:string* Status of the responseverification:object* Verification request decision object.nullif decision is not available yetid:string* UUID v4 which identifies the verification sessionattemptId:string* UUID v4 of the attempt which received a status (as shown inverification.statusfield)vendorData:string | null* The unique identifier that you created for your end-user.nullif not specifiedendUserId:string | null* TheUUIDthat you created for your end-user.nullif not specifiedstatus:string* Verification status, one ofapproved,declined,resubmission_requested,review,expired,abandonedcode:integer* Verification session decision code, one of9001,9102,9103,9104,9121. For more info, see the verification session decision codesreason:string | null* Reason why the verification failedreasonCode:integer | null* Reason code of the failed verification. For more info, see the possible codes for a failed verificationdecisionTime:string | null* Timestamp of the decision, represented asUTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset(ISO 8601)acceptanceTime:string* Timestamp of the session generation, represented asUTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset(ISO 8601)person:object* Data about the verified persongender:string | null* Person’s gender, represented as M or F, ornullif not presentidNumber:string | null* National identification numberlastName:string | null*null, unless prefilled by the customeraddresses:array* Array of person's addressesfullAddress:stringAddress as a single string
firstName:string | null* Person's first name as written on the document, if availabledateOfBirth:string* Person’s date of birth, represented asYYYY-MM-DDnationality:string | null* Person's nationalityyearOfBirth:string | null* Person’s year of birth, represented asYYYYplaceOfBirth:string | null* Person's place of birthpepSanctionMatch:string | null* Legacy field, may return incorrect result, should be ignoredcitizenship:string | null* Deprecated, always returns null
document:object* Verified documenttype:string | nullDocument typenumber:string | nullDocument number,[a-zA-Z0-9]characters onlycountry:string | null* Document issuing country, represented as ISO 3166alpha-2codevalidUntil:string | nullDocument is valid until date, represented asYYYY-MM-DD. Optional, must be configured for your integration by the Solutions EngineervalidFrom:string | nullDocument is valid from date, represented asYYYY-MM-DD. Optional, must be configured for your integration by the Solutions Engineer
additionalVerifiedData:object* Data which has been optionally verified for sessionproofOfAddress:objectProof of address data. Optional, available only if the name match check has been enabled for the integrationnameMatch:booleanIndicates if the name on the proof of address document matches the name from the initial request data.nullif the check could not be completed.nameMatchPercentage:floatIndicates the level of similarity the matched names have, in the range of 0.00-100.00.nullif the check could not be completed.documentType:stringIndicates the type of the proof of address document.nullif the check could not be completed.
comments:array* (Deprecated)
technicalData:object* Technical dataip:string | nullIP of the device from which the verification was made
API call
You can use the GET sessions/{sessionId}/decision[↗] endpoint to get the decision data.
Below is an explanation and a sample of the API call payload for a PoA Extraction session. The endpoint is used for many purposes, to find more info about it, see the GET sessions/{sessionId}/decision[↗] documentation.
Sample response
{
"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": "2022-11-25",
"validUntil": null
},
"reasonCode": null,
"vendorData": "11111111",
"endUserId": null,
"decisionTime": "2023-01-23T10:31:05.293000Z",
"acceptanceTime": "2023-01-23T10:25:40.026Z",
"additionalVerifiedData": {
"proofOfAddress": {
"nameMatch": true,
"nameMatcPercentage": 100.00,
"documentType": "UTILITY_BILL"
},
},
}
"technicalData": {
"ip": null
}Response properties explained
status:stringStatus of the responseverification:objectVerification request decision object.nullif decision is not available yetid:stringUUID v4 which identifies the verification sessionattemptId:stringUUID v4 of the attempt which received a status (as shown inverification.statusfield)vendorData:string | nullThe unique identifier that you created for your end-user.nullif not specifiedendUserId:string | nullTheUUIDthat you created for your end-user.nullif not specifiedstatus:stringVerification status, one ofapproved,declined,resubmission_requested,review,expired,abandonedcode:integerVerification session decision code, one of9001,9102,9103,9104,9121. For more info, see the verification session decision codesreason:string | nullReason why the verification failedreasonCode:integer | nullReason code of the failed verification. For more info, see the possible codes for a failed verificationdecisionTime:stringTimestamp of the decision, represented asUTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset(ISO 8601)acceptanceTime:stringTimestamp of the session generation, represented asUTC YYYY-MM-DDTHH:MM:SS.SSS+Timezone Offset(ISO 8601)person:objectData about the verified persongender:string | nullPerson’s gender, represented as M or F, ornullif not presentidNumber:string | nullNational identification numberlastName:string | nullnull, unless prefilled by the customeraddresses:arrayArray of person's addressesfullAddress:stringAddress as a single string
firstName:string | nullPerson's first name as written on the document, if availabledateOfBirth:stringPerson’s date of birth, represented asYYYY-MM-DDnationality:string | nullPerson's nationalityyearOfBirth:string | nullPerson’s year of birth, represented asYYYYplaceOfBirth:string | nullPerson's place of birthpepSanctionMatch:string | null*Legacy field, may return incorrect result, should be ignoredcitizenship:string | nullDeprecated, always returns null
document:objectVerified documenttype:string | nullDocument typenumber:string | nullDocument number,[a-zA-Z0-9]characters onlycountry:string | nullDocument issuing country, represented as ISO 3166alpha-2codevalidUntil:string | nullDocument is valid until date, represented asYYYY-MM-DD. Optional, must be configured for your integration by the Solutions EngineervalidFrom:string | nullDocument is valid from date, represented asYYYY-MM-DD. Optional, must be configured for your integration by the Solutions Engineer
additionalVerifiedData:objectData which has been optionally verified for sessionproofOfAddress:objectProof of address data. Optional, available only if the name match check has been enabled for the integrationnameMatch:booleanIndicates if the name on the proof of address document matches the name from the initial request data.nullif the check could not be completed.nameMatchPercentage:floatIndicates the level of similarity the matched names have, in the range of 0.00-100.00.nullif the check could not be completed.documentType:stringIndicates the type of the proof of address document.nullif the check could not be completed.
comments:array(Deprecated)
technicalData:objectTechnical dataip:string | nullIP of the device from which the verification was made
Veriff Customer Portal
You can find the verification session related info, including uploaded images, in the Veriff Customer Portal, by opening the session on the All Verifications page.
→ See Review verification in Veriff Customer Portal about how to view the session info in the Veriff Customer portal
Optional Proof of Address name match check
Note that the name match check is not performed by default, it needs to be configured for your integration.
Please ask your Solutions Engineer to configure the feature for your integration.
In order to do the Proof of Address name match check, you can add the optional parameters person.firstName and person.lastName to the POST /sessions request payload.
If the check has been enabled, and you have sent us the first name and last name data, the check will be performed. The results are displayed in decision webhook response, in:
additionalVerifiedData.proofOfAddressobject, more specifically inproofOfAddress.nameMatchandproofOfAddress.nameMatchpercentagefields
If the check has been enabled, but you do not send us the name data, the strings will be null.
Sample POST /sessions request payload
GET {baseURL}/v1/sessions/
Type: object
Headers:
X-AUTH-CLIENT: string (required) = API key
Content-Type: application/jsoncurl -X POST \
--url '/v1/sessions/' \
-H 'Content-Type: application/json' \
-H 'X-AUTH-CLIENT: API-PUBLIC-KEY' \
-d '{
"verification": {
"person": {
"firstName": "John",
"lastName": "Smith",
},
}
}'Webhook payload
Below is an explanation and a sample of the part of a decision webhook payload relevant to the name match check. To see the full decision webhook response related to Proof of Address check, see the Webhook payload section above.
Sample request
{
"status": "success",
"verification": {
...
"additionalVerifiedData": {
"proofOfAddress": {
"nameMatch": true
"nameMatcPercentage": 100.00
},
},
},
...
}Request properties explained
status:string* Status of the responseverification:object* Verification request decision object...
additionalVerifiedData:object* Data which has been optionally verified for sessionproofOfAddress:object* Proof of address datanameMatch:boolean | null* Indicates if the name on the proof of address document matches the name from the initial request data.nullif 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.nullif the check could not be completed.
...
*Required field
Note about PDF support
Legacy PoA Extraction solution supports PDF file uploads.
Contact your solutions engineer for info and configuration.
The file that is uploaded for Proof of Address flow must contain only one PoA document. If you need to send several PoA documents, upload them one-by-one in separate PDF files.
For PoA, documents can be uploaded in following configurations:
Single PDF file, where the document data is on one page
Single PDF file, where the document data spans over several pages
Veriff processes first 5 pages of uploaded PDF file. System removes empty pages from the PDF.
Changelog
Date | Description |
|---|---|
Jul 18, 2025 |
|
Jun 6, 2025 | Heading “Article versioning” changed to “Changelog” |
May 2, 2025 | Documentation marked as legacy solution as new Proof of Address Verification solution is now available. Note bout PDF support added, as the multi-page PDF upload is supported only by the legacy Proof of Address Extraction |
Mar 12, 2025 | Documentation published |