Python Smartsheet Webhook Verification

I am not a programmer by any stretch of the imagination. I am trying to create a webhook in Python using Anvil for the callback url

I have created a webhook. I am struggling to get it authenticated/verified. I have spent hours reading and trying all sorts of solutions.

I am using Atom on my desktop for the webhook.

On Anvil, the code I for the callback url is as follows:


@anvil.server.http_endpoint('/webhook', methods=['POST'])

def webhoook(**q):

    if 'Smartsheet-Hook-Challenge' in event['headers']:

      return {

        'statusCode': 200,

        'headers': {

          'Smartsheet-Hook-Response':

            event['headers']['Smartsheet-Hook-Challenge'],

          'Content-Type': 'application/json',

          'Access-Control-Allow-Methods': 'OPTIONS,GET,POST'

        }

      }



The code I have for the webhook to enable it is as follows:

Webhook = smartsheet_client.Webhooks.update_webhook(

 WEBHOOK_ID_IS_HERE,    # webhook_id

 smartsheet_client.models.Webhook({

  'enabled': True}))


IndexResult = smartsheet_client.Webhooks.list_webhooks(

 page_size=100,

 page=1,

 include_all=False)


print(Webhook)



The response I get back is always disabled.



How do I get my callback url to send the smartsheet header challenge back to smartsheet to enable this webhook?


Additionally, I have code that updates a dropdown list. I currently have this code executing every sixty seconds. Once I get this webhook enabled, how do I listen for this event to execute my code?

Answers

  • I've got the following code echoing back on reqbin just fine. However, when I try to enable the webhook with smartsheet, it returns an HTTP 500


    @anvil.server.http_endpoint('/webhook', methods=['POST'])

    def webhoook(**q):

     request = anvil.server.request

     challenge = request.body_json['challenge']

     return {'smartsheetHookResponse': challenge}

  • Genevieve P.
    Genevieve P. Employee Admin

    Hi @ducktapeonmydesk

    Were you able to get this resolved? It looks like the challenge should maybe be set to the request.headers.get instead of the request.body_json.

    If this isn't the issue, I would recommend reaching out to Smartsheet Support so they can work with you in a private channel on this, or posting in the Stack Overflow community, here.

    Cheers!

    Genevieve

  • ducktapeonmydesk
    edited 10/15/21

    Hi, @Genevieve P. ,


    Yes, I actually got this working. To help anyone that may come across this in the future that is also looking for help, I will post my code below.


    This is the code that I put on the Anvil server

    import anvil.server
    import json
    import requests
    
    @anvil.server.http_endpoint('/webhook', methods=['POST'])
    def webhook():
      request = anvil.server.request
      challenge = request.headers.get('smartsheet-hook-challenge')
      ssresponse = {'smartsheetHookResponse': challenge}
      return [ssresponse,anvil.server.call('updateAppt')]
    


    I was then able to enable to webhook with the following code

    import smartsheet
    
    smartsheet_client = smartsheet.Smartsheet('YOUR SECRET KEY HERE')
    
    Webhook = smartsheet_client.Webhooks.update_webhook(
      WEBHOOK ID HERE,       # webhook_id
      smartsheet_client.models.Webhook({
        'enabled': True}))
    
    print(Webhook)
    


    Finally, this is the code for the webhook that Anvil calls from the first code block above. The code here is for updating a dropdown list (just as ddupdate does), but you can put whatever you want between 'def updateAppt()' and the last line, 'anvil.server.wait_forever()'

    import smartsheet
    import anvil.server
    
    anvil.server.connect("YOUR ANVIL UPLINK CODE HERE")
    
    @anvil.server.callable
    def updateAppt():
        smartsheet_client = smartsheet.Smartsheet('YOUR SECRET KEY HERE')
        smartsheet_client.errors_as_exceptions(True)
        sheet = smartsheet_client.Sheets.get_sheet(SHEET ID HERE) #PM Appt times
        schsheet = smartsheet_client.Sheets.get_sheet(SHEET2 ID HERE) #Main Sheet
        apptColumn = COLUMN ID HERE
        schAvailAppointTime = COLUMN2 ID HERE
        apptColumn = smartsheet_client.Sheets.get_sheet(sheet.id, column_ids=apptColumn)
        schAvailAppointTime = smartsheet_client.Sheets.get_sheet(schsheet.id, column_ids=schAvailAppointTime)
        schsheetcolumns = smartsheet_client.Sheets.get_columns(schsheet.id, include_all=True)
    
        apptArray = []
        for row in apptColumn.rows:
            for cell in row.cells:
                if cell.value != None:
                    apptArray.append(cell.value)
    
                column_spec = smartsheet.models.Column({'type':'PICKLIST', 'options': apptArray})
        response = smartsheet_client.Sheets.update_column(schsheet.id, COLUMN2 ID HERE, column_spec)
        updated_column = response.result
    
    anvil.server.wait_forever()
    


  • Genevieve P.
    Genevieve P. Employee Admin

    Hi @ducktapeonmydesk

    Thank you so much for providing your solution! This may be exactly what someone else is looking for, so I really appreciate you taking the time.

    Cheers,

    Genevieve