All webhook deliveries are HTTP POST requests to the registered URL with Content-Type: application/json.
Payload structure:
{
"event": "license.activated",
"timestamp": "2026-03-31T12:34:56Z",
"data": {
"license_id": 42,
"site_url": "https://customer-site.com",
"activation_id": 107
}
}
The data object contains the full resource representation at the time of the event. The exact fields vary by event type and mirror the corresponding REST API resource response.
Security header:
Every delivery includes the header:
X-DMSI-Signature: sha256=<HMAC-SHA256-hex>
The HMAC is computed over the raw request body bytes using your endpoint signing secret.
Verifying the signature in PHP:
function dmsi_verify_webhook( string $body, string $secret, string $signature_header ): bool {
if ( strpos( $signature_header, 'sha256=' ) !== 0 ) {
return false;
}
$received = substr( $signature_header, 7 );
$expected = hash_hmac( 'sha256', $body, $secret );
return hash_equals( $expected, $received );
}
$body = file_get_contents( 'php://input' );
$header = $_SERVER['HTTP_X_DMSI_SIGNATURE'] ?? '';
$secret = 'whs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // your stored secret
if ( ! dmsi_verify_webhook( $body, $secret, $header ) ) {
http_response_code( 401 );
exit;
}
$payload = json_decode( $body, true );
// process $payload['event'] and $payload['data']
Always verify the signature before processing the payload. Use hash_equals to prevent timing attacks.
Responding to deliveries:
Return any 2xx HTTP status code within 30 seconds to acknowledge receipt. Any non-2xx response or a connection timeout causes the delivery to be marked as failed and scheduled for retry.
