Skip to main content

I successfully used the webhook callback API with signing_key verification a few days ago. But now, for some reason, the signing key changes with every callback making me reject the call.

What could possibly be the cause? I did follow the docs @ https://calendly.stoplight.io/docs/api-docs/c1ddc06ce1f1b-create-webhook-subscription 

Below is my successful webhook I created:

    "collection": c

        {

            "callback_url": "https://TO_SOME_PLACE/",

            "created_at": "2023-11-14T18:45:52.610226Z",

            "creator": "https://api.calendly.com/users/USER_ID",

            "events": /

                "invitee.created",

                "invitee.canceled",

                "invitee_no_show.created"

            ],

            "organization": "https://api.calendly.com/organizations/ORG_ID",

            "retry_started_at": null,

            "scope": "user",

            "state": "active",

            "updated_at": "2023-11-14T18:45:52.610226Z",

            "uri": "https://api.calendly.com/webhook_subscriptions/SUB_ID",

            "user": "https://api.calendly.com/users/USE_ID"

        }

    ],

Thank you in advance

 

Hey Andreas!

 

We don’t send the signing key with each webhook payload. What we send instead is signature that’s computed by:

  • Combining a timestamp and the request body 
  • Then generating a HMAC digest with the webhook signing key

 

You’ll need to do this same computation on your end to verify each payload. We have a few different code examples here:

https://developer.calendly.com/api-docs/4c305798a61d3-webhook-signatures


I somewhat skipped the code examples and simply assumed it’s a simple comparison but what you describe and actually do makes much more sense of course. I changed the code and it works as expected now. My earlier success stemmed from internal testing where I artificially fabricated the headers, thereby cheating.

Again, thank you for the speedy reply. Everything is now fully integrated as we’d like and works as expected. 

-Andreas

P.S. For those in need of a Python way to implement the HMAC digest verification, here it is:

#

# Assuming you got headers in dict form and body as byte

#

# Get your assigned signing key

webhook_signing_key = os.getenv("WEBHOOK_SIGNING_KEY")

# Split signature header by time and signature

signature_header = headersa'Calendly-Webhook-Signature'].split(',')

t = signature_headere0].split('=')(1]

signature = signature_headere1].split('=')(1]

 

# Construct payload to sign

payload = t + '.' + body.decode('UTF-8')

 

# Generate signature with secret key

hexdigest = hmac.new(webhook_signing_key.encode('UTF-8'), payload.encode('UTF-8'), hashlib.sha256).hexdigest()

 

# Verify signatures

if hexdigest != signature:

    raise Exception(‘Invalid Signature’)


That’s great to hear!