Webhooks
This guide helps you set up webhooks to receive updates from Passbase
Once your user successfully completes a Verification, Passbase will verify and process the identity Resource(s) asynchronously, as the processing is happening at a later time and not directly in response to your code’s execution. Passbase will notify your system about changes in regards to status updates of the Verification so your integration can take subsequent steps.
This is where a webhook comes in place. Passbase can notify you once we have finished processing all the Resources. You can set up webhooks in your developer dashboard's webhook section.
You can find more information about Passbase's integration best-practice in the Overview & Integration Guide section. Below is a graph that summarizes and displays which stage of the processing flow the Passbase system will send a webhook to you.
.jpg?alt=media&token=5c9d76d4-bd85-47ec-9aa5-15be4568eabb)
You can either follow the integration guide or watch the video tutorial that shows how to setup a webhook endpoint in NodeJS. Please be aware that some property or function names might have slightly changed with newer versions. Make sure to compare your implementation with the latest code snippets here in the documentation.
To properly receive incoming webhooks, your server should provide an endpoint supporting:
- TLS encryption version 1.2
- POST requests are either raw in text/plain if encrypted or application/json if no encryption is activated
You can use a service like e.g. https://webhook.site/ to test receiving webhooks from your developer dashboard. For local testing, you can use a CLI tool such as
ngrok
to forward the requests to your local development server.Ensure your webhooks return a 200 response code when successfully received.
Any webhooks triggered from your projects that return a non-200 response code risk being automatically disabled. Email notifications will be sent when Passbase suspects a failing webhook.
Our webhook service supports five events, which describe the status of an Identity. Those are:
VERIFICATION_COMPLETED
: The Verification has completed processing and is ready to be reviewed in your developer dashboard.VERIFICATION_REVIEWED
: The Verification has beenapproved
ordeclined
in your developer dashboard.DATAPOINT_UPDATED
: The Verification has one or more data points updated post processing.WATCHLIST_MONITORING
: The Identity returns as not clean from the adverse media and / or watchlist check.IDENTITY_AUTHENTICATED
: The Authentication has successfully beenapproved
through Biometric Authentication.
Make sure you're not relying on the order of the events inside your application due to networking latency. It is possible that events can arrive at the same time. Though you can assume that once you receive the
VERIFICATION_REVIEWED
event, VERIFICATION_COMPLETED
has fired as well.The
VERIFICATION_COMPLETED
event is triggered when a Verification has completed processing and awaits to be reviewed (accepted or declined) either manually or automatically through our Automated Thresholds feature. The value of the status property can either be pending
if the verification lands in manual review, or approved
or, declined
if you have automated thresholds enabled.{
"event": "VERIFICATION_COMPLETED",
"key": "b76e244e-26a3-49ef-9c72-3e599bf0b5f2",
"status": "pending",
"created": 1582628711,
"updated": 1582628999,
"processed": 1582628999,
}
pending
, this is the default status of aVERIFICATION_COMPLETED
event if there are no automated thresholds enabled in your developer dashboard. The Verification is now displayed in your developer dashboard and ready to be reviewed.approved
, this is the status when a Verification passed the auto-review threshold set in your developer dashboard.declined
, this is the status when a Verification failed to pass the auto-review threshold set in your developer dashboard.
If your project has the Watchlist Check feature enabled and automated thresholds set, the
VERIFICATION_COMPLETED
webhook event will display a status of approved
or declined
even if the Verification returns a dirty watchlist check and is a status of pending
within the developer dashboard. Click here to learn more.You can find a further description of the response values below:
Key | Data type | Description |
event | string | The type of event that triggered this webhook. |
key | string | The UUID of the Identity which triggered this webhook. This will help you link back to your user as well as query our backend API for the details of the Identity. |
status | string | Whether the Verification was approved or declined. This is triggered by you accepting/declining the Verification in the dashboard or Passbase automation does it for you. |
created | integer | UNIX timestamp, when the Verification was created |
updated | integer | UNIX timestamp, when the Verification was updated. |
processed | integer | UNIX timestamp, when the Verification was processed by Passbase. |
The
VERIFICATION_REVIEWED
event is triggered when a Verification status has changed. This will happen if the Verification has been approved or declined in your dashboard, or the automation has automatically approved or declined based on a threshold set by you (e.g. >80%). The value of the status property can be approved
, declined
or pending
. The status will only be pending
if a verification was previously approved
then returned a not clean watchlist check.After this event, it is time to use the Passbase API, to retrieve the details of this verification with the identity access
key
. Please take a look at the API section and integration best practices for more information.{
"event": "VERIFICATION_REVIEWED",
"key": "b76e244e-26a3-49ef-9c72-3e599bf0b5f2",
"status": "approved",
"created": 1582628711,
"updated": 1582628999,
"processed": 1582628999,
}
approved
, this is the status when you approve a Verification manually in your developer dashboard or when it passed the auto-review threshold.declined
, this is the status when you decline a Verification manually in your developer dashboard or when it failed to pass the auto-review threshold.pending
, this is the status when a Verification was previously approved or declined but returns a not clean watchlist check results and is therefore rolled back to pending state for manual review.
If your project has the Watchlist Check feature enabled and automated thresholds set, the
VERIFICATION_REVIEWED
webhook event will display a status of approved
or declined
even if the Verification returns a dirty watchlist check and is a status of pending
within the developer dashboard. Click here to learn more.You can find a further description of the response values below:
Key | Data type | Description |
event | string | The type of event that triggered this webhook. |
key | string | The UUID of the Identity which triggered this webhook. This will help you link back to your user as well as query our backend API for the details of the Identity. |
status | string | Whether the Verification was approved or declined. This is triggered by you accepting/declining the Verification in the dashboard or Passbase automation does it for you. |
created | integer | UNIX timestamp, when the Verification was created |
updated | integer | UNIX timestamp, when the Verification was updated. |
processed | integer | UNIX timestamp, when the Verification was processed by Passbase. |
The
DATAPOINT_UPDATED
event is triggered when an Identity's data points have been updated. This will happen if the Verification has already been processed, and one or more data points, including liveness score, facematch score, or id authenticity score, are updated. The webhook payload will include the type
and value
of the updated data points.After this event, it is time to use the Passbase API, to retrieve the details of this Verification with the identity access
key
. Please take a look at the API section and integration best practices for more information.{
"event": "DATAPOINT_UPDATED",
"key": "ce31e763-e0a5-4ce7-9b43-1086541abf30",
"resource_key": "6ff6c2bf-add7-4569-96ff-40ee86f946f1",
"type": "SEX",
"value": "male",
"updated": 1619095419,
"created": 1619095419
}
You can find a further description of the response values below:
Key | Data type | Description |
event | string | The type of event that triggered this webhook. |
key | string | The UUID of the Identity which triggered this webhook. This will help you link back to your user as well as query our backend API for the details of the Identity. |
resource_key | string | The UUID of the Resource which triggered this webhook. |
type | string | The data point that was updated. |
value | string | The new value of the updated data point. |
created | integer | UNIX timestamp, when the Verification was created. |
updated | integer | UNIX timestamp, when the Verification was updated. |
The
WATCHLIST_MONITORING
webhook event is only available within the developer dashboard if the Watchlist Check feature is enabled. Click here to learn more.The
WATCHLIST_MONITORING
event will be triggered when an Identity's AML Profile is returns as not clean from the adverse media and / or watchlist check. The value of the clean property will default tofalse
.After this event, it is time to use the Passbase API, to retrieve the details of this verification with the identity access
key
. Please take a look at the API section and integration best practices for more information.{
"event": "WATCHLIST_MONITORING",
"key": "9b663f6d-a953-48a0-b288-e54ceed82b8b",
"clean": false,
"types": [
"warning",
"sanction",
"adverse-media-general",
"pep",
"adverse-media-narcotics",
"adverse-media",
"pep-class-2",
"adverse-media-violent-crime",
"adverse-media-sexual-crime",
"adverse-media-financial-crime",
"adverse-media-terrorism",
"adverse-media-fraud",
"pep-class-1"
],
"updated": 1618848473,
"created": 1618848473
}
false
, this is the default value of theWATCHLIST_MONITORING
event.
You can find a further description of the response values below:
Key | Data type | Description |
event | string | The type of event that triggered this webhook. |
key | string | The UUID of the Identity which triggered this webhook. This will help you link back to your user as well as query our backend API for the details of the Identity. |
clean | boolean | Whether the Identity is clean or appears on the adverse media and/or watchlist checks. |
types | array | List of watchlist checks returned if Identity appears on the adverse media and/or watchlist checks. |
created | integer | UNIX timestamp, when the AML Profile was created |
updated | integer | UNIX timestamp, when the AML Profile was updated. |
The
IDENTITY_AUTHENTICATED
webhook event is only available within the developer dashboard if the Biometric Authentication feature is enabled. Click here to learn more.The
IDENTITY_AUTHENTICATED
event will be triggered when an Authentication is created indicating an Identity has successfully authenticated through the Biometric Authentication feature. After this event, it is time to use the Passbase API, to retrieve the details of this verification with the identity access
key
. Please take a look at the API section and integration best practices for more information.{
"event": "IDENTITY_AUTHENTICATED",
"key": "a11fc1bf-45e0-4317-babf-f40ce1b71f65",
"status": "approved",
"created": 1589550161,
"updated": 1605210019,
"processed": 1589550260,
}
approved
, this is the default status of theIDENTITY_AUTHENTICATED
event.
You can find a further description of the response values below:
Key | Data type | Description |
event | string | The type of event that triggered this webhook. |
key | string | The UUID of the Identity which triggered this webhook. This will help you link back to your user as well as query our backend API for the details of the Identity. |
status | string | The authentication was approved. This is triggered by end-user successfully completing reauthentication. |
created | integer | UNIX timestamp, when the Root Identity was created |
updated | integer | UNIX timestamp, when the Root Identity was updated by a successful Authentication. |
processed | integer | UNIX timestamp, when the Root Identity was processed by Passbase. |
Webhooks are a crucial node to ensure the functionality of your integration, as such, they can be the target of a malicious user aiming to disrupt the service or impersonate your users. In order to protect your application from these threats, you must include a 32 bytes-long secret in your webhook configuration, which will be used to encrypt the request body.
When you enable Encryption, the Webhook event is sent in a raw file format of text/plain. Below you'll find an example of how to decipher an incoming webhook request. We assume the variable
request_body
is the response you received via the webhook. The cipher initialization vector will be sent over in the first 16 bytes of the response.Javascript
Python
Ruby
PHP
Go
const crypto = require("crypto")
// Your response from the webhook.
const request_body = ""
// In the example here it is already a string. In prod it'll be a raw file format of
// text/plain, hence you gotta do request_body.toString() in the next line
const encrypted_result = Buffer.from(request_body, 'base64')
const iv = encrypted_result.slice(0,16)
const cipher = crypto.createDecipheriv('aes-256-cbc', "YOUR_WEBHOOK_SECRET", iv)
const decrypted_result_bytes = Buffer.concat([cipher.update(encrypted_result.slice(16)), cipher.final()])
const decrypted_result = decrypted_result_bytes.toString()
const json_result = JSON.parse(decrypted_result)
from Crypto.Cipher import AES
import base64
import json
request_body = "" # Your response from the webhook
encrypted_result = base64.b64decode(encrypted_webhook)
iv = encrypted_result[:16]
cipher = AES.new("YOUR_WEBHOOK_SECRET".encode("utf8"), AES.MODE_CBC, iv)
decrypted_result_bytes = cipher.decrypt(encrypted_result[16:])
decrypted_result = bytes.decode(decrypted_result_bytes)
json_result = json.loads(decrypted_result)
require 'openssl'
require 'base64'
require 'json'
request_body = "" # Your response from the webhook
encrypted_result = Base64.decode64(request_body)
cipher = OpenSSL::Cipher::AES256.new(:CBC)
cipher.decrypt
cipher.key = "YOUR_WEBHOOK_SECRET"
cipher.iv = encrypted_result[0..15]
decrypted_result = cipher.update(encrypted_result[16..-1]) + cipher.final
json_result = JSON.parse(decrypted_result)
// OpenSSL is already integrated in PHP
$request_body = ""; // Your response from the webhook
$key = "YOUR_WEBHOOK_SECRET";
$encrypted_result = base64_decode($request_body);
$iv = substr($encrypted_result, 0, 16);
$decrypted_result = openssl_decrypt(substr($encrypted_result, 16), 'AES-256-CBC', $key, $options=OPENSSL_RAW_DATA, $iv);
$json_result = json_decode($decrypted_result, true);
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func main() {
var webhook_response = "" // Your response from the webhook
key := []byte("YOUR_WEBHOOK_SECRET")
decrypted_webhook := decrypt(key, webhook_response)
fmt.Printf(decrypted_webhook)
}
func decrypt(key []byte, cryptoText string) string {
cipherText, err := base64.StdEncoding.DecodeString(cryptoText)
if err != nil {
panic(err)
}
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
if len(cipherText) < aes.BlockSize {
panic("cipherText too short")
}
iv := cipherText[:aes.BlockSize]
cipherText = cipherText[aes.BlockSize:]
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(cipherText, cipherText)
return fmt.Sprintf("%s", cipherText)
}
The example server in the next section also shows a working version how to decrypt webhooks.
But a webhook endpoint is nothing else than a simple
POST
endpoint of a server, like in the example below:app.post("/passbase-webhooks", (req, res) => {
processWebhook(req);
res.status(200).send("Success");
});
const processWebhook = (request) => {
const webhook = webhookHelper.decryptWebhookIfNeeded(request);
console.log(webhook);
switch (webhook.event) {
case "VERIFICATION_COMPLETED":
// Do logic here for VERIFICATION_COMPLETED event
break;
case "VERIFICATION_REVIEWED":
// Do logic here for VERIFICATION_REVIEWED event
break;
default:
console.log("Couldn't process webhook event");
}
};
If you are using Google Firebase as your backend, you can also receive webhooks by using Google Cloud Functions. You can learn how to set up your Firebase project for using Cloud Functions here.
After you have set it up, you can expose cloud function as an express server endpoint. This sample project shows you the easiest way to set this up. To sum up, you need to configure a cloud function to listen to incoming post requests. In the example below, we listen to an endpoint called
widgets/webhooks
:import * as functions from "firebase-functions";
const crypto = require("crypto");
const express = require("express");
const cors = require("cors");
const app = express();
const admin = require("firebase-admin");
admin.initializeApp();
app.use(cors({ origin: true }));
// Receive post request with Express Endpoint
app.post("/webhooks", (req: any, res: any) => {
const incomingWebhook = req.body;
// Do what you want to do with the webhook
console.log(incomingWebhook);
// (Optional) - Decrypt webhook if you set up encryption
decryptWebhookTest(incomingWebhook)
.then((webhook) => {
// Do what you want to do with the webhook
console.log(webhook);
})
.catch((err: any) => console.log(err));
res.sendStatus(200);
});
const decryptWebhookTest = async (webhookResponse: string) => {
// If needed
};
// Expose Express API as a single Cloud Function:
exports.widgets = functions.https.onRequest(app);
And by this, you will get a webhook endpoint that looks like this:
https://us-central1-<your-project-id>.cloudfunctions.net/widgets/webhooks
If you set this as your wehook endpoint under your Passbase Webhook Settings and trigger a function by e.g. finishing a Verification or approving/declining one, it will fire a webhook to the Google Cloud Function and you can see it in the Firebase Logs. Now you can do what you want with it, e.g. ping our API or update your user.
If you are struggling, just use our sample project from Github and adjust your own project code to it. This article from the official Firebase documentation provides additional details.
Last modified 1yr ago