Setup Webhooks Subscriptions

This document shows you how to subscribe webhook fields for an Instagram professional account using your app. This allows you to receive real-time notifications whenever someone comments on the Media objects of the Instagram professional account using your app or when a Instagram user sends a message to that Instagram professional account.

Requirements

You will need:

Access level

  • Advanced Access if your app serves Instagram professional accounts you don't own or manage
  • Standard Access if your app serves Instagram professional accounts you own or manage

Access tokens

  • An Instagram User access token requested from a Instagram user who can manage comments on the Instagram professional account

App Dashboard

Base URL

  • All endpoints can be accessed via the graph.instagram.com host

Endpoints

IDs

  • The ID for the Instagram professional account (<YOUR_APP_USERS_IG_USER_ID>) that is using your app

NOTE: The owner of the Instagram media upon which the comment or @mention appears must not have set their account to private

Permissions

  • instagram_business_basic – Required for all webhook fields
  • See the Instagram fields table in this guide for specific permissions for each field

Webhooks server

Limitations

  • Webhook customization for Instagram business level webhooks isn't supported. Webhook notifications are sent for the webhook fields your app is subscribed to if your app user is subscribed to at least one Instagram webhook field.

Create an Endpoint

Your endpoint 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. Alternatively, you can use our sample app which is already configured to process these requests.

Verification Requests

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:

Sample Verification Request

GET https://www.your-clever-domain-name.com/webhooks?
  hub.mode=subscribe&
  hub.challenge=1158201444&
  hub.verify_token=meatyhamhock
ParameterSample ValueDescription

hub.mode

subscribe

This value will always be set to subscribe.

hub.challenge

1158201444

An int you must pass back to us.

hub.verify_token

meatyhamhock

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.

Validating Verification Requests

Whenever your endpoint receives a verification request, it must:

  • Verify that the 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).
  • Respond with the hub.challenge value.

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 indicate success or failure with a response.

Event Notifications

When you configure your Webhooks product, you will subscribe to specific fields on an object type (e.g., the photos field on the user 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 user object's photos field and one of your app's Users posted a Photo, we would send you a POST request that would look something like this:

POST / HTTPS/1.1
Host: your-clever-domain-name.com/webhooks
Content-Type: application/json
X-Hub-Signature-256: sha256={super-long-SHA256-signature}
Content-Length: 311

{
  "entry": [
    {
      "time": 1520383571,
      "changes": [
        {
          "field": "photos",
          "value":
            {
              "verb": "update",
              "object_id": "10211885744794461"
            }
        }
      ],
      "id": "10210299214172187",
      "uid": "10210299214172187"
    }
  ],
  "object": "user"
}

Payload Contents

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.

Most payloads will contain the following common properties, but the contents and structure of each payload varies depending on the object fields you are subscribed to. Refer to each object's reference document to see which fields will be included.

Property Description Type

object

The object's type (e.g., user, page, etc.)

string

entry

An array containing an object describing the changes. Multiple changes from different objects that are of the same type may be batched together.

array

id

The object's ID

string

changed_fields

An array of strings indicating the names of the fields that have been changed. Only included if you disable the Include Values setting when configuring the Webhooks product in your app's App Dashboard.

array

changes

An array containing an object describing the changed fields and their new values. Only included if you enable the Include Values setting when configuring the Webhooks product in your app's App Dashboard.

array

time

A UNIX timestamp indicating when the Event Notification was sent (not when the change that triggered the notification occurred).

int

Validating Payloads

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.

To validate the payload:

  1. Generate a SHA256 signature using the payload and your app's App Secret.
  2. Compare your signature to the signature in the X-Hub-Signature-256 header (everything after sha256=). If the signatures match, the payload is genuine.

Responding to Event Notifications

Your endpoint should respond to all Event Notifications with 200 OK HTTPS.

Frequency

Event Notifications are aggregated and sent in a batch with a maximum of 1000 updates. However batching cannot be guaranteed so be sure to adjust your servers to handle each Webhook individually.

If any update sent to your server fails, we will retry immediately, then try a few more times with decreasing frequency over the next 36 hours. Your server should handle deduplication in these cases. Unacknowledged responses will be dropped after 36 hours.

Note: The frequency with which Messenger event notifications are sent is different. Please refer to the Messenger Platform Webhooks documentation for more information.

Subscribe to webhooks

To subscribe your app user to Instagram webhook fields so they can receive Instagram event notifications, send a POST request to the /<YOUR_APP_USERS_IG_USER_ID>/subscribed_apps endpoint with the subscribed_fields parameter set to a comma-separated list of webhooks fields.

Request Syntax

Formatted for readability.

POST /<YOUR_APP_USERS_IG_USER_ID>/subscribed_apps
  ?subscribed_fields=<LIST_OF_WEBHOOK_FIELDS>
  &<ACCESS_TOKEN>

Request Parameters

Value Placeholder Value Description

<YOUR_APP_USERS_IG_USER_ID>

The app user's Instagram professional account ID

<ACCESS_TOKEN>

App user's Instagram User access token.

<LIST_OF_WEBHOOK_FIELDS>

A comma-separated list of Instagram webhook fields

Example Request

Formatted for readability.

curl -i -X POST \
  "https://graph.instagram.com/v21.0/1755847768034402/subscribed_apps
  ?subscribed_fields=comments,messages
  &access_token=EAAFB..."

On success, your app receives a JSON response with success set to true.

{
  "success": true
}

Instagram fields

You can subscribe to the following fields to receive notifications for events that take place on Instagram.

FieldDescription

comments

Comments on an Instagram media object owned by your app user's Instagram professional account.

Permission Required: instagram_business_manage_comments

The ad_id, ad_title and original_media_id will be returned in the media object when a Instagram user comments on a boosted Instagram post or Instagram ads post.

live_comments

Comments on a live Instagram media object owned by your app user's Instagram professional account.

Permission Required: instagram_business_manage_comments

message_reactions

Reactions on an Instagram media object owned by your app user's Instagram professional account.

Permission Required: instagram_business_manage_messages

messages

A Instagram user has sent a message to your app user's Instagram professional account.

Permission Required: instagram_business_manage_messages

messaging_optins

A Instagram user has agreed to receive messages from your app user's Instagram professional account.

Permission Required: instagram_business_manage_messages

messaging_postbacks

Responses from buttons, ice breakers, persistent menus, or quick replies within a message sent by your app user's Instagram professional account.

Permission Required: instagram_business_manage_messages

messaging_referral

A Instagram user sends a message in an existing conversation with your app user's Instagram professional account via an ig.me link.

Permission Required: instagram_business_manage_messages

messaging_seen

A Instagram user has seen a message sent by your app user's Instagram professional account.

Permission Required: instagram_business_manage_messages

Example Notifications

The following are examples for the types of webhooks notifications you can receive.

Messages

{
  "object": "instagram",
  "entry": [
    {
      "id": "<YOUR_APP_USERS_IG_USER_ID>",        // The ID of your app user's Instagram Professional account
      "time": 1569262486134,
      "messaging": [
        {
          "sender": { "id": "<INSTAGRAM_SCOPED_ID>" },     // Instagram-scoped ID for the Instagram user who sent your app user a message
          "recipient": { "id": "<YOUR_APP_USERS_IG_USER_ID>" },  // ID of your app user's Instagram Professional account
          "timestamp": 1569262485349,
          "message": {
            "mid": "<MESSAGE_ID>",     // ID of the message sent to your app user
      
            "text": "<MESSAGE_TEXT>",   // Included when the Instagram user sends a message containing text
            
            "is_deleted": true,         // Included when the Instagram user deletes a message
      
            "is_echo": true,            // Included when your app user's Instagram Professional account sends a message to the Instagram user

            "is_unsupported": true,    // Included when the Instagram user sends a message with unsupported media
      
      
            "attachments": [                  // An array of media objects included when the Instagram user sends 1 or more media
              {                               // Can be audio, file, image (image or sticker), share,
                "type":"image",               //    story_mention, video, ig_reel or reel
                "payload":{ "url":"<URL_FOR_THE_MEDIA>" }  
              },
              {
                "type":"video",
                "payload":{ "url":"<URL_FOR_THE_MEDIA>" }
              }
            ],

      
            "quick_reply": {                      // Included when the Instagram user clicks a quick reply
              "payload": "<QUICK_REPLY_OPTION_SELECTED>"    
            },      
      
            "referral": {              // Included when the Instagram user clicks an Instagram Shop product
              "product": {
                "id": "<PRODUCT_ID>"
            },      
      
            "referral": {                   // Included when the Instagram user clicks a CTD ad
              "ref": "<AD_REF_PARAMETER_VALUE_IF_SET>"
              "ad_id": "<AD_ID>",
              "source": "ADS",
              "type": "OPEN_THREAD",
              "ads_context_data": {
                "ad_title": "<AD_TITLE>",
                "photo_url": "<IMAGE_URL_THAT_WAS_SELECTED>",
                "video_url": "<THUMBNAIL_URL_FOR_THE_AD_VIDEO>",
              }
            },

            "reply_to":{               // Included when the Instagram user sends an inline reply
              "mid":"<MESSAGE_ID>"
            } 
      
            "reply_to": {               // Included when the Instagram user replies to a story
              "story": {
                "url":"<CDN_URL_FOR_THE_STORY>",
                "id":"<STORY_ID>"       
              }
            }
          }
        }
      ]
    }
  ]
}

Message Reactions

{
  "object": "instagram",
  "entry": [
    {
      "id": "<YOUR_APP_USERS_IG_USER_ID>",  // ID for your app user's Instagram Professional account
      "time": 1569262486134,
      "messaging": [
        {
          "sender": {
            "id": "<INSTAGRAM_SCOPED_ID>"  // Instagram-scoped ID for the Instagram user who sent the message
          },
          "recipient": {
            "id": "<YOUR_APP_USERS_IG_USER_ID>"  // ID for your app user's Instagram Professional account
          },
          "timestamp": 1569262485349,
          "reaction" :{
            "mid" : "<MESSAGE_ID>",
            "action": "react",          // or unreact if removing the reaction
            "reaction": "love",         // Not included when action is unreact
            "emoji": "\u{2764}\u{FE0F}" // Not included when action is unreact
          } 
        }
      ]
    }
  ]
}  

Messaging Postbacks

{
  "object": "instagram",
  "entry": [
    {
      "id": "<INSTAGRAM_SCOPED_ID>",  // ID of your app user's Instagram Professional account
      "time": 1502905976963,
      "messaging": [
        {
          "sender": { "id": "<INSTAGRAM_SCOPED_ID>" },    // Instagram-scoped ID for the Instagram user who sent the message
          "recipient": { "id": "<YOUR_APP_USERS_IG_USER_ID>" },  // ID of your app user's Instagram Professional account
          "timestamp": 1502905976377,
          "postback": {
            "mid":"<MESSAGE_ID>",           // ID for the message sent to your app user
            "title": "<USER_SELECTED_ICEBREAKER_OPTION_OR_CTA_BUTTON>",
            "payload": "<OPTION_OR_BUTTON_PAYLOAD>",  // The payload with the option selected by the Instagram user
          }
        }
      ]
    }
  ]
}

Messaging Referral

{
  "object": "instagram",
  "entry": [
    {
      "id": "<INSTAGRAM_SCOPED_ID>",  // ID of your Instagram Professional account  
      "time": 1502905976963,
      "messaging": [
        {
          "sender": {
            "id": "<INSTAGRAM_SCOPED_ID>"  // Instagram-scoped ID for the Instagram user who sent the message
          },
          "recipient": {
            "id": "<YOUR_APP_USERS_IG_USER_ID>"  // ID of your Instagram Professional account
          },
          "timestamp": 1502905976377,
          "referral": {
                 "ref": "<IGME_LINK_REF_PARAMETER_VALUE>"
                 "source": "<IGME_SOURCE_LINK>"  
                 "type":  "OPEN_THREAD"  // Included when a message is part of an existing conversation
          }
        }
      ]
    }
  ]
}
  

Messaging Seen

{
   "object":"instagram",
   "entry":[
      {
         "id":"<YOUR_APP_USERS_IG_USER_ID>",     // ID for your app user's Instagram Professional account
         "time":1569262486134,
         "messaging":[
            {
               "sender":{
                  "id":"<INSTAGRAM_SCOPED_ID>"  // Instagram-scoped ID for the Instagram user who sent the message
               },
               "recipient":{
                  "id":"<YOUR_APP_USERS_IG_USER_ID>"  // ID for your app user's Instagram Professional account
               },
               "timestamp":1569262485349,
               "read":{
                  "mid":"<MESSAGE_ID>"  // ID for the message that was seen
               }
            }
         ]
      }
   ]
}