How to use Asana Webhooks with AWS Lambda (Python)

Sharon Lavie
3 min readDec 1, 2019


What are we going to talk about

This tutorial will show you how to collect data from Asana with webhooks using an AWS Lambda function with an API Gateway

The next tutorial will show how to load the webhook data into a Postgresql database.


As i wanted to automate some processes in my company, including data from Asana, i was trying to set webhooks and load the data to a Postgresql DB that would be used by our Backend team.

The steps are:

  • create a Lambda function (with an API Gateway)
  • create an Asana access token
  • establish an Asana Webhook

Create a Lambda function (with an API Gateway)

(we’re gonna use Python 3.7)

  • Login to the AWS console, go to Lambda and create a new function
  • Give it a name, choose python 3.7 (not 3.8**) and for permissions choose — ‘ Create a new role with basic Lambda permissions’
  • Click on ‘Create Function’

** we have to use python 3.7 since the package that works with Postgresql db doesn’t support python 3.8.

Choose the trigger

create Lambda trigger

*** We have to choose an open API Gateway, because the Asana API doesn’t support passing parameters to the endpoint.

The API Gateway is created automatically.

At the end of this process, you’ll get back to the Lambda function main screen and have the endpoint (the API gateway) url.

Create an Asana Access Token

follow the instructions here:

I used a personal access token, it’s enough for our needs.

Establish an Asana Webhook

The instructions are stated here:

Not too complicated, but just to make it a bit clearer (when using the python Asana package):

  • Install the python Asana package: pip install asana
  • Send a webhooks/create request from your local machine to Asana.

The code should look like this:

import asana

token = '<asana_token>'

client = asana.Client.access_token(token)
client.headers["Asana-Enable"] = "string_ids"

req = {"resource": "<resource_id>", "target": "<api_endpoint>" }

res = client.webhooks.create(req)


** resource_id → your Asana project id, you can either use the API to fetch it or just copy it from the Asana url

Now! the tricky part is the API handshake process.

As you’ve probably seen, Asana is using a handshake confirmation as described here —

To make this work, you’d need to fetch the request header key — X-Hook-Secret that will be sent by Asana to your endpoint, and return it in your response back to Asana, sounds complicated, but it’s actually a very small piece of code in our Lambda function, so just copy and paste the following code to your Lambda function:

def lambda_handler(event, context):

secret = event['headers']['X-Hook-Secret']
return {"statusCode":"200",
"headers": {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-Hook-Secret': secret

Run your local code as shown above (the webhooks/create request) and it should return the following python list:

{'gid': '<your webhook id>, 'resource_type': 'webhook', 'target': 'https://<your endpoint>', 'active': True, 'created_at': '2019–12–01T17:36:33.430Z', 'last_failure_at': None, 'last_failure_content': '', 'last_success_at': '2019–12–01T17:36:34.093Z', 'resource': {'gid': '<your project id>', 'resource_type': 'project', 'name': '<your project name>'}}