Webhook Request Verification


I’m having trouble verifying webhooks coming in from ShipHero.
I’ve tried to pinpoint the issue, and it seems it has to do with how the post params are converted to JSON and fed to the hmac.new(… msg:data …) function.

Running the example in this page (Webhooks – Developer Resources | ShipHero) does not yield proper results, since what’s being sent in the “X-ShipHero-HMAC-SHA256” header is always different than the generated HMAC.

Could you please clarify how are you converting the post params to JSON (other than the plain old JSON encoding to a string)?

It’s also important to note that I’m trying to verify the Generate Label Webhook, and I’ve create a new app in the Settings > API section and using the API Secret to generate the HMAC. Might it be that the HMAC in the header is generated using a different API Secret?


If you post your code it would possibly be easier to troubleshoot. One thing that wasn’t obvious to me initially is the HMAC module is expecting the secret to be a byte string or bytesarray. If you have stored your secret in a text format then you would want to call .encode() on it prior to passing it into the example function. We use Django so the specifics of your request handling may be different.

secret = "<secret from settings>".encode()
hmac_header = request.META.get('HTTP_X_SHIPHERO_HMAC_SHA256')
verified = verify_webhook_hmac(secret, request.body, hmac_header)
1 Like

I’m using PHP instead of Python, but the issue is with the inputs and not the actual implementation.
Here is a snippet of how the HMAC is generated:

// String retrieved from API > Settings by creating a new Shop
$api_secret = [API_SECRET];

// JSON String of POST Params
$request_content = '{"shipping_name":"Manual Order Shipping Method","to_address":{"city":"SAN FRANCISCO","state":"CA","zip":"94105","name":"test order","address_2":null,"country":"US","address_1":"123 MAIN ST","email":"none@none.com","phone":null,"company_name":null},"shipping_method":"My Carrier","order_id":"83478763","packages":[{"width":10,"weight_in_oz":11,"length":10,"line_items":[{"tariff_code":"0","price":"0.00","customs_description":null,"customs_value":"0.00","line_item_id":"225458557","barcode_exists":"0","partner_line_item_id":"MO114-265348960","sku":"yellow-kit","barcode_scanned":"0","name":"Yellow Kit","ignore_on_customs":false,"product_name":"Yellow Kit","quantity":"2"}],"height":10}],"order_number":"MO114","partner_order_id":"MO114","from_address":{"city":"Garnerville","state":"NY","zip":"10923","name":"ShipHero Apparel","address_2":null,"country":"US","address_1":"123 Main St","email":"hello@shiphero.com","phone":"11111111111","company_name":null}}';

// Base64 Encoded HMAC using SHA-256 algorithm and binary output
$hashed_signature = base64_encode(hash_hmac(

HMAC is generating fine, but the issue is the one passed through the headers (X-ShipHero-HMAC-SHA256) is always different than the generated one.

Hi @mansourw
Thanks for reaching out and welcome to our community!
Would you have an order we can use for investigating this on our side?
Thanks in advance!

Hello Tomas,

Thanks for replying, and apologies for the delay in responding.

Basically this is happening on all orders received via the Generate Label Webhook, I’m sure the issue is with generating the HMAC on our end so that we’d compare with the one coming in from the headers.

Any pointers on how you are building the HMAC from your end before attaching it to the header?
Are you using the JSON string of the POST body?

It would be appreciated if you could walk us through all the steps in order to perform this properly.

Thanks in advance,

Hi @mansourw!
My apologies for missing your reply earlier.

This is what Im currently doing to test this:

In my test order I get this as Body:

{"shipping_method": "Test", "order_id": 171413532, "profile": "default", "fulfillment_status": "pending", "order_number": "#1292", "shop_name": "tomstomcats.myshopify.com", "account_id": 6334, "partner_order_id": "3184834740412", "shipping_name": "None", "from_address": {"name": "tomas wingord", "company_name": "tomas wingord", "address_1": "55 W RAILROAD AVE BLDG 4", "address_2": "BLDG 4", "email": "twingord@shiphero.com", "city": "GARNERVILLE", "state": "NY", "zip": "10923", "country": "US", "phone": "8556055222"}, "to_address": {"name": "tomas wingord", "company_name": "shiphero", "address_1": "55 W railroad Av", "address_2": "", "email": "twingord@shiphero.com", "city": "GARNERVILLE", "state": "NY", "zip": "10923", "country": "US", "phone": "8556055222"}, "packages": [{"weight_in_oz": 49.01, "width": 0.0, "length": 0.0, "height": 0.0, "line_items": [{"sku": "46401204", "tariff_code": "610442", "price": 180.0, "customs_description": "Jacket1", "customs_value": "180.00", "line_item_id": 475870287, "quantity": 1, "weight": 48.01, "partner_line_item_id": "9117670375612", "id": "9117670375612", "country_of_manufacture": "", "product_name": "Jacket1", "name": "Jacket1", "ignore_on_customs": false}], "box_code": "custom"}]}

With this x-shiphero-hmac-sha256:


And then at https://app.shiphero.com/dashboard/settings/api my Secret is


So if I use the HMAC generator tool: Free HMAC-SHA256 Online Generator Tool | Devglan

I get the hmac-sha256 that should be:


For this last part, make sure that its set to Base64 and not plain text

Let me know if that matches or not for you.

Thanks again for the patience!

1 Like

Hey tomasw!

Thank you for your detailed reply.
One thing I’ve realized, and I think would be the root of the issue is that there is a “1” before the HMAC from the header (x-shiphero-hmac-sha256) as well as another “1” that is omitted from the secret.

Is that something relevant? And if yes, it’s important to note that our secret starts with a “0” and not a “1”.

Thanks again!
We’ll let you know if all works out.


Nice catch @mansourw! :sweat_smile:

My apologies for that, I pasted that from a text editor I was using and it added a 1 somehow.
My secret is actually


(I edited my comment above as well)

Hey @tomasw!

Thank you again for the support. Just wanted to let you know everything is working perfectly :slight_smile:



Hi @tomasw,

It seems there is a new issue that has emerged regarding the Generate Label Webhook.
You’ve stopped sending the header ‘X-ShipHero-HMAC-SHA256’ :confused:
Has the name of the header changed?


Hi @mansourw

Thanks for reporting this! We are currently investigating this internally and will let you know. It looks like it is no longer sending the header (but it should).
We will keep you updated
Thanks again!

Hi @mansourw!
HMAC should be displaying now for your webhooks. Give it a try and let us know
Thanks again for the patience while we investigated this,

Hey @tomasw!

Hope you’re doing well.

We’ve received feedback from Mike regarding this, but it seems we need more information on how to proceed.
How I see it, you’ve added an API record for “Manual Order” and specified that we should use the key/secret combination from there.
However, we are operating a 3PL account, and it wont always be feasible to create an API key/secret for each subaccount.
Would it be possible to attach the HMAC headers for webhooks created with an API key/secret from the main account (ie. when selecting “All” in the dropdown list)