IntegrationsAdvanced

How to Connect AI to WhatsApp With the Meta Cloud API

Set up the official WhatsApp Cloud API, verify a webhook, and reply with AI through the Graph API.

12 minAdvanced

The WhatsApp Cloud API is Meta's official, free-to-start path with no middleman. It is more setup than Twilio but it is what you ship to production. This guide covers the test number, webhook verification, and sending an AI reply back through the Graph API.

What you need

  • A Meta developer account and a Business app at developers.facebook.com
  • The WhatsApp product added to that app
  • A public HTTPS endpoint (ngrok works for testing)
  • An AI API key and Node 18+

Step 1: Grab the test credentials

In the app dashboard open WhatsApp > API Setup. Meta gives you a temporary access token, a test phone number id, and a field to add recipient numbers. Add your own number and send the sample template to confirm delivery works.

Meta for Developers - WhatsApp API Setup
Temporary access token: EAAG...... (expires in 24h)
Phone number ID: 123456789012345
Test recipients: +1 555 010 1234 [verified]
Note the Phone number ID, you will need it to send messages.

Step 2: Verify the webhook

Meta verifies your webhook with a GET request carrying hub.challenge and a verify token you choose. Echo the challenge back when the token matches. Inbound messages then arrive as POST requests.

server.js
import "dotenv/config";
import express from "express";
import OpenAI from "openai";

const ai = new OpenAI();
const app = express();
app.use(express.json());

const VERIFY = process.env.VERIFY_TOKEN;

app.get("/webhook", (req, res) => {
  if (
    req.query["hub.mode"] === "subscribe" &&
    req.query["hub.verify_token"] === VERIFY
  ) {
    return res.send(req.query["hub.challenge"]);
  }
  res.sendStatus(403);
});

app.listen(3000, () => console.log("up on :3000"));
Use the same token in two places
The verify token in your code must exactly match the one you type into the Meta webhook config screen. A mismatch is the number one reason verification fails.

Step 3: Handle inbound and reply

Inbound messages are buried in entry[0].changes[0].value.messages. Pull the text and the sender, run the model, then POST to the Graph API messages endpoint to reply.

server.js (continued)
app.post("/webhook", async (req, res) => {
  res.sendStatus(200); // ack fast

  const value = req.body.entry?.[0]?.changes?.[0]?.value;
  const msg = value?.messages?.[0];
  if (!msg) return;

  const out = await ai.chat.completions.create({
    model: "gpt-5-mini",
    messages: [{ role: "user", content: msg.text.body }],
  });

  await fetch(
    `https://graph.facebook.com/v20.0/${process.env.PHONE_ID}/messages`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.WA_TOKEN}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        messaging_product: "whatsapp",
        to: msg.from,
        text: { body: out.choices[0].message.content },
      }),
    },
  );
});
The 24 hour window
You can only send free-form replies within 24 hours of the user's last message. Outside that window you must use a pre-approved message template.

Step 4: Point Meta at your tunnel

zsh - whatsapp-cloud
$ngrok http 3000
Forwarding https://x9y8z7.ngrok.io -> localhost:3000
Callback URL: https://x9y8z7.ngrok.io/webhook
Then subscribe to the 'messages' field
$

Result

Messages to your test number now return AI answers through Meta's official pipeline. Replace the temporary token with a permanent System User token and register your own number to move beyond testing.

Watch related tutorials

Tags
#whatsapp#cloud-api#meta#webhook#ai