Skip to main content

Request authentication

An API request from the Webhooks API can be verified by using the Host, X-ms-date, X-ms-content-sha256 and Authorization headers with the unique secret specified when the webhook was registered with POST:/webhooks/v1/webhooks. For more info, see POST:/webhooks/v1/webhooks.

The authorization is a SHA-256 HMAC hash of:

  • Request date
  • Content of the webhook payload
  • Webook URI that is created using the secret specified for the webhook.

Sample Data

Receiving the secret when registering webhook


"url": "",
"events": ["epayments.payment.created.v1", ...]

"//": "👇 This is the important bit"

Sample request sent to you with valid authorization and content


x-ms-date = Thu, 30 Mar 2023 08:38:32 GMT
x-ms-content-sha256 = lNlsp1XA03N34HrQsVzPgJKtC+r7l/RBF4V3JQUWMj4=
Authorization = HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=agAiSyogQbDHpeucoNwYz+yAr5nJ+v+zasdkSbqzv+U=


How to verify a received request

Check that the content has not been modified

Hash the serialized request content using SHA256 encryption then base64 encode it. This hash should match the header value 'x-ms-content-sha256'.

'X-Ms-Content-Sha256': 'lNlsp1XA03N34HrQsVzPgJKtC+r7l/RBF4V3JQUWMj4='

Verify the authentication header

Concatenate request method, path and query, date, host and content hash (from previous step) like so: POST\n\<pathAndQuery\>\n\<date\>;\<host\>;\<hash\> and sign it with the hmac-sha256 and your secret. This ought to match the Signature part of the 'authorization' header in the request you received. Please note the use of \n not \r\n.

Authorization: HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=agAiSyogQbDHpeucoNwYz+yAr5nJ+v+zasdkSbqzv+U=

Sample Code

'use strict';

const assert = require('node:assert');
const { describe, it } = require('node:test');

const crypto = require('crypto');

describe('Sample Code', () => {

it('Verifying Hmac Headers', () => {

const secret = 'A0+AeKBRG2KRGvnNwJpQlb6IJFk48CKXCIcrLoHncVJKDILsQSxS6NWCccwWm6r6FhGKhiHTBsG2wo/xU6FY/A==';

const request = {
method: 'POST',
url: '',
pathAndQuery: '/e2cee29b-012e-4f1d-8ef4-e95fd74a7a63', // this is the path and query part of the target URL
headers: {
'X-Ms-Date': 'Thu, 30 Mar 2023 08:38:32 GMT' ,
'X-Ms-Content-Sha256': 'lNlsp1XA03N34HrQsVzPgJKtC+r7l/RBF4V3JQUWMj4=' ,
'Host': '', // this is the host part of the target URL
'Authorization': 'HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=agAiSyogQbDHpeucoNwYz+yAr5nJ+v+zasdkSbqzv+U='
content: '{"some-unique-content":"ee6e441b-cc4a-46f8-895d-a5af79bcc233/hello-world"}'

// Verify content
const expectedContentHash = crypto

assert.equal(request.headers['X-Ms-Content-Sha256'], expectedContentHash, 'Content hash was not valid');

// Verify signature
const expectedSignedString =
`${request.method}\n` +
`${request.pathAndQuery}\n` +

const expectedSignature = crypto.createHmac('sha256', secret)

const expectedAuth = `HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=${expectedSignature}`

assert.equal(expectedAuth, request.headers.Authorization, "Authorization was not valid");

Help us improve our documentation

Did you find what you were looking for?