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 !!