Webhooks

Webhooks keep your system in sync with the status of the bronID verifications. You will receive a webhook every time there is a change in the verification status of your KYC entries. This includes an initial webhook when you submit the KYC. The initial webhook will have the same value as the HTTP response you get from the API. For security reasons, always verify the signature of the webhook to confirm it came from bronID.

Webhooks get triggered when:

  • There is a new KYC submission (through the API or the bronID Portal)
  • There is a change in the status of the verification

The verification status of the webhooks can be:

  • pending - the verification is pending processing
  • verified - the verification was successful
  • rejected - the verification was not successful
  • info - (legal entities only) additional information required for verification
  • locked - too many unsuccessful verification attempts

Look up the understanding results documentation for more details.

Webhook can also be retrieved using the getVerificationStatus API endpoint.

Webhook response parameters

NameTypeDescription
name
stringThe full name of the entity / individual
verificationStatus
stringThe verification status - verified / rejected / pending / info / locked (see details)
verificationUuid
string(deprecated - use trace and submissionId) The UUID of the verification
trace
stringEntities: The UUID of the verification, Individuals: The UUID of the specific verification attempt
submissionId
stringEntities: same as trace, Individuals: The UUID of the verification grouping
parentVerificationTrace
(optional)
stringEntities: not present, Individuals: The verificationUuid of the encapsulating entity - Only exists if verified as part of an entity
parentVerificationUuid
(optional)
stringSAME AS "parentVerificationTrace"
parentUserId
(optional)
stringEntities: not present, Individuals: The userId of the encapsulating entity - Only exists if verified as part of an entity
entityType
stringThe entity type of the verification (Note: customer might change this when using Whitelabel forms)
timestamp
numberTimestamp when the webhook was sent
userId
(optional)
stringThe userId connected to this verification (if supplied)
submissionStatus
stringHelper status - whether the data has been received by bronID - submitted / incomplete / locked
verificationScore
numberEntities: not present, Individuals: Indication of the number of data sources matched
stakeholders
(optional)
arrayAn array of stakeholders connected to this verification
screeningId
(optional)
stringThe identifier of the performed PEPs & Sanctions screening - if configured
idvRiskScore
(optional)
objectThe ID Verification risk of the entity/individual (Undefined / Low / Low to Medium / Medium / Medium to High / High)
stakeholders
(optional)
object arrayThe details of verified stakeholders part of the verification
requestedActions
(only info status)
arrayIndividuals or documents that need to supplied to continue the verification process (see details)
signature
objectUsed to verify the webhook source is bronID

Webhook examples

We will look at some webhooks results to show you their structure and how to handle them.

Pending webhook

The pending webhook means that the KYC verification is pending processing. The status of this verification will change into verified, rejected or info.

Here is the example of the pending webhook:

{ "name": "My Company", "verificationStatus": "pending", "entityType": "privateCompany", "verificationUuid": "63152524-c722-4a44-8931-1c6caad4dbcf", "timestamp": 1585549407, "userId": "yourUniqueUserId", "submissionStatus": "submitted", "stakeholders": [], "idvRiskScore": { "description": "Medium", }, "signature": { "version": "1", "sha256": "bronid_sec_sha256_340cb830d92ecebbc88709d4828c39a33884004bd92fc55523c7e36ba3d07728", "keccak256": "bronid_sec_keccak256_080b5c54352977d8bbdbffe7f9cc90fa08fcaf53e6814b50728fc79e3d9f75d2" } }

Verified webhook

The verified webhook means that the KYC verification has satisfied the bronID verification requirements.

Here is the example of the verified webhook:

{ name: "My Unregulated Trust", verificationStatus: "verified", entityType: "unRegulatedTrust", verificationUuid: "63152524-c722-4a44-8931-1c6caad4dbcf", trace: "63152524-c722-4a44-8931-1c6caad4dbcf", submissionId: "63152524-c722-4a44-8931-1c6caad4dbcf", timestamp: 1585548662, userId: "yourUniqueUserId", submissionStatus: "submitted", idvRiskScore: { description: "Low", }, stakeholders: [ { id: "14c4d03d-b484-468a-bf32-822be11b84fc", submissionId: "37fcaaf6-c409-48f5-950f-9ec987bbf44d", trace: "63152524-c722-4a44-8931-1c6caad4dbcf", verificationUuid: "63152524-c722-4a44-8931-1c6caad4dbcf", name: "First ok Last", role: "beneficiaries", submissionStatus: "submitted", timestamp: 1701656768, verificationScore: 200, verificationStatus: "verified", idvRiskScore: { description: "Low" }, outOfWatchLists: [{ "Country Name": "The country of the watchlist", name: "The name of the watchlist", description: "The description of the watchlist", link: "https://the.link.com" }], inWatchLists: [{ "Country Name": "International", description: "The PEP list is a pro...", link: "https://bronid.com", name: "PEP List", results: [ // the results of the PEP list - https://docs.bronid.com/peps-and-sanctions ] }], }, { id: "017cce93-399d-425a-8fc9-29315979e1da", idvRiskScore: { description: "Undefined" }, name: "My Comp Pty Ltd", role: "trustee", submissionStatus: "submitted", verificationStatus: "pending", } ], signature: { version: "1", sha256: "bronid_sec_sha256_d1a08cf016dcb86c4a4d551220eba5da6ba51e12bbb1c78d7bab01e9cea87885", keccak256: "bronid_sec_keccak256_20d89ffa5870fbb2cc577585e431f626a586857b164d34a902bfd17bc61be75e" } }

Rejected webhook

The rejected webhook means that the KYC verification has not has satisfied the bronID verification requirements.

Here is the example of the rejected webhook:

{ "name": "My Company", "verificationStatus": "rejected", "entityType": "privateCompany", "verificationUuid": "63152524-c722-4a44-8931-1c6caad4dbcf", "timestamp": 1585548940, "userId": "yourUniqueUserId", "submissionStatus": "submitted", "stakeholders": [], "idvRiskScore": { "description": "Medium", }, "signature": { "version": "1", "sha256": "bronid_sec_sha256_d4dab7958f6205adc6e52f3d3a3947c6a7677b7b4aca84780c8770013bec0786", "keccak256": "bronid_sec_keccak256_7dd112ee1255367ff5cc17a3199b162ac9307d781dbbc407264cc95202838242" } }

Info webhook

The info webhook means that you need to provide more details to complete the verification. In this example we will look at a verification that is missing a stakeholder (individual) and a document.

Here is the example of the info webhook:

{ "verificationStatus": "info", "entityType": "privateCompany", "name": "THE ENTITY NAME", /* the verificationUuid which has missing information */ "verificationUuid": "63152524-c722-4a44-8931-1c6caad4dbcf", "trace": "63152524-c722-4a44-8931-1c6caad4dbcf", "timestamp": 1583455152245, "userId": "theSubmittedUserId", "idvRiskScore": { "description": "Medium", }, /* these are the requestedActions */ "requestedActions": [ { "type": "individual", "role": "trustee", /* the missing stakeholder id */ "id": "5ad6b33c-44f1-4b12-9ec9-31fadd41f6c3", "fields": { /* information about the missing stakeholder */ "country": "AUS", "firstName": "Jane", "lastName": "Citizen", "middleName": "" } }, { "type": "document", /* the missing document id */ "id": "a2820913-8be8-4cd9-bacc-29b6cfd2d38c", /* the name of the requested document */ "extractType": "Trust Deed for My Entity" } ] }

You can submit the information for the requestedActions with a follow-up request:

{ "metadata_version": "4", "metadata_serviceUid": "yourServiceUid", "metadata_secretKey": "yourSecretKey", /* this matches the verificationUuid of the info verification */ "verificationUuid": "cd0c518f-7084-49ff-802a-9c517245daf2", /* these are the requestedActions */ "requestedActions": [ { "type": "individual", "role": "trustee", /* this matches the id of the requested stakeholder */ "id": "5ad6b33c-44f1-4b12-9ec9-31fadd41f6c3", "fields": { "country": "AUS", "firstName": "Jane", "lastName": "Citizen", "middleName": "", "gender": "female", "dateOfBirth": "20/10/1982", "unitNumber": "1", "streetNumber": "94", "streetName": "lennox", "streetType": "Street", "suburb": "CASINO", "postcode": "2470", "state": "NSW", "email": "email@domain.com" } }, { "type": "document", /* this matches the id of the requested document */ "id": "a2820913-8be8-4cd9-bacc-29b6cfd2d38c", /* the base64 of the document */ "documentBase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==", } ] }

Locked webhook

The locked webhook means that the KYC verification has not has satisfied the bronID verification requirements.

Here is the example of the locked webhook:

{ "name": "My Company", "verificationStatus": "locked", "entityType": "privateCompany", "verificationUuid": "63152524-c722-4a44-8931-1c6caad4dbcf", "timestamp": 1585548940, "userId": "yourUniqueUserId", "submissionStatus": "submitted", "stakeholders": [], "signature": { "version": "1", "sha256": "bronid_sec_sha256_d4dab7958f6205adc6e52f3d3a3947c6a7677b7b4aca84780c8770013bec0786", "keccak256": "bronid_sec_keccak256_7dd112ee1255367ff5cc17a3199b162ac9307d781dbbc407264cc95202838242" } }

Verify webhook source

You can verify the webhook came from bronID by re-creating the signature on your side. To create the signature, append the pre-shared signing key to the end of the payload and then generate a hash. Your hash should match the webhook signature.

The webhook response includes two signatures - KECCAK256 and SHA3-256.

You can read the signatures from the headers of the webhook response:

  • SHA256 signature is sent in the X-BronID-Signature-SHA header.
  • KECCAK256 signature is sent in the X-BronID-Signature-KECCAK header.
  • The signature version is sent in the X-BronID-Signature-version header.

Here is an example of the headers (headers are not case-sensitive in most libraries):

x-bronid-signature-version 1 x-bronid-signature-keccak bronid_sec_keccak256_dc230818b21d4966e4be610f8b2578aed4509087cc5b8daea26fa0254d1691bb x-bronid-signature-sha bronid_sec_sha256_6741d61a30a8ec787af84a9de7fb2dc40142160edbd7f3d618860fc7912647ab

Note: SHA3-256 gives different results than SHA-256 (part of the SHA2 family).

You can also see an interactive environment which you can fork to test generating the signatures here. (Replit account required)

Verify webhook source from payload (deprecated)

You can verify the webhook came from bronID by re-creating the signature on your side. To create the signature, append the pre-shared signing key to the end of the payload and then generate a hash. Your hash should match the webhook signature.

The response contains two signatures - KECCAK256 and SHA3-256.

Note: SHA3-256 gives different results than SHA-256 (part of the SHA2 family).

Note: Omit the signatures from the response when signing the payload in your code.

Here is an example of a signed response:

{ /* payload start */ "name": "My Company", "verificationStatus": "verified", "verificationUuid": "63152524-c722-4a44-8931-1c6caad4dbcf", "timestamp": 1585548940, "userId": "yourUniqueUserId", "submissionStatus": "submitted", "stakeholders": [], /* payload end */ /* omit the signature to verify source */ "signature": { "version": "1", "sha256": "bronid_sec_sha256_d4dab7958f6205adc6e52f3d3a3947c6a7677b7b4aca84780c8770013bec0786", "keccak256": "bronid_sec_keccak256_7dd112ee1255367ff5cc17a3199b162ac9307d781dbbc407264cc95202838242" } }

Runnable example

// secret signing key const signingKey = "the_secret_signing_key@!"; // sample incoming webhook const incomingWebhook = { /* payload start */ name: "My Company", verificationStatus: "pending", verificationUuid: "5e397c13-3413-477f-b980-58e45cf97d0c", timestamp: 1586151903, userId: "yourUniqueUserId", submissionStatus: "submitted", stakeholders: [ { name: "Dave ok Citizen", role: "directors", id: "c184f980-60a2-4a32-801d-4decb96f7c3a", verificationStatus: "verified", verificationScore: 250, verificationUuid: "b4920dd6-1c81-4a26-b7a5-b15d8ccd07f0", submissionStatus: "submitted", timestamp: 1586151899, inWatchLists: [ { method: "background", name: "International Criminal Police Organization (INTERPOL) Wanted Persons", officialUrl: "https://www.interpol.int/How-we-work/Notices/View-Red-Notices", }, ], outOfWatchLists: [ { method: "background", name: "Canada Office of the Superintendent of Financial Institutions (OSFI)", officialUrl: "http://www.osfi-bsif.gc.ca/Eng/fi-if/amlc-clrpc/atf-fat/Pages/default.aspx", }, ], }, { name: "Jane ok Citizen", role: "shareholders", id: "42de9703-e563-4504-9c26-b5667c604576", verificationStatus: "verified", verificationScore: 250, verificationUuid: "f069cc43-7114-4eb9-9228-c13d1172d28d", submissionStatus: "submitted", timestamp: 1586151899, inWatchLists: [], outOfWatchLists: [ { method: "background", name: "International Criminal Police Organization (INTERPOL) Wanted Persons", officialUrl: "https://www.interpol.int/How-we-work/Notices/View-Red-Notices", }, { method: "background", name: "Canada Office of the Superintendent of Financial Institutions (OSFI)", officialUrl: "http://www.osfi-bsif.gc.ca/Eng/fi-if/amlc-clrpc/atf-fat/Pages/default.aspx", }, ], }, ], /* signature is still present for backward compatibility - leave it in the response */ /* this signature is applied only to the payload, not the entire webhook response */ signature: { version: "1", sha256: "bronid_sec_sha256_e29dea58183041072e68f13966419450932f226527d21e81f174e013fa5e023c", keccak256: "bronid_sec_keccak256_6fbc541cc20e3b32f8ee9e9d01b9f444b46c2761dfaba268dce6901e0f7c06ea", }, /* payload end */ }; // --- USING THE PAYLOAD --- // YOU CAN USE THE RAW TEXT OF THE PAYLOAD IF YOUR LIBRARY SUPPORTS IT // OTHERWISE YOU NEED TO STRINGIFY THE JSON PAYLOAD const stringifiedPayload = JSON.stringify(incomingWebhook); // append the signing key const unsignedString = `${stringifiedPayload}${signingKey}`; // generate signature const generatedSha3_256 = createHash('sha3-256').update(unsignedString).digest('hex'); // expected sha3_256 signature: 21d5cb103c29ab23514caad00f286818754160afda203226e8a9165b1c3c92d4 // prefix with "bronid_sec_sha256_" before comparison const comparableSignature = `bronid_sec_sha256_${generatedSha3_256}`; // read webhook signature from 'X-BronID-Signature-SHA' header const sha256Signature = "bronid_sec_sha256_21d5cb103c29ab23514caad00f286818754160afda203226e8a9165b1c3c92d4"; // read webhook signature version from 'X-BronID-Signature-version' header const signatureVersion = "1"; // current version const isVerifiedSource = sha256Signature === comparableSignature; console.log(isVerifiedSource ? "source is bronID!" : "unauthorised source!"); // Click “▶ run” to try this code live and generate a webhook signature.