Set up the WhatsApp Echo Bot

The WhatsApp Echo Bot is a sample webhook server application that echoes back to you whatever you send it. It can serve as a basic reference for how to set up webhooks and reply to incoming messages.

To test out the echo bot, we assume you have a Meta developer app with the WhatsApp product added already. Follow the getting started workflow to onboard as a developer and send your first test message.

After you send your test message, configure webhooks with the WhatsApp Echo Bot:

Configure the WhatsApp Echo Bot
Using Glitch
  1. Go to our starter webhook project on Glitch: Remix on Glitch

  2. Click Remix to edit. A new copy of the project will be created for you.

  3. Back in App Dashboard > WhatsApp > Getting Started, copy your access token from the developer portal:

  4. Save it into the .env file in the Glitch app under WHATSAPP_TOKEN.

  5. Now, set the other .env variable called VERIFY_TOKEN. This can be any string you choose. In our case, we picked "blue_panda".

  6. At this point, the .env file in the Glitch app will look like this:

  7. To get the webhook url from Glitch click the Share button (you need to be logged in to see it) copy the live site link. Make sure to append /webhook to the end of the URL.

  8. Use this URL as the Webhook URL when setting up webhooks on the Meta Developer portal (also enter matching verify token, blue_panda in our case):

  9. Click Verify and Save. Back in the Configuration screen, click Manage and subscribe to the messages webhooks field:

  10. Now, when you send a message to the API number on WhatsApp, it should send back your message in the following format "Ack: {your message}".
Using AWS Lambda

Before you start, make sure to register and sign into an AWS development account.


In AWS:
  1. Open the AWS Lambda console. AWS operates in several regional data centers and this example is set up in the US East (N. Virginia) us-east-1 region. So the actual link is https://us-east-1.console.aws.amazon.com/lambda/home.
  2. Click Create Function > Author from scratch and create your function. For this example, we have added and/or selected the following options:
    • Function name: cloudEcho
    • Runtime: Node.js 16.x, since we're implementing Javascript-based Lambda function
    • Execution role: Create a new role with basic Lambda permissions
    • Advanced Settings: Enable function URL has been checked and Auth type was set to None.
    The Advanced Settings look like this:
  3. Click Create Function.
  4. Once the function is created, you are redirected to the function page. There, you can see the following information:
    • The function's URL ending in .lambda-url.AWS_REGION.on.aws/. Save that for later use.
    • The Code source tab for that function.
  5. Inside your function's Code Source, you need to add code that does the following:
    • Only accepts GET and POST requests
    • Verifies using the GETrequest described here.
    • Replies to the message based on the message payload structure described here.
    The code sample to be copied and pasted is:
    const https = require("https");
    
    exports.handler = async (event)  => {
      const VERIFY_TOKEN = "Set_your_verify_token_value_here";
      const WHATSAPP_TOKEN = "Paste_whatsapp_access_token_here";
    
      let response;
      if (event?.requestContext?.http?.method === "GET") {
        // https://developers.facebook.com/docs/graph-api/webhooks/getting-started#verification-requests
        // to learn more about GET request for webhook verification
        let queryParams = event?.queryStringParameters;
        if (queryParams != null) {
          const mode = queryParams["hub.mode"];
          if (mode == "subscribe") {
            const verifyToken = queryParams["hub.verify_token"];
            if (verifyToken == VERIFY_TOKEN) {
              let challenge = queryParams["hub.challenge"];
              response = {
                  "statusCode": 200,
                  "body": parseInt(challenge),
                  "isBase64Encoded": false
              };
            } else {
              const responseBody = "Error, wrong validation token";
              response = {
                  "statusCode": 403,
                  "body": JSON.stringify(responseBody),
                  "isBase64Encoded": false
              };
            }
          } else {
              const responseBody = "Error, wrong mode";
              response = {
                  "statusCode": 403,
                  "body": JSON.stringify(responseBody),
                  "isBase64Encoded": false
            };
          }
        }
        else {
          const responseBody = "Error, no query parameters";
          response = {
              "statusCode": 403,
              "body": JSON.stringify(responseBody),
              "isBase64Encoded": false
          };
        }
      } else if (event?.requestContext?.http?.method === "POST") {
        // process POST request (WhatsApp chat messages)
        // https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/payload-examples#text-messages
        // to learn about WhatsApp text message payload structure
        let body = JSON.parse(event.body)
        let entries = body.entry;
        for (let entry of entries) {
          for (let change of entry.changes) {
            let value = change.value;
            if(value != null) {
              let phone_number_id = value.metadata.phone_number_id;
              if (value.messages != null) {
                for (let message of value.messages) {
                  if (message.type === 'text') {
                    let from = message.from;
                    let message_body = message.text.body;
                    let reply_message = "Ack from AWS lambda: " + message_body;
                    sendReply(phone_number_id, WHATSAPP_TOKEN, from, reply_message);
                    const responseBody = "Done";
                    response = {
                        "statusCode": 200,
                        "body": JSON.stringify(responseBody),
                        "isBase64Encoded": false
                    };
                  }
                }
              }
            }
          }
        }
      } else {
        const responseBody = "Unsupported method";
        response = {
            "statusCode": 403,
            "body": JSON.stringify(responseBody),
            "isBase64Encoded": false
        };
      }
      
      return response;
    }
    
    const sendReply = (phone_number_id, whatsapp_token, to, reply_message) => {
      let json = {
        messaging_product: "whatsapp",
        to: to,
        text: { body: reply_message },
      };
      let data = JSON.stringify(json);
      let path = "/v12.0/"+phone_number_id+"/messages?access_token="+whatsapp_token;
      let options = {
        host: "graph.facebook.com",
        path: path,
        method: "POST",
        headers: { "Content-Type": "application/json" }
      };
      let callback = (response) => {
        let str = "";
        response.on("data", (chunk) => {
          str += chunk;
        });
        response.on("end", () => {
        });
      };
      let req = https.request(options, callback);
      req.on("error", (e) => {});
      req.write(data);
      req.end();
    }
    
  6. Once you paste the code, you will see the Changes not deployed banner pop up. Do not deploy your function yet! We need to set verify token and access token before that.
In Meta for Developers:
  1. Open Meta for Developers > My Apps and select the app you have created while following the getting started workflow. Click WhatsApp > Getting started.
  2. Copy the temporary access token:
In AWS:
  1. Paste the access token into your Lambda function. Then, set up the VERIFY_TOKEN field in your Lambda function. For this example, we're using blue_panda.
  2. Click Deploy.
In Meta for Developers:
  1. Open Meta for Developers > My Apps and select the app you have created while following the getting started workflow. Click WhatsApp > Configuration > Configure a webhook.
  2. Under Callback URL, paste your Lambda function URL (this is the URL that was generated immediately after the function was created). Under Verify Token, paste the token you created after pasting your access token (for our example, we're using blue_panda):
  3. Click Verify and Save.
  4. Once verification is successful, click Manage back in the Configuration page:
  5. A new dialog module opens up with all available objects you can subscribe to. Click Subscribe for the messages object. Then, click Done.
  6. You are done setting up the echo bot! Now, when you send a message to the API number on WhatsApp, it should send back your message in the following format "Ack from AWS lambda: {your message}".