establishing successful webhook

Hi I am new to the asana api . I am using the code provided from the doc references but i am getting this error Error creating webhook:
{
errors: [
{
message: ‘The remote server which is intended to receive the webhook responded with an incorrect status code: 502’,
help: ‘For more information on API status codes and how to handle them, read the docs on errors: Errors
}
]
}

\i am trying to get a single projects details from asana but so far have had no luck.
below is my code

const Asana = require('asana');

const accessToken = 'removed for posting';
const targetUrl = 'https://b1f6-197-245-40-71.ngrok-free.app/webhook';
const PROJECT_ID = 'removed for posting';


const client = Asana.ApiClient.instance;
const token = client.authentications['token'];
token.accessToken = accessToken;

const webhooksApiInstance = new Asana.WebhooksApi();

// Construct the request body
const body = {
    data: {
      resource: PROJECT_ID,
      target: targetUrl,
      filters: [{ resource_type: "task", action: "changed" }] // Example filter: trigger webhook for task changes
    }
  };
  

// Optional query parameters
const opts = {
  opt_fields: "active,created_at,filters,filters.action,filters.fields,filters.resource_subtype,last_failure_at,last_failure_content,last_success_at,resource,resource.name,target"
};

// Create the webhook
webhooksApiInstance.createWebhook(body, opts)
  .then((result) => {
    console.log('Webhook created successfully:');
    console.log(JSON.stringify(result.data, null, 2));
  })
  .catch((error) => {
    console.error('Error creating webhook:');
    console.error(error.response ? error.response.body : error.message);
  });

thank you

Hi @swasteer - I moved your post to the Developers & API forum so you can get more technical responses. A 502 error probably means your haven’t established your server properly (i.e., not an issue with the code you posted).

1 Like

Hi @swasteer ,

The 502 error you’re seeing is being generated by the server at your targetUrl. The Asana webhook system is trying to establish the webhook “handshake” to verify your server, and your server is returning a 502. This could be when it sending a POST to send the X-Hook-Secret header to establish the secret to use, or sending the initial X-Hook-Signature header. In either case, Asana is expecting a 200 response from your server and it is receiving a 502 instead.

I recommend using Postman to test sending messages to your ngrok endpoint and seeing what your server is returning.

Hope this helps!

2 Likes

Thank you @David_Neal

This was the issue and i have fixed it. below is the solution that worked for me.

const express = require('express');
const bodyParser = require('body-parser');
const Asana = require('asana');

const app = express();
const PORT = 6000;
const ASANA_ACCESS_TOKEN = 'hidden';
const PROJECT_ID = 'hidden';
const WORKSPACE_ID = 'hidden';
const targetUrl =  'https://04bc-197-245-40-71.ngrok-free.app/webhooks'; 

app.use(bodyParser.json());

// Endpoint to receive webhook events and handle X-Hook-Secret
app.post('/webhooks', async (req, res) => {
  if (req.headers['x-hook-secret']) {
    // Respond to Asana's verification request
    res.set('X-Hook-Secret', req.headers['x-hook-secret']);
    res.status(200).send('OK');
  } else {
    console.log('Received Webhook Event:', JSON.stringify(req.body, null, 2));
    // Handle other webhook events here
    if (req.body.events && req.body.events.length > 0) {
      for (const event of req.body.events) {
        if (event.resource && event.resource.gid) {
          try {
            const task = await getTaskDetails(event.resource.gid);
            console.log('Task details:', task);
          } catch (error) {
            console.error('Error fetching task details:', error.message);
          }
        }
      }
    }
    res.status(200).send('OK');
  }
});

// Function to fetch task details by task ID
async function getTaskDetails(taskId) {
  let client = Asana.ApiClient.instance;
  let token = client.authentications['token'];
  token.accessToken = ASANA_ACCESS_TOKEN;

  let tasksApiInstance = new Asana.TasksApi();
  let opts = {
    task: taskId,
    opt_fields: 'name,notes,assignee,name,completed,due_on',
  };

  return tasksApiInstance.getTask(taskId, opts);
}

// Start the server
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

1 Like

Hi @swasteer,

I’m glad you got it working! It is strongly recommended you store the secret passed by the X-Hook-Secret header in the initial handshake to validate events. After the initial handshake, every webhook event includes an X-Hook-Signature header that is a hash created with the secret. Take a look at the sample Node.js app to see an example of using the crypto library to validate the webhook payload.

One thing to note, the example application stores the secret in a global variable, which will be lost when the server restarts. Your application should securely store the secret so it is persisted across server restarts. Also, keep in mind a unique secret is generated for every webhook registered.

Hope this helps!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.