Search
⌃K

Webhooks

This guide helps you set up webhooks to receive updates from Passbase

General

Why Do You Need a Webhook?

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.

Integration

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.

1. Webhook Configuration

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.

2. Event Types

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 been approved or declined 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 been approved 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_REVIEWEDevent, VERIFICATION_COMPLETED has fired as well.

Verification Completed

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,
}

Possible statuses

  • pending, this is the default status of a VERIFICATION_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.

Verification Reviewed

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,
}

Possible statuses

  • 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.

Data Point Updated

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.

Watchlist Monitoring

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
}

Clean Boolean

  • false, this is the default value of the WATCHLIST_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.

Identity Authenticated

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,
}

Possible statuses

  • approved, this is the default status of the IDENTITY_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.

3. Security / Encryption

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.

Examples

Example Server

You can find an example where we set up a webhook endpoint using NodeJS on our Github here.
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");
}
};

Serverless with Firebase

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.