Webhook V1 Validation via Python

Hello,
I’ve set up a webhook on my Private app triggered on a Contact property update.
I’m trying to validate the request (using the v1 validation) but the hashes are not matching.
Below is my Python code:

client_secret = os.environ.get("HUBSPOT_WEBHOOK_SECRET")
payload = json.loads(request.body)
hubspot_signature = request.headers.get('X-Hubspot-Signature')
print(hubspot_signature)
# Validate request from HubSpot
source_string = client_secret + json.dumps(payload)
expected_hash = hashlib.sha256(source_string.encode()).hexdigest()
print("Hash", expected_hash)
if expected_hash == hubspot_signature:
 print("Good to go")
 for update in payload:
 # Update user
 print("Update obj", update)

return Response(status=200)

I had to change it slightly from the docs as I’m using python3 (hence json.dumps and having to use .encode())
Everything runs correctly, but the expected_hash is not matching the hubspot_signature. I have confirmed that my client_secret matches the secret on my Private app.
Any ideas?

Hi @DonalPocketed

Flask application is correctly configured to receive POST requests at the webhook route and that your server is accessible to HubSpot

Kindly replace ‘/webhook’ with the actual route where your webhook is set up in your Flask application

Update the code with the -
request.data.decode(‘utf-8’) instead of json.dumps(request.body) to decode the raw request data, as request.body might not provide the raw bytes necessary for generating the correct hash

@app.route(‘/webhook’, methods=[‘POST’])
def webhook():
client_secret = os.environ.get(“HUBSPOT_WEBHOOK_SECRET”)
payload = json.loads(request.data)
hubspot_signature = request.headers.get(‘X-Hubspot-Signature’)

# Validate request from HubSpot
source_string = client_secret + request.data.decode(‘utf-8’)
expected_hash = hashlib.sha256(source_string.encode(‘utf-8’)).hexdigest()

if expected_hash == hubspot_signature:
print(“Signature is valid”)
for update in payload:
# Update user
print(“Update obj”, update)
return Response(status=200)
else:
print(“Signature is invalid”)
return Response(status=403)

Hope this helps - Happy to help further !!

Thank you very much and have a fantastic day!

Warm regards

Thank you for the response on this @Humashankar !
This exact code didn’t work as I’m actually using Django (rest framework) - but it pointed me in the right direction.
Below is the code that worked for me in case anyone else is using Django for their webhooks:

def post(self, request, *args, **kwargs):
 client_secret = os.environ.get("HUBSPOT_WEBHOOK_SECRET")
 payload = json.loads(request.body)
 hubspot_signature = request.headers.get('X-Hubspot-Signature')
 # Validate request from HubSpot
 source_string = client_secret + request.body.decode('utf-8')
 expected_hash = hashlib.sha256(source_string.encode('utf-8')).hexdigest()
 ## Check that the hash matches the request signature
 if expected_hash == hubspot_signature:
 for update in payload:
 ## Check the contact for their email
 contact_id = update['objectId']
 try:
 hs_contact = api_client.crm.contacts.basic_api.get_by_id(contact_id)
 print(hs_contact)
 except Exception as e:
 print(e)
 return
 property = update['propertyName']
 value = update['propertyValue']
 print(property, value)

 return Response(status=200)

So very similar to what you sent but I had to use request.body instead of request.data.
I will mark your response as the accepted solution.
Thanks again!

Hi @DonalPocketed - It was great to know that hint helped you to fix the code.

As well as your acceptance is a motivation for me to help others in the community !!