Creating a Webhook Callback for Meta's WhatsApp API Using a Coda Pack

Hi community,

I’m trying to implement a webhook callback for the Meta (WhatsApp Business) API directly within a Coda pack. Currently, I have a working solution on Glitch that uses an Express server to receive incoming WhatsApp messages and automatically save them to a table in Coda.

Here’s how the flow works on Glitch:

  1. Meta sends a POST request to the server’s endpoint whenever a new WhatsApp message is received.
  2. The server verifies the message, extracts the text, and sends it to a table in Coda via Coda’s API.
  3. The server responds with a 200 OK status code to confirm the webhook reception.

My goal is to replicate this flow within a Coda pack, eliminating the need for an external server like Glitch. Specifically, the pack should:

  • Configure a webhook with Meta’s API to receive messages.
  • Extract relevant data from the message (sender, text, timestamp, etc.).
  • Automatically sync the data into a Coda table.

Here’s the current code I’m using in Glitch:

import express from "express";
import axios from "axios";

const app = express();
app.use(express.json());

const { WEBHOOK_VERIFY_TOKEN, GRAPH_API_TOKEN, CODA_API_TOKEN, CODA_DOC_ID, PORT } = process.env;

// POST route to handle incoming WhatsApp messages
app.post("/webhook", async (req, res) => {
  console.log("Incoming webhook message:", JSON.stringify(req.body, null, 2));

  const message = req.body.entry?.[0]?.changes?.[0]?.value?.messages?.[0];
  
  // Verify that the message type is "text"
  if (message?.type === "text") {
    const messageBody = message.text.body; // Extract the message text

    try {
      // Send the message to the Coda table
      await axios({
        method: "POST",
        url: `https://coda.io/apis/v1/docs/${CODA_DOC_ID}/tables/Registro_Mensajes/rows`,
        headers: {
          Authorization: `Bearer ${CODA_API_TOKEN}`,
          "Content-Type": "application/json",
        },
        data: {
          rows: [
            {
              cells: [
                {
                  column: "Mensajes",
                  value: messageBody,
                },
              ],
            },
          ],
        },
      });
      console.log("Message saved to Coda:", messageBody);
    } catch (error) {
      console.error("Error saving the message to Coda:", error.response?.data || error.message);
    }
  }

  // Respond to WhatsApp with a 200 status code to confirm the webhook
  res.sendStatus(200);
});

// GET route for initial webhook verification
app.get("/webhook", (req, res) => {
  const mode = req.query["hub.mode"];
  const token = req.query["hub.verify_token"];
  const challenge = req.query["hub.challenge"];

  if (mode === "subscribe" && token === WEBHOOK_VERIFY_TOKEN) {
    res.status(200).send(challenge);
    console.log("Webhook verified successfully!");
  } else {
    res.sendStatus(403);
  }
});

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

Variable Breakdown:

  1. WEBHOOK_VERIFY_TOKEN: A token used to verify that the webhook request comes from Meta. It is compared with the value sent by Meta during the webhook setup.
  2. GRAPH_API_TOKEN: The access token for Meta’s API that authorizes requests to WhatsApp endpoints.
  3. CODA_API_TOKEN: The access token for Coda’s API to allow writing data to a specific table.
  4. CODA_DOC_ID: The ID of the Coda document containing the tables where the messages are stored.
  5. PORT: The port on which the Express server runs. Defaults to port 3000 if not defined.

Questions for the Community:

  1. Is it possible to replicate this flow directly in a Coda pack?
  2. How can I set up the pack to receive webhook callbacks, process them, and sync the data into a Coda table?
  3. Are there any examples of webhook setups in a Coda pack that I can use as a reference?

Any guidance or suggestions would be greatly appreciated. Thanks in advance! :blush:

Hello @Jose_Manuel_Canadas

You can set up an automation in your Coda doc using a webhook trigger. This will generate a URL and API token that you can use with the Meta endpoint. The Coda automation receives a JSON payload, which can be decoded directly to populate any table in your doc.

Let me know if this approach meets your needs.

Best regards,
Arnhold

2 Likes

As @Felipe_Arnhold has pointed, you don’t need a pack to receive a Webhook-triggered automation and packs are not meant for that. But you do need to authenticate the webhook before sending it to Coda. If you can’t set up a bearer authentication within Meta , you can’t eliminate the middleman.