Close Menu
GeekBlog

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    Instagram Already Has an Off Switch for the Algorithm. It Resets Every Time You Close the App.

    September 12, 2026

    Anthropic Banned Five Groups of Working Scientists. It Says It Cannot Prove Any of Them Meant Harm.

    September 12, 2026

    Google Made Its Best Paid Gemini Feature Free. The Price Is Access to Your Inbox.

    September 12, 2026
    Facebook X (Twitter) Instagram Threads
    GeekBlog
    • Home
    • Mobile
    • Tech News
    • Blog
    • Gaming
    • Smartwatch
    • How-To Guides
    • AI & Software
    Facebook
    GeekBlog
    Home»Blog»How to Integrate Facebook Messenger Into Your App (Webhooks, Send API, App Review)
    Blog

    How to Integrate Facebook Messenger Into Your App (Webhooks, Send API, App Review)

    Ethan CaldwellBy Ethan CaldwellSeptember 9, 202612 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Email Copy Link
    Messaging application open on a phone for Facebook Messenger app integration
    Share
    Facebook Twitter LinkedIn Pinterest Email Copy Link

    To integrate Facebook Messenger into your app, you create a Meta app, connect it to a Facebook Page, subscribe a webhook to that Page’s messaging events, and reply through the Send API using a Page access token. That is the whole loop: Meta pushes incoming messages to your server, and your server pushes replies back. Everything else (quick replies, templates, m.me links, app review) is built on top of those four pieces.

    Quick answer: Create an app at developers.facebook.com, add the Messenger product, generate a Page access token with pages_messaging, register an HTTPS webhook subscribed to messages and messaging_postbacks, then POST replies to https://graph.facebook.com/v21.0/me/messages. Test with app admins, then submit for App Review before the public can message you.

    This guide walks through the Messenger Platform as it works today, including one thing that trips up a lot of teams: the old Customer Chat plugin for websites has been retired, so the “embed a chat bubble” approach you may remember no longer works the way it did. If you are also wiring up Facebook sign in for the same app, the Facebook Login integration guide covers that side, and the API authentication guide explains tokens in more depth.

    How the Messenger Platform is wired

    Messenger integrations always run through a Facebook Page, never through a personal profile. Users message the Page, Meta delivers those events to your webhook, and your app answers as the Page. You need three things registered in the Meta developer dashboard:

    • A Meta app of type Business with the Messenger product added.
    • A Facebook Page you administer, connected to that app in the Messenger settings panel.
    • A Page access token that carries the pages_messaging permission. This is the credential you send with every Send API call.

    Access tokens come in short lived and long lived flavors. For a production bot, generate a System User token in Business Manager or exchange a user token for a long lived Page token so you are not rotating credentials every hour. Store it as an environment variable, never in client code, because a Page token lets the holder send messages as your business.

    Warning: Messenger is a server to server integration. Never call the Send API from a mobile app or browser with an embedded Page token. Route everything through your own backend.

    Step 1: Create the app and connect the Page

    In the developer dashboard, choose Create App, pick the Business use case, and add Messenger from the product list. Under Messenger, Messenger API Settings, click Add or Remove Pages, authorize your Page, and click Generate Token next to it. Copy the token to a safe place.

    While you are in that panel, note the App ID and App Secret from App Settings, Basic. The secret is used to validate the X-Hub-Signature-256 header on every webhook delivery, which is how you know a request really came from Meta.

    Step 2: Build and verify the webhook

    Meta will only talk to a publicly reachable HTTPS endpoint with a valid certificate. During development, a tunnel such as ngrok or Cloudflare Tunnel is the usual answer. The webhook has two jobs: answer a one time GET verification challenge, and accept POST deliveries of events.

    Here is a minimal Node and Express webhook that handles verification, checks the signature, and echoes text messages back:

    import express from "express";
    import crypto from "crypto";
    
    const app = express();
    const VERIFY_TOKEN = process.env.VERIFY_TOKEN;
    const PAGE_TOKEN = process.env.PAGE_ACCESS_TOKEN;
    const APP_SECRET = process.env.APP_SECRET;
    const GRAPH = "https://graph.facebook.com/v21.0";
    
    app.use(express.json({ verify: (req, res, buf) => { req.rawBody = buf; } }));
    
    // Webhook verification (one time, when you register the URL)
    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 === VERIFY_TOKEN) return res.status(200).send(challenge);
      return res.sendStatus(403);
    });
    
    function validSignature(req) {
      const header = req.get("x-hub-signature-256") || "";
      const expected = "sha256=" + crypto.createHmac("sha256", APP_SECRET).update(req.rawBody).digest("hex");
      return header.length === expected.length && crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
    }
    
    async function send(psid, message) {
      await fetch(`${GRAPH}/me/messages?access_token=${PAGE_TOKEN}`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ recipient: { id: psid }, messaging_type: "RESPONSE", message })
      });
    }
    
    // Event delivery
    app.post("/webhook", async (req, res) => {
      if (!validSignature(req)) return res.sendStatus(401);
      res.sendStatus(200); // ack fast, Meta retries slow endpoints
      if (req.body.object !== "page") return;
      for (const entry of req.body.entry) {
        for (const ev of entry.messaging || []) {
          const psid = ev.sender.id;
          if (ev.message && ev.message.text) {
            await send(psid, { text: `You said: ${ev.message.text}` });
          } else if (ev.postback) {
            await send(psid, { text: `Postback: ${ev.postback.payload}` });
          }
        }
      }
    });
    
    app.listen(3000);

    Recommended for you:

    How to Use the TikTok for Developers Documentation
    Blog·Sep 9, 2026

    How to Use the TikTok for Developers Documentation

    Back in the dashboard, under Messenger, Webhooks, enter your public URL plus /webhook and the same verify token you set in the environment. Then subscribe the Page to the messages and messaging_postbacks fields. You can also subscribe from the command line:

    curl -X POST "https://graph.facebook.com/v21.0/me/subscribed_apps" \
      -d "subscribed_fields=messages,messaging_postbacks,messaging_optins" \
      -d "access_token=$PAGE_ACCESS_TOKEN"
    Tip: Return a 200 within a few seconds and do the real work asynchronously. Meta counts slow or failing webhooks against your app and will eventually pause deliveries.

    Step 3: Send richer messages

    The Send API accepts more than plain text. The message object in the snippet above can carry quick replies, attachments, and structured templates.

    Quick replies

    Quick replies are tappable chips under a message. Up to 13 are allowed, each with a title and a payload that comes back to your webhook as message.quick_reply.payload:

    {
      "recipient": { "id": "<PSID>" },
      "messaging_type": "RESPONSE",
      "message": {
        "text": "What do you need help with?",
        "quick_replies": [
          { "content_type": "text", "title": "Order status", "payload": "ORDER_STATUS" },
          { "content_type": "text", "title": "Returns", "payload": "RETURNS" },
          { "content_type": "user_phone_number" }
        ]
      }
    }

    Templates

    Templates render cards with images, titles and buttons. The generic template is the workhorse; the button template is a text bubble with up to three buttons. Buttons can be postback (sends a payload to you) or web_url (opens a link).

    {
      "recipient": { "id": "<PSID>" },
      "message": {
        "attachment": {
          "type": "template",
          "payload": {
            "template_type": "generic",
            "elements": [{
              "title": "Order #10422",
              "subtitle": "Shipped, arriving Thursday",
              "image_url": "https://example.com/box.png",
              "buttons": [
                { "type": "web_url", "url": "https://example.com/track/10422", "title": "Track" },
                { "type": "postback", "title": "Contact support", "payload": "SUPPORT_10422" }
              ]
            }]
          }
        }
      }
    }

    Message types and the 24 hour window

    Every send carries a messaging_type. Use RESPONSE for replies inside the standard 24 hour window after the user last messaged you, UPDATE for proactive follow ups inside that window, and MESSAGE_TAG with an approved tag (for example CONFIRMED_EVENT_UPDATE or POST_PURCHASE_UPDATE) for the narrow set of cases allowed outside it. Marketing outside the window is not one of those cases. The full rules live in the Messenger Platform Send API documentation.

    Entry points: m.me links, buttons and the retired Chat Plugin

    Once the webhook works, you need a way for people to start a conversation. The simplest is an m.me link, which opens Messenger to your Page on any device:

    https://m.me/YOUR_PAGE_USERNAME?ref=pricing_page
    
    <!-- inside your web page or app -->
    <a href="https://m.me/YOUR_PAGE_USERNAME?ref=pricing_page">Chat with us on Messenger</a>

    The ref parameter arrives in your webhook as a referral event (or inside the first postback if you have a Get Started button configured), which lets you tailor the opening message by where the user came from. On mobile apps, open the same URL with the platform’s default link handler and Messenger takes over.

    What about the Customer Chat plugin, the embeddable chat window that used to sit in the corner of a website? Meta’s developer documentation for the plugin now states that as of May 9, 2024 the plugin’s functionality is no longer accessible, and guest mode was removed before that. We verified this directly against Meta’s Chat Plugin documentation. If you have an old fb-customerchat snippet in your site, remove it and switch to m.me links, a Send to Messenger button, or a hosted chat widget of your own that hands off to Messenger.

    Set up a Get Started button and persistent menu

    The Messenger Profile API configures the first touch experience. One call sets the Get Started payload, a greeting, and a persistent menu:

    curl -X POST "https://graph.facebook.com/v21.0/me/messenger_profile?access_token=$PAGE_ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "get_started": { "payload": "GET_STARTED" },
        "greeting": [{ "locale": "default", "text": "Hi {{user_first_name}}, ask us anything." }],
        "persistent_menu": [{
          "locale": "default",
          "composer_input_disabled": false,
          "call_to_actions": [
            { "type": "postback", "title": "Track an order", "payload": "TRACK" },
            { "type": "web_url", "title": "Visit site", "url": "https://example.com" }
          ]
        }]
      }'

    Permissions, App Review and going live

    While the app is in Development mode, only people with a role on the app (admins, developers, testers) can message it. To reach the public you must switch to Live mode, and that requires App Review approval for pages_messaging. Meta also requires Business Verification for most messaging permissions. Prepare a short screencast showing the user flow, a clear description of what the bot does, and a privacy policy URL, because incomplete submissions are the most common reason for rejection.

    Permission or featureWhat it unlocksNeeds App Review
    pages_messagingSend and receive messages as the PageYes, plus Business Verification
    pages_manage_metadataSubscribe the Page to webhook fieldsYes
    Human Agent tagReply up to 7 days after the last user message when a person answersYes, separate feature request
    Handover ProtocolPass threads between your bot and the Page InboxNo, configured in Messenger settings

    Sharing the inbox with humans

    Most businesses do not want a bot to own every conversation. The Handover Protocol lets your app be the Primary Receiver and pass a thread to the Page Inbox in Meta Business Suite when a customer asks for a person. Your webhook receives pass_thread_control and take_thread_control events so you know who currently owns the conversation. The reverse works too: an agent in the Business Suite inbox can hand the thread back to your bot.

    Troubleshooting

    Webhook verification fails with 403

    The verify token you typed in the dashboard does not match the one your server compares against, or your server is returning the challenge with extra characters. Echo hub.challenge exactly, as plain text, with a 200 status.

    Messages arrive from admins but not from other people

    The app is still in Development mode. Until App Review approves pages_messaging and you flip the app to Live, only users with an app role can trigger events.

    Send API returns error code 10 or 200

    Recommended for you:

    How to Use Regular Expressions in Jinja2
    Blog·Sep 9, 2026

    How to Use Regular Expressions in Jinja2

    Error 10 usually means you are outside the 24 hour window without a valid tag, or the permission has not been granted. Error 200 typically points to a token that lacks the required scope. Regenerate the Page token after adding permissions, because scopes are baked into the token at generation time.

    Signature check keeps failing

    You are hashing a re serialized body instead of the raw bytes. Capture the raw request body before JSON parsing, as the Express example above does with the verify hook.

    The old chat bubble disappeared from the website

    That is the retired Customer Chat plugin. There is no fix beyond replacing it with an m.me link, a Send to Messenger button, or your own widget. See the Messenger basics guide if you need to explain the change to nontechnical stakeholders.

    Frequently asked questions

    Can I integrate Messenger without a Facebook Page?

    No. Every Messenger Platform integration is anchored to a Facebook Page, and all messages are sent and received as that Page. If your product has no Page yet, create one first, then connect it to the app in the Messenger settings panel and generate the Page access token.

    Is there a cost to use the Messenger Platform?

    The API itself is free to use for standard messaging within the 24 hour window and with approved message tags. Paid options exist for certain marketing messages, and Meta adjusts those programs over time, so check the current Messenger Platform policy pages before planning a campaign that depends on them.

    How do I test before App Review approves the app?

    Add teammates as testers or developers under App Roles, then have them message the Page from their own Facebook accounts. Events flow to your webhook exactly as they will in production. You can also send test payloads manually with curl using the Page token and a known PSID.

    What is a PSID and why does it differ from a user ID?

    A Page Scoped ID identifies a user only in the context of one Page. The same person gets a different PSID for each Page they message, and it is not the same as their Facebook Login user ID. If you need to link the two, use the ID matching API that Meta provides for businesses.

    Does the Customer Chat plugin still work on websites?

    Meta’s own documentation states that the Chat Plugin’s functionality became inaccessible on May 9, 2024. Existing snippets no longer render a working chat window. Replace them with m.me links or a Send to Messenger button, both of which open the conversation in Messenger itself.

    The bottom line

    A Messenger integration is a small amount of plumbing: a Page token, a verified HTTPS webhook, and a Send API client. Once the echo bot in this article runs, adding quick replies, templates and a persistent menu is mostly a matter of sending different JSON.

    Budget real time for App Review and Business Verification, and plan for a human handoff from day one. Those two items, not the code, are what usually decide whether a Messenger project ships on schedule.

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Telegram Email Copy Link
    Previous ArticleHow to Filter Posts in WordPress by Category (WP_Query, pre_get_posts, REST API and Blocks)
    Next Article How to Access a Minikube Service From Outside the Cluster
    Ethan Caldwell

      Ethan Caldwell is GeekBlog's resident Apple specialist, covering the entire Apple ecosystem - iPhone, iPad, Mac, Apple Watch, AirPods and the software that ties them together. A longtime iOS user and gadget collector, Ethan tracks Cupertino's every move, breaking down Apple keynotes, A- and M-series chip benchmarks, iOS feature updates and the rumor mill into clear, practical takes that help readers decide whether the latest Apple hardware is worth the upgrade.

      Related Posts

      11 Mins Read

      South Carolina vs Michigan: Which State Is Better to Live In?

      11 Mins Read

      Are There Cordless Vacuums With Replaceable Batteries?

      12 Mins Read

      How to Use Parabolic SAR (Stop and Reverse) for Day Trading

      10 Mins Read

      Michigan vs Illinois: Which State Is Better to Live In?

      11 Mins Read

      California or Florida: Which State Is Better to Move To?

      11 Mins Read

      Best Front End Development Books to Learn From in 2026

      Top Posts

      How to Use YouTube: A Beginner’s Guide

      July 7, 20265 Views

      Gal Gadot’s Lawyers Spent Six Months on One AI Clause. Then SAG Called Them for Pointers.

      September 2, 20264 Views

      Every iPhone Camera Ranked in 2026 (Best to Worst)

      July 6, 20263 Views
      Stay In Touch
      • Facebook

      Subscribe to Updates

      Get the latest tech news from FooBar about tech, design and biz.

      Most Popular

      How to Change HEIC to JPG on iPhone, Mac, Android and Windows (No Software Needed)

      September 3, 20266 Views

      Gal Gadot’s Lawyers Spent Six Months on One AI Clause. Then SAG Called Them for Pointers.

      September 2, 20265 Views

      How to Spot AI Generated Images in 2026 (The Old Tricks Stopped Working)

      September 3, 20263 Views
      Our Picks

      Instagram Already Has an Off Switch for the Algorithm. It Resets Every Time You Close the App.

      September 12, 2026

      Anthropic Banned Five Groups of Working Scientists. It Says It Cannot Prove Any of Them Meant Harm.

      September 12, 2026

      Google Made Its Best Paid Gemini Feature Free. The Price Is Access to Your Inbox.

      September 12, 2026

      Subscribe to Updates

      Get the latest creative news from FooBar about art, design and business.

      HEICJPG.online - Convert HEIC to JPG online
      Facebook
      • About Us
      • Contact us
      • Privacy Policy
      • Disclaimer
      • Terms and Conditions
      • Editorial Policy
      • Cookie Policy
      © 2026 GeekBlog

      Type above and press Enter to search. Press Esc to cancel.