In a nutshell, webhooks are needed to handle responses from Veriff services about:
Events happening in the verification session
Verification session decisions
System’s confidence about the genuineness of a session
Data about different checks and extractions
Session info (e.g., session ID, attempt ID, different timestamps)
In order to use a webhook, you need to create an endpoint, i.e. a webhook URL on your side that accepts payloads posted by Veriff’s services.
Available webhook types
Decision webhook, used by most solutions and products, returns the result of the verification once the verification has been processed and contains info about the session
Event webhook, optional webhook, tracks the events happening in the identity verification process performed by the end-user
Watchlist screening webhook, returns data from the check performed in a AML Screening service verification session
INE webhook, returns data from the check performed in the Mexican Electoral Registry (INE) registry verification session
CURP webhook, returns data from the check performed in the Mexican Population Registry (CURP) registry verification session
INE+CURP webhook, returns data from the check performed in the Mexican Electoral Registry (INE) and Mexican Population Registry (CURP) verification session
User-defined statuses webhook, returns data from when the Customer Portal user defines a custom status for an attempt
Full Auto webhook, available only for Self Serve: Essential Plan integrations which return
insights
,extractions
anddecisionScore
data
Which webhook type I need?
Veriff offers a number of solutions (aka products) to verify end-user’s identity, and uses different webhooks to pass back the verification data.
There is no single webhook that you always need to set up. The list of webhooks you need to configure depends on the product(s) you are using.
You need to configure the decision webhook to receive session decision and verified data from Veriff for:
AML screening via IDV integration
Configuring the decision webhook for other products and solutions is optional, you may do it if you want to receive session info (e.g., session decision, attempt ID, decision timestamp).
For all the solutions, you can choose to configure the optional event webhook to notify you about the progress of the verification flow (events).
Veriff sends the watch-list screening webhook for AML screening
For specific Mexican registry checks Veriff sends:
Veriff sends the user-defined statuses webhook for when user has added a status to an attempt in the Veriff Customer Portal.
Veriff sends the full auto webhook for Self-Serve Essential Plan customers.
Webhook prerequisites
- Make sure you have access to the Veriff Customer Portal
- See the list of Which webhook type I need? and/or Available webhook types sections to understand which webhook(s) you may need
- Set up webhook URL(s) on your side and have them at hand
- Make sure they match the Webhook URL requirements
- Make sure your system is able to handle Webhooks receipt, delivery and resending requirements
- Secure your communication, check the HMAC Authentication and Endpoint Security article
- Make sure your system is able to handle the Backwards compatible changes
6.Proceed to Set up webhooks section below
Webhook delivery, receipt and resending
Order of delivery: to follow the best practices, Veriff does not guarantee that the webhooks are delivered in the order in which they are generated. Therefore, you should not expect to receive them in that order either, and should implement a logic to handle this accordingly.
Delivery approach: we guarantee the delivery of webhook at-least-once. The receiving API should be idempotent.
Confirmation of receipt: After sending the webhook, Veriff’s systems expect a confirmation about receiving the webhook from your side. This confirmation from your server should come within 5,000 ms, and we expect it to be in the form of a successful HTTP response code (a 200 code).
Rule of resending: If the confirmation does not arrive within that timeframe, for example there is a network connectivity issue or technical issue with delivering the notification (any non-200 response code), Veriff will try to resend the failed webhook for up to a week.
Webhook URL requirements
Only HTTPS URLs are allowed
Veriff does not allow adding custom ports to webhook URLs
Set up webhooks
Step 1: Configure webhook URL
Go to the Veriff Customer Portal (you need to have an active account with Veriff)
Navigate to All Integrations on the left navigation bar
Find and open the relevant integration
Navigate to the Settings tab on the integration's page
Fill in the relevant
webhook URL
input field with the URL where your endpoint is accepting payloads from Veriff
Note that the image below does not contain all the possible webhook URLs. The list available depends on your integration.
Step 2: Tie the verification result to the end-user
When your server receives a response from Veriff, you need to be able to reference it to the relevant end-user.
You can do this by using the Veriff session ID or by using your own end-user identifier.
Using the Veriff' session ID
To track this, record the Veriff session ID value during session creation. It can be found in the session response payload as verification.id
Some webhook’s payloads refer to it as either session ID or attempt ID, or both. Please see the specific webhook payload for exact info.
Using your own end-user ID
You need to provide this to Veriff.
You can store the end-user identifier in the vendorData
or endUserId
property during the session creation.
Note: it is technically possible for one end-user to be associated with multiple verification sessions. Therefore, if you are only recognizing end-users by your own identifier, and not Veriff's session ID, this could potentially create ambiguous situations in code.
Step 3: Secure the webhook communication
It is important to check that the webhook responses do indeed originate from Veriff. All the activities are picked up by a webhook listener, which need to be secured.
For that we use the X-HMAC-SIGNATURE header, which value is an HMAC-SHA256 hex encoded keyed hash using your shared secret key.
There are three ways to secure the webhook listener:
Have a secure TLS server for your webhook listener (Veriff will call only HTTPS URLs which are hosted by servers with a publicly verifiable certificate)
Verify the
X-AUTH-CLIENT
andX-HMAC-SIGNATURE
headers on the received webhooks (the signature is calculated using the shared secret key that only you and Veriff know)Allowlist the Veriff IP range for webhook listeners (ask your Solutions Engineer for info)
→ See the HMAC Authentication and Endpoint Security section about how you can create and validate the X-HMAC-SIGNATURE
Step 4: Test webhooks
Do not use sensitive data or expose personally identifiable information (PII) even when testing.
Webhooks testing prerequisites
Active integration with Veriff
Webhook URL is defined in Veriff Customer Portal
Basic understanding of HTTP/HTTPS protocols
(Optional) Development environment for local testing
Webhooks testing flow
We recommend using the decision webhook to test.
Set up a webhook URL to receive Veriff data (see Get webhook URL for testing)
Add the webhook URL to the Webhook decision URL field in Veriff environment (see Configure webhook URL for info)
Start a verification session (see your options in the Create verification session article)
Open the session URL on your device and go through the verification flow
Update session status to
approved
ordeclined
in the Veriff Environment (see Forcing the status and data of the verification session when testing[↗] in the Knowledge Base (requires a login to the Veriff environment))Check your webhook listener for webhook data
Get webhook URL for testing
If you do not have an existing webhook URL to test with, then depending on if you are going to use PII data or not, see the options below:
Use a free service when testing without PII data
Set up a local webhook listener
Testing without PII data
If you are not going to use PII data, use free Webhook.site[↗] service, where you can create a unique URL.
After you have generated the URL, go through steps 2-5 in the flow above. Then, check the page on the Webhook.site to see the data sent via the webhook.
Testing using PII data
If PII data is going to be used then it is recommended that you create a server for your webhook listener. Below you find:
A sample JS script to set up a server to listen for POST requests at /hook and log incoming JSON data
Guide to using ngrok to get a publicly accessible URL, allowing external services to send data to your local server for webhook testing and debugging
Install dependencies
First, make sure you have express and body-parser installed:
npm install express body-parser
Create the server script
Use the following javascript code to set up a simple Express server to receive webhook data.
onst express = require("express")
const bodyParser = require("body-parser")
const app = express()
const PORT = 3000
app.use(bodyParser.json())
app.listen(PORT, () => console.log(`🚀 Server running on port ${PORT}`))
app.use(bodyParser.json())
app.post("/hook", (req, res) => {
console.log(req.body)
res.status(200).end()
})
Run the server
Save this code to a file (e.g., server.js
) and start the server by running:
node server.js
You should see a message in the terminal confirming that the server is running on localhost:3000
: Server running on port 3000
Expose the server to the internet using ngrok
To test webhooks or allow external services to send data to your local server, you need to make localhost:3000
accessible from the internet. Let us use ngrok
.
Install ngrok (if you have not already) by following the instructions on ngrok's website[↗].
In a new terminal window, run the command bash ngrok http 3000 to start a tunnel to
localhost:3000
Ngrok will display output similar to this:
Forwarding https://1234abcd.ngrok.io -> http://localhost:3000
This public URL (https://1234abcd.ngrok.io
) is now a tunnel to your local server
Test webhooks with the ngrok URL
Paste the ngrok URL
(e.g., https://1234abcd.ngrok.io/hook
) to the Webhook decision URL
in Veriff Customer Portal.
Go through the steps 2-5 above in the flow.
When the webhook sends data, it will reach your local /hook
endpoint, and you will see the request data logged in the terminal where your server is running.
Mock payload and shared secret key for local testing
You can use the example signature and sample payload below to test webhooks sending and receipt and not depend on Veriff sending the response. Use the curl
command below.
Mock shared secret key for testing
To validate this example signature and payload, use a shared secret key
abcdef12-abcd-abcd-abcd-abcdef012345
. Otherwise you will see an authentication error that the API key and shared secret key do not match.
Beware the hardspaces: generating the value may vary depending on the programming language used, e.g., some languages include the hard spaces in the body, and some omit them.
curl --request POST 'https://your.url'\
--header 'accept: application/json' \
--header 'x-auth-client: 8e4f7cd8-7a19-4d7d-971f-a076407ee03c' \
--header 'x-hmac-signature: 01fa3ded011bfce75672c99877a6cc1cf7aeaeda0ccb6b43fc21b60f595063c2' \
--header 'content-type: application/json' \
--data '{
"status": "success",
"verification": {
"id": "12df6045-3846-3e45-946a-14fa6136d78b",
"code": 9001,
"person": {
"gender": null,
"idNumber": null,
"lastName": "MORGAN",
"addresses": [
{
"fullAddress": "1234 Snowy Ridge Road, Indiana, 56789 USA",
"parsedAddress": {
"city": null,
"unit": null,
"state": "Indiana",
"street": "1234 Snowy Ridge Road",
"country": "USA",
"postcode": "56789",
"houseNumber": "null"
}
}
],
"firstName": "SARAH",
"citizenship": null,
"dateOfBirth": "1967-03-30",
"nationality": null,
"yearOfBirth": "1967",
"placeOfBirth": "MADRID",
"pepSanctionMatch": null
},
"reason": null,
"status": "approved",
"comments": [],
"document": {
"type": "DRIVERS_LICENSE",
"number": "MORGA753116SM9IJ",
"country": "GB",
"validFrom": null,
"validUntil": "2022-04-20",
"placeOfIssue": "MADRID",
"firstIssue": "2015-03-21",
"issueNumber": "01",
"issuedBy": "ISSUER"
},
"reasonCode": null,
"vendorData": "12345678",
"decisionTime": "2019-11-06T07:18:36.916Z",
"acceptanceTime": "2019-11-06T07:15:27.000Z",
"additionalVerifiedData": {
"driversLicenseCategory": {
"B": true
},
"driversLicenseCategoryFrom": {
"B": "2019-10-06"
},
"driversLicenseCategoryUntil": {
"B": "2025-10-05"
},
"estimatedAge": 32,
"estimatedGender": 0.613
},
"riskLabels": [
{
"label": "document_integration_level_crosslinked_with_fraud",
"category": "document",
"sessionIds": [
"5a2358e7-fd31-4fcb-a23f-4d76651ba68a"
]
},
{
"label": "document_integration_level_crosslinked_with_multiple_declines",
"category": "document",
"sessionIds": [
"fd5c1563-1d23-4b1a-ae46-7ba429927ed8"
]
}
],
"biometricAuthentication": {
"matchedSessionId": "d40edb60-6ae6-4475-be72-84b81669cce6",
"matchedSessionVendorData": "User001"
}
},
"technicalData": {
"ip": "186.153.67.122"
}
}'
Checklist to verify production readiness
Basic setup
Webhook endpoint is properly configured in the Veriff Customer Portal
Endpoint is accessible via HTTPS
Basic logging is implemented and verified
Test webhooks have been successfully received and processed
Your setup is compatible with Veriff’s Backwards compatible changes
Security essentials
Webhook signature validation is implemented
Secrets are stored securely (not in code)
IP allowlist is configured (if needed)
PII data handling requirements are met
Core implementation
Webhook processing is asynchronous
System handles out-of-order webhook delivery correctly
Idempotency checks are implemented (handling at-least-once delivery)
Response time is consistently under 5000ms
Server returns HTTP 200 status code upon successful receipt
System can handle webhook retries for up to one week
Basic error handling is in place
Testing & validation
All webhook types have been tested
Error scenarios have been verified
Payload structure is validated
Success/failure rates are monitored
Monitoring
Basic alerts are set up for failures (see Codes section for overview of possible different error codes)
Webhook delivery is tracked
Error logs are reviewed
Response times are monitored
Article versioning
Date | Description |
---|---|
Mar 31, 2025 | Links to IDV products’ guides updated Mentions of “Full Auto” removed Mentions of “Self-Serve: Essential Plan” updated |
Mar 12, 2025 | Documentation published |