Skip to content

Webhook Signatures & Security ​

Biosyn provides real-time HTTP webhook notifications for attendance and access events. When a user interacts with a device (check-in, check-out, door open), Biosyn instantly pushes an event payload to your configured webhook endpoint.


Webhook Signature Verification ​

To ensure that incoming webhooks originate from Biosyn and have not been tampered with, Biosyn signs every request using HMAC SHA-256.

Webhook Headers ​

Every webhook HTTP request includes the following header:

http
X-WDMS-Signature: sha256=a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e

Signature Generation Algorithm ​

  • Algorithm: HMAC-SHA256
  • Secret Key: Your Location Webhook Secret Key (webhook_secret)
  • Message: Exact JSON request body payload (raw string)

Code Verification Examples ​

python
import hmac
import hashlib
import json

def verify_biosyn_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
    if not signature_header or not signature_header.startswith("sha256="):
        return False

    provided_signature = signature_header.split("sha256=")[1]

    expected_signature = hmac.new(
        secret.encode('utf-8'),
        raw_body,
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(expected_signature, provided_signature)
javascript
const crypto = require("crypto");

function verifyBiosynWebhook(rawBody, signatureHeader, secret) {
  if (!signatureHeader || !signatureHeader.startsWith("sha256=")) {
    return false;
  }

  const providedSig = signatureHeader.replace("sha256=", "");
  const expectedSig = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(providedSig, "utf-8"),
    Buffer.from(expectedSig, "utf-8"),
  );
}
php
<?php

function verifyBiosynWebhook(string $rawBody, string $signatureHeader, string $secret): bool
{
    if (empty($signatureHeader) || !str_starts_with($signatureHeader, 'sha256=')) {
        return false;
    }

    $providedSig = substr($signatureHeader, 7);
    $expectedSig = hash_hmac('sha256', $rawBody, $secret);

    return hash_equals($expectedSig, $providedSig);
}

Webhook Event Payload Structure ​

Event: attendance ​

json
{
  "event": "attendance",
  "payload": {
    "location_id": 1,
    "device_sn": "AFK921400123",
    "pin": 10042,
    "card_no": "1234567890",
    "verified_type": 4,
    "door_id": 1,
    "event": 0,
    "status": 0,
    "timestamp": "2026-08-26T10:30:00Z",
    "index": 5978,
    "site_code": 0,
    "dev_id": 1,
    "mask_flag": true,
    "temperature": 36.5,
    "conv_temperature": 97.7,
    "created_at": "2026-08-26T10:30:01Z"
  }
}

Webhook Delivery & Retry Policy ​

  • Max Retries: 3 attempts
  • Backoff Strategy: Exponential backoff (1s, 2s, 4s)
  • Timeout: 30 seconds per attempt
  • Accepted HTTP Response: Any 2xx status code (e.g. 200 OK, 204 No Content)

Enterprise Biometric Gateway Infrastructure