HMAC stands for Hash-based Message Authentication Code, and is described here: https://en.wikipedia.org/wiki/HMAC, but essentially it's a cryptographically secure hash value generated based on a computed value and a pre-shared key.
HMAC signing is enabled by associating an HMAC secret with the API key - this will be either an API user or an API integration. Once a secret is set, valid HMAC signatures must accompany every API request.
The HMAC signature should be sent in a custom HTTP Header named X-PX-Request-ID
>. This header should be built using the following values concatenated together, in this order:
/merchant/30/restaurants/pxweb/menu/tier?key=9dxxxxxfe843bbxxxxxcd9xxxxxf88d850xxxxx
Once this string is generated, the following operations should be performed on it to get the message signature:
X-PX-Request-ID
Request URI: https://od.pxsweb.com/api/v1/merchant/30/restaurants/pxweb/menu/tier?key=9dxxxxxfe843bbxxxxxcd9xxxxxf88d850xxxxx Body: None Timestamp: 1583254634525 Value to be hashed: 1583254634525/merchant/30/restaurants/pxweb/menu/tier?key=9dxxxxxfe843bbxxxxxcd9xxxxxf88d850xxxxx Base64 encoded hash result: 4iX2WnHGrCL2fIc2V9zOH2z2SY/UswsQS+MQSmlrlN8= Header without base64-encoding: 1583254634525;4iX2WnHGrCL2fIc2V9zOH2z2SY/UswsQS+MQSmlrlN8= Actual header to be sent: X-PX-Request-ID: MTU4MzI1NDYzNDUyNTs0aVgyV25IR3JDTDJmSWMyVjl6T0gyejJTWS9Vc3dzUVMrTVFTbWxybE44PQ==
Request URI: https://od.pxsweb.com/api/v1/orders/xxxxx/items?key=9dxxxxxfe843bbxxxxxcd9xxxxxf88d850xxxxx Body: {"id":"xxx","quantity":1,"size":""} Timestamp: 1583254967310 Value to be hashed: 1583254967310/orders/xxxxx/items?key=9dxxxxxfe843bbxxxxxcd9xxxxxf88d850xxxxx{"id":"xxx","quantity":1,"size":""} Base64 encoded hash result: uE9rkxYON1+FU+SWVrRVTZFpO04w0IUvkm28GWF7hI= Header without base64-encoding: 1583254967310;EuE9rkxYON1+FU+SWVrRVTZFpO04w0IUvkm28GWF7hI= Actual header to be sent: X-PX-Request-ID: MTU4MzI1NDk2NzMxMDtFdUU5cmt4WU9OMStGVStTV1ZyUlZUWkZwTzA0dzBJVXZrbTI4R1dGN2hJPQ==
The following Javascript implements this algorithm in Javascript as a Postman Pre-request Script
// 1. Get timestamp in milliseconds var timestampMs = new Date().getTime(); // 2. Get all of url, including query parameters, following /api/v1 var fullUrl = pm.variables.replaceIn(pm.request.url.toString()); var partialUrl = fullUrl.match(/\/api\/v1(.*)$/)[1]; // 3. Get request body, if one exists var requestBody = pm.request.body.raw || ''; // 4. Concatenate var rawHeader = ''.concat(timestampMs, partialUrl, requestBody); // 5. Create binary HMAC using your secret and encode binary result in base64 var signBytes = CryptoJS.HmacSHA256(rawHeader, pm.variables.get('hmac_secret')); var signBase64 = CryptoJS.enc.Base64.stringify(signBytes); // 6. Concatenate timestamp, a semicolon and the base64 signed value and base64 encode the result var hmacBase64 = btoa(''.concat(timestampMs, ';', signBase64)); // 7. Set custom header with final header value pm.request.headers.add({ key: "X-PX-Request-ID", value: hmacBase64 });