Meta Webhooks for Messenger Platform |
Meta Webhooks allows you to receive real-time HTTP notifications of changes to specific objects in the Meta social graph. For example, we could send you a notification when a person sends your Facebook Page or Instagram Professional account a message. Webhooks notifications allow you to track incoming messages and message status updates. Webhooks notifications also allow you to avoid rate limits that would occur if you were querying the Messenger Platform endpoints to track these changes.
To successfully implement Webhooks for Messenger or Instagram conversations, you will need to:
Before you start we assume you have:
Your server must be able to process two types of HTTPS requests: Verification Requests and Event Notifications. Since both requests use HTTPs, your server must have a valid TLS or SSL certificate correctly configured and installed. Self-signed certificates are not supported.
The sections below explain what will be in each type of request and how to respond to them.
The code samples shown here are taken from our sample app located on GitHub . Visit GitHub to see the complete example and more information about setting up your webhooks server.
To create an endpoint to receive webhooks notifications from the Messenger Platform, the app.js
file may look like the follow:
// Create the endpoint for your webhook app.post("/webhook", (req, res) => { let body = req.body; console.log(`\u{1F7EA} Received webhook:`); console.dir(body, { depth: null }); ...
This code creates a /webhook
endpoint that accepts POST
requests and checks that the request is a webhook notification.
200 OK
responseThe endpoint must return a 200 OK
response, which tells the Messenger Platform the event has been received and does not need to be resent. Normally, you will not send this response until you have completed processing the notification.
Your endpoint should respond to all notifications:
200 OK HTTPS
responseThe following code will be in the app.post
in your app.js
file and may look like the following:
... // Send a 200 OK response if this is a page webhook if (body.object === "page") { // Returns a '200 OK' response to all requests res.status(200).send("EVENT_RECEIVED"); ... // Determine which webhooks were triggered and get sender PSIDs and locale, message content and more. ... } else { // Return a '404 Not Found' if event is not from a page subscription res.sendStatus(404); } });
Anytime you configure the Webhooks product in your App Dashboard, we'll send a GET
request to your endpoint URL. Verification requests include the following query string parameters, appended to the end of your endpoint URL. They will look something like this:
GET https://www.your-clever-domain-name.com/webhooks? hub.mode=subscribe& hub.verify_token=mytoken& hub.challenge=1158201444
Whenever your endpoint receives a verification request, it must:
hub.verify_token
value matches the string you set in the Verify Token field when you configure the Webhooks product in your App Dashboard (you haven't set up this token string yet).hub.challenge
value.Your app.js
file may look like the following:
// Add support for GET requests to our webhook app.get("/messaging-webhook", (req, res) => { // Parse the query params let mode = req.query["hub.mode"]; let token = req.query["hub.verify_token"]; let challenge = req.query["hub.challenge"]; // Check if a token and mode is in the query string of the request if (mode && token) { // Check the mode and token sent is correct if (mode === "subscribe" && token === config.verifyToken) { // Respond with the challenge token from the request console.log("WEBHOOK_VERIFIED"); res.status(200).send(challenge); } else { // Respond with '403 Forbidden' if verify tokens do not match res.sendStatus(403); } } });
Parameter | Sample Value | Description |
---|---|---|
|
| This value will always be set to |
|
| An |
|
| A string that that we grab from the Verify Token field in your app's App Dashboard. You will set this string when you complete the Webhooks configuration settings steps. |
Note: PHP converts periods (.) to underscores (_) in parameter names .
If you are in your App Dashboard and configuring your Webhooks product (and thus, triggering a Verification Request), the dashboard will indicate if your endpoint validated the request correctly. If you are using the Graph API's /app/subscriptions
endpoint to configure the Webhooks product, the API will respond with success or failure.
When you configure your Webhooks product, you will subscribe to specific fields
on an object
type (for example, the messages
field on the page
object). Whenever there's a change to one of these fields, we will send your endpoint a POST
request with a JSON payload describing the change.
For example, if you subscribed to the page
object's message_reactions
field and a customer reacted to a message your app sent, we would send you a POST
request that would look something like this:
{ "object":"page", "entry":[ { "id":"{PAGE_ID}", "time":1458692752478, "messaging":[ { "sender":{ "id":"{PSID}" }, "recipient":{ "id":"{PAGE_ID}" }, ... } ] } ] }
Payloads will contain an object describing the change. When you configure the webhooks product, you can indicate if payloads should only contain the names of changed fields, or if payloads should include the new values as well.
We format all payloads with JSON, so you can parse the payload using common JSON parsing methods or packages.
We do not store any Webhook event notification data that we send you, so be sure to capture and store any payload content that you want to keep.
We sign all Event Notification payloads with a SHA256 signature and include the signature in the request's 'X-Hub-Signature-256' header, preceded with 'sha256='. You don't have to validate the payload, but you should and we strongly recommend that you do.
To validate the payload:
X-Hub-Signature-256
header (everything after sha256=
). If the signatures match, the payload is genuine.Please note that we generate the signature using an escaped unicode version of the payload, with lowercase hex digits. If you just calculate against the decoded bytes, you will end up with a different signature. For example, the string äöå
should be escaped to \u00e4\u00f6\u00e5
.
The app.js
file may look like the following:
// Import dependencies and set up http server const express = require("express"), bodyParser = require("body-parser"), { urlencoded, json } = require("body-parser"), app = express().use(bodyParser.json()); ... // Verify that the callback came from Facebook. function verifyRequestSignature(req, res, buf) { var signature = req.headers["x-hub-signature-256"]; if (!signature) { console.warn(`Couldn't find "x-hub-signature-256" in headers.`); } else { var elements = signature.split("="); var signatureHash = elements[1]; var expectedHash = crypto .createHmac("sha256", config.appSecret) .update(buf) .digest("hex"); if (signatureHash != expectedHash) { throw new Error("Couldn't validate the request signature."); } } }
If a notification sent to your server fails, we will immediately try a few more times. Your server should handle deduplication in these cases. If, after 15 minutes, we are still unable to devliver notifications, an alert is sent to your developer account.
If delivery of a notification continues to fail for 1 hour, you will receive a Webhooks Disabled alert, and your app will be unsubscribed from the webhooks for the Page or Instagram Professional account. Once you have fixed the issues you will need to subscribe to the Webhooks again.
To test your webhook verification run the following cURL request with your verify token:
curl -X GET "localhost:1337/webhook?hub.verify_token=YOUR-VERIFY-TOKEN&hub.challenge=CHALLENGE_ACCEPTED&hub.mode=subscribe"
If your webhook verification is working as expected, you should see the following:
WEBHOOK_VERIFIED
logged to the command line where your node process is running.CHALLENGE_ACCEPTED
logged to the command line where you sent the cURL request.To test your webhook send the following cURL request:
curl -H "Content-Type: application/json" -X POST "localhost:1337/webhook" -d '{"object": "page", "entry": [{"messaging": [{"message": "TEST_MESSAGE"}]}]}'
If your webhook is working as expected, you should see the following:
TEST_MESSAGE
logged to the command line where your node process is running.EVENT RECEIVED
logged to the command line where you sent the cURL request.Once your webhooks server endpoint, or sample app is ready, go to your app's App Dashboard to subscribe to Meta Webhooks.
In this example we will use the dashboard to configure a Webhook and subscribe to the messages
field. Any time a customer sends your app a message, a notification will be sent to your webhooks endpoint.
Enter your endpoint's URL in the Callback URL field and add your verification token to the Verify Token field. We will include this string in all Verification Requests. If you are using one of our sample apps, this should be the same string you used for your app's TOKEN
config variable.
The last step is to subscribe to individual fields. Subscribe to the messages
field and send a test Event Notification.
If your endpoint is set up correctly, it should validate the payload and execute whatever code you have set it up to do upon successful validation. If you are using our sample app, load the app's URL in your web browser. It should display the payload's contents.
You can change your Webhooks subscriptions, verify token, or API version at any time using the App Dashboard.
Note: It is recommended that you use the latest API version to receive all information available for each webhook.
You can also do this programmatically by using the
/app/subscriptions
endpoint
.
Messaging Webhooks Field | Description |
---|---|
| A notification is sent when a message that was sent by your business has been delivered to a customer. Only available for Messenger conversations. |
| A notification is sent when your business has sent a message. This separate webhook field is available only for Messenger conversations. For Instagram Messaging conversations, the message echo notifications are included with the |
| A notification is sent when a customer edits a previously-sent message. Only availalbe for Messenger conversations. |
| A notification is sent when a customer reacts to a message sent by your business. |
| A notification is sent when a customer reads a message sent by your business, for Messenger conversations. See |
| A notification is sent when your business has received a message from a customer from any conversation entry point. For Instagram Messaging, this subscription will also include notifications when your Instagram Professional account has sent a message since there is no separate |
| A notification is sent when a customer links or unlinks their Messenger account from their account with your business. Only available for Messenger conversations. |
| A notification is sent when a person has submitted feedback for your business. Only available for Messenger conversations. |
| A notification is sent when a person has played a round of an Instant Game. Only available for Messenger conversations. |
| A notification is sent when a change has occurred during the Handover Protocol |
| A notification is sent when a customer has clicked a Messenger plugin, accepted a message request using customer matching, or has opted in to receive messages via the checkbox plugin. Only available for Messenger conversations. |
| A notification is sent when a policy enforcement warning has been sent or a policy enforcement action has been taken on the app associated with the Page. |
| A notification is sent when a customer clicks a postback button, Get Started button, or persistent menu item for Messenger conversations or an Icebreaker option or Generic Template button for Instagram Messaging conversations. |
| A notification is sent when a customer resumes a conversation with the Page by clicking an ig.me or m.me link, an ad or chat plugin. |
| A notification is sent when a customer reads a message sent by your business, for Instagram Messaging conversations. See |
| A notification is sent when a customer provides feedback on a message sent by your business by clicking the feedback buttons. |
| A notification is sent when your business has received a message from a customer, when the message contains cart/order information. Only available for Messenger conversations. |
| A notification is sent when a conversation is idle for an app during the Handover Protocol |
You will need to connect your Webhooks app to your Page and subscribe your Page to the Webhooks notifications you want to receive.
You can connect an app to a Page in the Meta Business Suite > All Tools > Business Apps
Note: You will need to subscribe all messaging apps for your business to the messaging webhooks.
You will need to subscribe your Page to the Webhooks notifications you want to receive.
MODERATE
task
on the Page being queried
To subscribe to a Webhooks field, send a POST
request to the Page's subscribed_apps edge using the Page's acccess token.
curl -i -X POST "https://graph.facebook.com/PAGE-ID/subscribed_apps ?subscribed_fields=messages &access_token=PAGE-ACCESS-TOKEN"
{ "success": "true" }
To see which app's your Page has installed, send a GET
request instead:
curl -i -X GET "https://graph.facebook.com/PAGE-ID/subscribed_apps &access_token=PAGE-ACCESS-TOKEN"
{ "data": [ { "category": "Business", "link": "https://my-clever-domain-name.com/app", "name": "My Sample App", "id": "APP-ID" "subscribed_fields": [ "messages" ] } ] }
If your Page has not installed any apps, the API will return an empty data set.
You can also use the Graph API Explorer to send the request to subscribe your Page to a Webhooks field.
pages_manage_metadata
permission. This will exchange your app token for a User access token with the pages_manage_metadata
permission granted.GET
dropdown menu and selecting POST
.me?fields=id,name
query with the Page's id followed by /subscribed_apps
, then submit the query. To receive notifications from people who have a role on your app, such as your app admins, developers or testers, your app only needs Standard Access. To receive notifications from your customers, people who do not have a role on your app, your app will need Advanced Access.
Learn more about Standard and Advanced Access , the data accessible with each, and requirements for implementation.