# Webhook V1 Validation via Python

**URL:** <https://community.hubspot.com/t/webhook-v1-validation-via-python/101537>\
**Category:** APIs & Integrations\
**Tags:** webhooks\
**Created:** [March 1, 2024, 9:38pm UTC](https://community.hubspot.com/t/webhook-v1-validation-via-python/101537 "2024-03-01T21:38:23Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![DonalPocketed](https://avatars.discourse-cdn.com/v4/letter/d/8e7dd6/32.png) [@DonalPocketed](https://community.hubspot.com/u/DonalPocketed)\
**Post date:** [March 1, 2024, 9:38pm UTC](https://community.hubspot.com/t/webhook-v1-validation-via-python/101537/1 "2024-03-01T21:38:23Z")

</div>

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:

```lia-code-sample
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?

---

<div class="post-metadata">

**Author:** ![Humashankar](https://d10pqhm3lwygmk.cloudfront.net/user_avatar/community.hubspot.com/humashankar/32/30856_2.png) [@Humashankar](https://community.hubspot.com/u/Humashankar)\
**Post date:** [March 2, 2024, 8:23pm UTC](https://community.hubspot.com/t/webhook-v1-validation-via-python/101537/2 "2024-03-02T20:23:27Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![DonalPocketed](https://avatars.discourse-cdn.com/v4/letter/d/8e7dd6/32.png) [@DonalPocketed](https://community.hubspot.com/u/DonalPocketed)\
**Post date:** [March 4, 2024, 9:55pm UTC](https://community.hubspot.com/t/webhook-v1-validation-via-python/101537/3 "2024-03-04T21:55:55Z")

</div>

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:

```lia-code-sample
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!

---

<div class="post-metadata">

**Author:** ![Humashankar](https://d10pqhm3lwygmk.cloudfront.net/user_avatar/community.hubspot.com/humashankar/32/30856_2.png) [@Humashankar](https://community.hubspot.com/u/Humashankar)\
**Post date:** [March 4, 2024, 9:59pm UTC](https://community.hubspot.com/t/webhook-v1-validation-via-python/101537/4 "2024-03-04T21:59:31Z")

</div>

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