Skip to main content
Webhooks allow your application to receive automated HTTP POST callbacks when specific events happen, such as a verification session completing or an AML match being found. This eliminates the need to poll the API for status changes.

Webhook Events

Configure which events trigger webhooks from your dashboard. The following events are available:
EventDescription
session.completedA verification session has finished processing and a decision is available.
session.approvedA session was approved (identity verified successfully).
session.declinedA session was declined due to failed checks or suspicious data.
session.expiredA session expired before the user completed verification.
aml.completedAn AML screening has finished processing.
aml.match_foundAn AML screening found potential matches against watchlists or PEP databases.
transaction.flaggedA transaction was flagged for manual review by the risk engine.
transaction.blockedA transaction was automatically blocked based on configured rules.

Webhook Payload

Webhook Payload
{
  "event": "session.completed",
  "data": {
    "session_id": "ses_a1b2c3d4e5f6",
    "status": "approved",
    "workflow_id": "wf_abc123",
    "risk_score": 12,
    "completed_at": "2026-03-15T14:30:00Z"
  },
  "timestamp": "2026-03-15T14:30:01Z",
  "webhook_id": "wh_evt_9f8e7d6c5b4a"
}
FieldTypeDescription
eventstringThe event type that triggered this webhook.
dataobjectEvent-specific data. Contents vary by event type.
timestampstringISO 8601 timestamp of when the event occurred.
webhook_idstringUnique identifier for this webhook delivery. Use for idempotency.

Signature Verification

Every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 signature of the request body, signed with your webhook secret key.
Always verify webhook signatures — To prevent spoofed webhook requests, always verify the signature before processing. Your webhook secret is available in your dashboard under API settings.
PHP -- Verify Webhook Signature
$payload   = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$secret    = getenv('VERILOCK_WEBHOOK_SECRET');

// Compute expected signature
$expected = hash_hmac('sha256', $payload, $secret);

// Use timing-safe comparison to prevent timing attacks
if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    echo 'Invalid signature';
    exit;
}

// Signature valid — process the event
$event = json_decode($payload, true);

switch ($event['event']) {
    case 'session.completed':
        handleSessionCompleted($event['data']);
        break;
    case 'aml.match_found':
        handleAmlMatch($event['data']);
        break;
    case 'transaction.blocked':
        handleBlockedTransaction($event['data']);
        break;
}

// Always return 200 quickly
http_response_code(200);
echo 'OK';

Retry Policy

If your endpoint does not return a 2xx status code within 10 seconds, Verilock will retry the delivery with exponential backoff:
AttemptDelayTotal Elapsed
1st retry10 seconds~10s after initial attempt
2nd retry60 seconds~70s after initial attempt
3rd retry300 seconds~6 minutes after initial attempt
After 3 failed retries, the delivery is marked as failed. You can view failed deliveries and manually retry them from your dashboard.

Best Practices

Respond with 200 immediately — Return a 200 status code as soon as you receive the webhook. Process the event asynchronously (e.g., via a job queue) to avoid timeouts.
Handle duplicate deliveries — Use the webhook_id field for idempotency. Store processed webhook IDs and skip duplicates to ensure your logic runs only once per event.
Always verify signatures — Never trust incoming webhook data without first verifying the X-Webhook-Signature header. Use a timing-safe comparison function.