Skip to content

Facebook Messenger

Connect a Facebook Page — including the Page subscription and Development-mode traps that make a "verified" webhook stay silent.

How a Page message reaches Evoriqa through your Meta app, and the two subscriptions it needs
How a Page message reaches Evoriqa through your Meta app, and the two subscriptions it needs

What you need

A Meta developer app of type Business with the Messenger product added, and a Facebook Page you administer.

Warning:

Meta gates this channel in two places that are silent when shut, and nearly every "webhook verified but nothing arrives" setup is one of them:

  1. 1
    An app in Development mode delivers events only for people holding a role on the app or the Page.
  2. 2
    The app-level webhook subscription does nothing until the Page itself is also subscribed.

Connect

There are two separate subscriptions in Meta's dashboard, on the same screen, that look almost identical. Both are required. Steps 3 and 4 below are those two — do not stop after step 3.

  1. 1
    Meta app → Messenger → Settings → Access Tokens. Connect your Page and Generate token — that is the Page access token. The Meta App Secret is under app → Settings → Basic.
  2. 2
    In Evoriqa, open the chatbot's Channels tab → Connect a channel, pick Messenger, and fill in:

    Then press Connect Messenger. Connecting from a chatbot's Channels tab attaches the channel to that chatbot — and a channel with no chatbot attached ingests messages but never answers them, which from Messenger looks exactly like a dead integration.

    Evoriqa then shows the channel's webhook URL, unique to this channel:

    Copy it. On a custom domain, the host is your domain instead of app.evoriqa.com — use whatever the tab shows.

  3. 3
    Subscription 1 — the app. Meta app → Messenger → Settings → WebhooksAdd Callback URL. Paste the webhook URL and the same verify token, then Verify and save. Tick the webhook field messages. Leave message_echoes off — it reflects the Page's own replies back, and they are discarded at ingest anyway.
  4. 4
    Subscription 2 — the Page. The step most setups miss, and the single most common cause of a green "Verified" webhook that never fires. Still in the Webhooks panel, scroll to the Page list below the callback URL. Your Page has its own Webhook Subscription column with an Add subscriptions (or Edit) control — open it and tick messages there as well.

    Step 3 subscribes the app to the field. Step 4 subscribes the Page to the app. Until both are set, Meta never calls the webhook at all — with no error surfaced anywhere.

Confirm the Page subscription

The API equivalent of step 4, if you would rather not trust the UI:

A subscribed Page answers with your Meta app listed, messages among its fields (name and id here are the app's, not the Page's):

An empty "data": [] means step 4 was never done — subscribe with:

Note:

Both of those calls need the pages_manage_metadata permission, which a plain messaging token does not carry. If you get:

nothing is broken — the token is valid (a broken token returns code 190), it just cannot read that endpoint. Either use the dashboard for step 4, or mint a token with pages_manage_metadata added in Graph API Explorer for the check and discard it afterwards. Evoriqa itself only ever needs pages_messaging.

Connect with the API

`POST /channels` takes the same three fields as the form, in a config object. All three are required — omit one and the call fails 422 naming it:

In production the Page access token is checked against the Graph API before the channel is created, so a wrong or expired token fails here rather than at the first inbound message. Add "graphVersion": "v27.0" to pin a Graph version for this channel. The response returns the inbound secret once — it is what authenticates Meta's webhook calls.

Verify it works

Message the Page from an account that holds a role on the app (App roles → add yourself as Admin, Developer, or Tester) or on the Page — and not from the Page's own identity. While the app is in Development mode, Meta silently drops events from everyone else.

The Messenger connect form: app secret, verify token and Page access token
The Messenger connect form: app secret, verify token and Page access token

The conversation should appear in the Inbox tagged Messenger. Inbound requests are verified with x-hub-signature-256 against the app secret. Images, files, and stickers arrive as attachments with their CDN links.

The channel row on the chatbot's Channels tab carries a health chip showing the last message received and the last one rejected. It splits any problem in one look: nothing received means Meta is not calling you (steps 3 and 4); rejected means Meta is calling and the app secret is wrong; received but unanswered means the reply failed, not the webhook.

Test the webhook without Meta

To prove the inbound path independently of Meta's delivery, post a signed payload yourself — the same x-hub-signature-256 scheme Meta uses. Fill in your app secret and the webhook URL Evoriqa gave you in step 2:

A healthy channel answers:

That message now sits in your Inbox as a real Messenger thread, and the AI answers it — so everything on the Evoriqa side works and any remaining problem is Meta's subscriptions. (The AI's reply is sent to sender id 7391045826113947, which Meta rejects as an unknown PSID — expected for a synthetic test.)

A 403 instead means the App Secret stored on the channel is wrong — it comes from app → Settings → Basic, and is not the App ID:

Before real customers can message you

The app must be switched to Live and granted Advanced Access to pages_messaging through Meta's App Review, which requires business verification. Until then the channel works only for app and Page roles — enough for a pilot, not for launch.

Testing locally

On app.evoriqa.com this section does not apply — skip to Troubleshooting. It is for self-hosted deployments running Evoriqa on a developer machine.

Meta will not call localhost. Put a tunnel (cloudflared, ngrok) in front of the dev server and point APP_URL at the tunnel origin, because the webhook URL shown at connect time is built from it — a stale value hands Meta an address it cannot reach and the step 3 handshake fails.

Quick tunnels hand out a new hostname every restart. When that happens, the callback URL Meta holds points at a host that no longer exists and delivery stops silently — update APP_URL, restart both the server and the worker, then re-enter the new callback URL in step 3.

Troubleshooting

Where to go next

Last updated