Webhooks

Webhooks deliver real-time, signed notifications when resource states change. Instead of polling, configure a webhook endpoint to receive push notifications.

Webhook delivery is not guaranteed. Clients must implement polling to retrieve final results if webhook delivery fails. We recommend a polling interval of 10 minutes or greater.

Endpoint Requirements

ItemRequirement
ProtocolHTTPS only (TLS 1.2+)
MethodPOST
Content-Typeapplication/json
Timeout60 seconds

Configuration

Webhook endpoints are configured per account in the AdvanGuard platform:

  • Webhook HTTPS URL — your endpoint that receives event notifications
  • Shared secret key (secretKey) — used for request signing (Base64-encoded; decode before use)

Event Format

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "eventType": "APPLICATION_COMPLETED",
  "webhookId": "wh_xxx",
  "data": {
    "applicationId": "app-7392581047263518721",
    "externalUserId": "user-001",
    "profileId": "pf-1234567890",
    "levelId": "level-kyc-standard",
    "status": "completed",
    "reviewAnswer": "GREEN"
  }
}

Event Fields

FieldTypeDescription
eventIdStringUnique event identifier (use for deduplication)
eventTypeStringEvent type (see table below)
webhookIdStringWebhook configuration ID in the AdvanGuard platform
dataObjectEvent-specific payload

Event Types

Application Events

Triggered when an Application's status changes.

eventTypeTriggerDescription
APPLICATION_PENDINGinitpendingData submission completed, verification in progress
APPLICATION_ON_HOLDpendingonHoldWaiting for manual review or external processing
APPLICATION_COMPLETEDcompletedVerification finished (check reviewAnswer for result)
APPLICATION_TERMINATEDterminatedApplication cancelled (manual or timeout)

Application event data fields:

FieldTypeDescription
applicationIdStringApplication ID
externalUserIdStringCustomer system user identifier
profileIdStringAssociated Profile ID
levelIdStringAssociated Level ID
statusStringNew application status
reviewAnswerStringGREEN (passed) or RED (rejected). Only present for APPLICATION_COMPLETED

AML Events

Triggered by AML ongoing screening updates.

eventTypeTriggerDescription
AML_OGS_UPDATEOngoing screening detects changesNew or updated screening results found
AML_ALERT_CREATEA new AML alert is createdTriggered when an alert is created by screening, re-screening, or ongoing monitoring

AML_OGS_UPDATE event data fields:

FieldTypeDescription
profileIdStringProfile ID
caseIdStringAML Case ID
alertIdStringAlert ID
numberOfNewResultsIntegerNumber of new matches
numberOfUpdatedResultsIntegerNumber of updated matches

Example:

{
  "eventId": "660e8400-e29b-41d4-a716-446655440001",
  "eventType": "AML_OGS_UPDATE",
  "webhookId": "wh_xxx",
  "data": {
    "profileId": "pf-1234567890",
    "caseId": "amlc_4d372e682f464d8f93856892b8b2cee1",
    "alertId": "amla_5e4fc571870841ecbff2f0e506101d7d",
    "numberOfNewResults": 0,
    "numberOfUpdatedResults": 1
  }
}

AML_ALERT_CREATE event data fields:

FieldTypeDescription
profileIdStringAssociated Profile ID. null if the alert is not linked to a case
caseIdStringAML Case ID. null if the alert is not linked to a case
alertIdStringAlert ID
createdAtLongAlert creation time in Unix epoch milliseconds

Example:

{
  "eventId": "bb0e8400-e29b-41d4-a716-446655440006",
  "eventType": "AML_ALERT_CREATE",
  "webhookId": "wh_xxx",
  "data": {
    "profileId": "pf-1234567890",
    "caseId": "amlc_4d372e682f464d8f93856892b8b2cee1",
    "alertId": "amla_5e4fc571870841ecbff2f0e506101d7d",
    "createdAt": 1752489000000
  }
}

Business Verification Events

Triggered when a standalone business verification check changes status.

eventTypeTriggerDescription
BUSINESS_VERIFICATION_STATUSBusiness verification status changesThe verification result for a submitted business check has been updated

BUSINESS_VERIFICATION_STATUS event data fields:

FieldTypeDescription
idStringBusiness verification result ID
statusStringVerification check status (IN_PROGRESS, COMPLETED, ERROR)
checkItemStringThe business check item that was performed (e.g. Basic Business Verification)
updatedAtIntegerUpdate time in Unix epoch seconds

Example:

{
  "eventId": "770e8400-e29b-41d4-a716-446655440002",
  "eventType": "BUSINESS_VERIFICATION_STATUS",
  "webhookId": "wh_xxx",
  "data": {
    "id": "KYBC-201464826803499999",
    "status": "COMPLETED",
    "checkItem": "Basic Business Verification",
    "updatedAt": 1769405823
  }
}

KYB Application Events

Triggered when a KYB application changes status.

eventTypeTriggerDescription
KYB_APPLICATION_STATUS_CHANGEApplication status changesKYB application status change event (triggered when the application status changes)

KYB_APPLICATION_STATUS_CHANGE event data fields:

FieldTypeDescription
applicationIdStringKYB application ID (e.g. KYB-XXXXXXXX)
statusStringNew application status (DRAFT, IN_PROGRESS, PENDING_REVIEW, PENDING_RESUBMISSION, APPROVED, REJECTED)
updatedAtIntegerUpdate time in Unix epoch seconds

Example:

{
  "eventId": "880e8400-e29b-41d4-a716-446655440003",
  "eventType": "KYB_APPLICATION_STATUS_CHANGE",
  "webhookId": "wh_xxx",
  "data": {
    "applicationId": "KYB-XXXXXXXX",
    "status": "IN_PROGRESS",
    "updatedAt": 1720425600
  }
}

KYB Email Notification Events

When webhook email notifications are enabled, the system pushes email content to your endpoint instead of sending emails directly, so you can handle delivery yourself. Empty fields are omitted from the payload (rather than returned as null).

eventTypeTriggerDescription
KYB_IDV_EMAILIDV email needs to be sentEmail notifications during the Identity Verification (IDV) process
KYB_QNRE_EMAILQuestionnaire email needs to be sentEmail notifications during the Questionnaire process (OTP, form link, confirmation)

KYB_IDV_EMAIL event data fields:

FieldTypePresenceDescription
emailStringAlwaysEmail address of the individual being verified
directUrlStringOnly for REQUEST_IDVIdentity verification link for the individual
expireHourIntegerOnly for REQUEST_IDVLink validity period in hours
emailTypeStringAlwaysREQUEST_IDV, NOTIFY_IDV_SUCCESS, or NOTIFY_IDV_FAILED

KYB_QNRE_EMAIL event data fields:

FieldTypePresenceDescription
emailStringAlwaysEmail address of the respondent
otpCodeStringOnly for OTP_VERIFICATION6-digit numeric verification code
urlStringOnly for FORM_NOTIFICATIONForm link for the recipient to continue filling
emailTypeStringAlwaysFORM_NOTIFICATION, OTP_VERIFICATION, or SUBMISSION_CONFIRMATION

Examples:

{
  "eventId": "990e8400-e29b-41d4-a716-446655440004",
  "eventType": "KYB_IDV_EMAIL",
  "webhookId": "wh_xxx",
  "data": {
    "email": "[email protected]",
    "directUrl": "https://kyb.example.com/idv?id=xxx&token=yyy",
    "expireHour": 72,
    "emailType": "REQUEST_IDV"
  }
}
{
  "eventId": "aa0e8400-e29b-41d4-a716-446655440005",
  "eventType": "KYB_QNRE_EMAIL",
  "webhookId": "wh_xxx",
  "data": {
    "email": "[email protected]",
    "otpCode": "385721",
    "emailType": "OTP_VERIFICATION"
  }
}

Content Signature

All webhook requests are signed using your shared secret key. Verify signatures to ensure events originate from AdvanGuard.

Signature Headers

HeaderDescription
aai-timestampRequest timestamp (seconds, Unix epoch)
aai-nonceOne-time random string for replay protection
aai-signatureBase64-encoded HMAC-SHA256 signature

What to Sign

The exact raw HTTP POST body (UTF-8), as received. Do not re-serialize or reformat the JSON — any change breaks the signature.

How to Compute

keyBytes  = Base64.decode(sharedSecretFromConsole)
signature = Base64( HMAC_SHA256(keyBytes, rawRequestBody) )

aai-timestamp and aai-nonce are for replay checks only — they are not part of the HMAC input.

Signature Verification

Step 1: Read Headers

Extract aai-timestamp, aai-nonce, and aai-signature from the request.

Step 2: Validate Timestamp

Reject requests where aai-timestamp is more than 5 minutes from current time.

Step 3: Validate Nonce

Each aai-nonce must be unique. Cache nonce values for at least 5 minutes to detect replays.

Step 4: Verify Signature

Recompute the HMAC-SHA256 signature and compare with aai-signature.

Java

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class WebhookVerifier {

    public static boolean verify(String rawBody, String secretKey, String signatureHeader)
            throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(secretKey);
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(keyBytes, "HmacSHA256"));
        String expected = Base64.getEncoder().encodeToString(
                mac.doFinal(rawBody.getBytes(StandardCharsets.UTF_8)));
        return expected.equals(signatureHeader);
    }
}

Step 5: Respond

ResponseResult
Any 2xxDelivery successful
Non-2xxDelivery failed, retry will be triggered

Important: Respond with 200 quickly and process the event asynchronously. Long processing times may cause timeouts and unnecessary retries.

Retry Policy

If a webhook request fails, the system retries delivery automatically.

Failure Conditions

  • Network error
  • Request timeout (> 60 seconds)
  • Any non-2xx HTTP response

Retry Schedule

AttemptDelay
1st retry5 seconds
2nd retry10 seconds
3rd retry20 seconds

Webhooks follow an at-least-once delivery model. After 3 failed retries, the event is not retried further — use polling as a fallback.

Best Practices

  1. Respond quickly — return 200 immediately and process the event in background.
  2. Handle duplicates — use eventId to deduplicate; the same event may be delivered more than once.
  3. Verify signatures — always verify the aai-signature header before processing.
  4. Implement polling — do not rely solely on webhooks; poll for status as a fallback.
  5. Use HTTPS — only HTTPS endpoints with TLS 1.2+ are supported.
  6. Cache the raw body — read and cache the raw HTTP body before your framework parses JSON, to ensure correct signature verification.