Handover Protocol

The handover protocol enables two or more Facebook apps to participate in a conversation by passing control of the conversation between them. This feature can be used in many ways to enrich your messaging experience. For example, this protocol makes it possible for an Instagram account to simultaneously use one Facebook app to build a bot for handling automated responses, and another Facebook app for customer service with live agents.

Use metadata field to pass additional context between apps. Avoid including any sensitive information like passwords, credentials, any UII information etc in the metadata field to protect user privacy .

Exclusivity

Whenever an app is in control of the thread, no other app would be able to interject the conversation by sending messages to the thread. A controlling app will have exclusive control of the thread. A Primary app would also not be able to interject a conversation, if it needs to interact with the user, it has to take control of the thread.

The non-controlling apps would still be able to listen to all webhook events on the standby channel for analytics/debugging/tracking purposes.

If another app is in control of the thread and any other app tries to message the user an error message as below would be sent back with HTTP Status: 400 Bad Request

{
    "error": {
        "message": "(#10) Message failed to send because another app is controlling this thread now.",
        "type": "OAuthException",
        "code": 10,
        "error_subcode": 2018300,
        "fbtrace_id": "AQ2lKD7UqnvqCrMs16fUNLk"
    }
}

Idle Mode

In idle mode, any app can claim ownership of the thread and start interacting with the user. HOP allows apps to send messages to a thread in idle mode.

When should I expect a thread to be in idle mode or non-controlled mode.

  • When Primary app is not set, all threads start in idle mode.
  • After thread ownership expiration (Default expiration time is 24 hours of inactivity after an app takes control)
  • The controlling app explicitly releases their ownership

If a Primary app is set and a user messages a page when thread is idle, then the Primary app gets the control of the thread. If no Primary app is set all the apps would receive the message and can respond. If exclusive control is needed the desired app needs to use the take thread control API to take control of the thread from idle mode.

Human Agent Tag behavior

We are also incorporating the behavior of allowing messages sent with the HUMAN_AGENT Tag to trigger thread transfer to the app sending the message with the tag. This is being built to allow for the possibility of HUMAN AGENT tools to be able to take thread control in an emergency situation such as a bot not responding. When you are not in control of the thread, please use this tag only when you see genuine cases of intervention and when you have ascertained 100% that you have to take control. We would be monitoring the use of this tag for any misuse or violation.

Primary Receiver

Optionally, the Page admin can define one of the connected apps to be the primary receiver for the Page.

  • If a Primary app is configured, by default all new threads will be sent to the Primary Receiver app. Else, all apps will get the message and any one of them can respond to the thread but they wouldn’t get exclusive control. For exclusive control an app needs to call the take thread control API - detailed in the API section below.
  • Primary app is the only app that will be allowed to take thread control from any other app via the Take Thread Control API
  • Primary app can be setup from Page settings > Messenger Platform > Connected Apps > Configure as below:

Assign a Primary Receiver

To assign an app as a primary receiver you must have full access. You can view, and assign, access levels in one of the following ways:

  • In the Meta Business Settings, go to Users > People. A person must have Full control.
  • In the New Pages Experience, go to the Facebook Page Settings > New Pages Experience > Page access. A person must have Facebook access.
  • In the Classic Page Experience, go to the Facebook Page Page settings > Page Roles. A person must have Admin access or be able to perform the MANAGE task on the Page.

Webhook Events

To help you manage your use of the handover protocol and track when control of the conversation is passed between Facebook apps, the Messenger Platform offers the following set of specialized webhook events.

messaging_handovers

The messaging_handovers webhook event is sent to the webhook associated with a Facebook app any time one of the following handover protocol actions is taken on that app:

  • Thread control is passed to the app
  • Thread control is taken from the app
  • Thread control is requested from the app
  • Metadata is passed to the app
  • App role is changed

standby

Apps that don't have the thread control at the time can optionally subscribe to a separate 'standby' channel to listen to incoming messages. It is important to implement the standby channel, as it allows apps to track the full context of the conversation and be well-informed on how to proceed if control is passed to them.

Handover Protocol APIs

The following is a summary of the available actions for Primary and other apps. For more information and usage details on each handover protocol action, see below this section.

Primary Apps

Non-Primary Apps

Page Inbox

Pass Thread Control

Take Thread Control

Standby Channel

Request Thread Control

Extend Thread Control

Release Thread Control

Pass Metadata

Get Secondary Receivers List

Get Thread Owner

Passing Thread Control

The Pass Thread Control API is used to pass control of a conversation between apps. The calling app can pass optional metadata along with the API request. When thread control is passed to an app, the pass_thread_control webhook event will be sent to this app along with any optional metadata.

All apps can use this API to pass the thread control to another app. You can also enable live chat in your bot by passing thread control directly to the Instagram inbox.

curl -X POST -H "Content-Type: application/json" -d '{
  "recipient":{"id":"<IGSID>"},
  "target_app_id":123456789,
  "metadata":"String to pass to secondary receiver app" 
}' "https://graph.facebook.com/v8.0/me/pass_thread_control?access_token=<PAGE_ACCESS_TOKEN>"

Example messaging_handovers Event: pass_thread_control:

{
  "sender":{
    "id":"<IGSID>"
  },
  "recipient":{
    "id":"<IGID>"
  },
  "timestamp":1458692752478,
  "pass_thread_control":{
    "previous_owner_app_id" : "<previous_app_id or null (idle_mode)>"
    "new_owner_app_id":"123456789",
    "metadata":"Additional content that the caller wants to set"
  }
}

Passing Thread Control to the Instagram Inbox (Live Chat)

The handover protocol can be used to pass thread control from an app to your Page inbox. This allows you to offer live chat by replying to messages sent to the Page inbox, and is also useful as a fallback if your bot is unable to understand a message.

To enable live chat via the Instagram inbox, do the following:

  1. From the current controlling app, pass thread control to the Page inbox by setting the target_app_id property of the request to 1217981644879628 (appid of Instagram inbox).

Taking Thread Control

Take Thread Control API allows the app with the Primary Receiver role to take control of the conversation from the other apps. This is useful if it takes too long for the other apps to respond or it becomes unresponsive. An optional metadata string may also be sent in the request.

The previous owner app will receive a messaging_handovers webhook event when control of the conversation has been taken away. The event will contain the metadata string.

curl -X POST -H "Content-Type: application/json" -d '{
  "recipient":{"id":"<IGSID>"},
  "metadata":"String to pass to the current controlling app" 
}' "https://graph.facebook.com/v8.0/me/take_thread_control?access_token=<PAGE_ACCESS_TOKEN>"

Example messaging_handovers Event: take_thread_control

{
  "sender":{
    "id":"<IGSID>"
  },
  "recipient":{
    "id":"<IGID>"
  },
  "timestamp":1458692752478,
  "take_thread_control":{
    "previous_owner_app_id":"123456789", //could be null if thread was in idle mode
    "new_owner_app_id": <new_app_id>,
    "metadata":"additional content that the caller wants to set"
  }
}
    

Request Thread Control

The Request Thread Control API allows an app to notify another app currently in control of the thread that it wants control of the chat. The controlling app can choose to pass the thread control or do nothing. An optional metadata string may also be sent in the request. If the thread is however in Idle mode, the control of the thread will directly be passed to the requesting app.

curl -X POST -H "Content-Type: application/json" -d '{
  "recipient":{"id":"<IGSID>"},
  "metadata":"additional content that the caller wants to set" 
}' "https://graph.facebook.com/v8.0/me/request_thread_control?access_token=<PAGE_ACCESS_TOKEN>"

Example messaging_handovers Event: request_thread_control

  {
  "sender":{
    "id":"<IGSID>"
  },
  "recipient":{
    "id":"<IGID>"
  },
  "timestamp":1458692752478,
  "request_thread_control":{
    "requested_owner_app_id":123456789,
    "metadata":"additional content that the caller wants to set"
  }
}
     

Retrieving the List of Non-Primary Receivers

Only the Facebook app with the Primary Receiver app role may retrieve the list of all messaging apps connected to the page.

curl -X GET "https://graph.facebook.com/v8.0/me/secondary_receivers?fields=id,name&platform=instagram&access_token=<PAGE_ACCESS_TOKEN>"

Example Response:

{
  "data":[
    {
      "id":"12345678910",
      "name":"David's Composer"
    },
    {
      "id":"23456789101",
      "name":"Messenger Rocks"
    }
  ]
}
    

Get Thread Owner

The handover protocol's Thread Owner API returns the app ID of the app the currently has thread control for a Page. This is useful for IG accounts that have complex implementations of the handover protocol, where an app's actions are dependent on whether it currently has thread control.

The Thread Owner API may be called by apps that are Primary as well as Non-Primary receivers.

On success, it will return the thread_owner object with the app_id of the app that currently has thread control along with expiration time for that app in the body of the response. However, if the thread is not owned by any app i.e thread is in Idle mode, the app_id field in the response would be null and the expiration field would not be present.

curl -X GET "https://graph.facebook.com/v8.0/me/thread_owner?recipient=<IGSID>&access_token=<PAGE_ACCESS_TOKEN>"
     

Example Response:

{
  "data": [ 
    {
      "thread_owner":{
        "app_id": <APP_ID>, //App Id of current thread owner app, null if thread Idle
        "expiration": 1234567 // Time after which thread will go into Idle mode. Field would not be present
  														//if thread is currently idle
      }
    }
  ]
}
     

Extending Thread Control

The Extend Thread Control API will allow any app currently in control of the thread to extend it’s expiration time to idle Mode. The duration is specified in seconds in the API call as below. A max of 7 days can be set as the duration in one call:

curl -X POST -H "Content-Type: application/json" -d '{
  "recipient": {
    "id": "<IGSID>"
  },
  "duration": 86400, // in seconds 
}' "https://graph.facebook.com/v8.0/me/extend_thread_control?access_token=<PAGE_ACCESS_TOKEN>"
    

Releasing Thread Control

The Release Thread Control API can be used to by any app to release their control of the thread whenever they are done with their flow. It is always considered best practice to release thread control when it is no longer needed rather than waiting for 24 hours to let the thread go into idle mode automatically.

curl -X POST -H "Content-Type: application/json" -d '{
  "recipient": {
    "id": "<IGSID>"
  },
}' "https://graph.facebook.com/v8.0/me/release_thread_control?access_token=<PAGE_ACCESS_TOKEN>"
    

Passing Additional Metadata Between Apps

There may be scenarios to pass additional data between apps to maintain context and control of threads. This can be done by using the Pass Metadata API. A call to this API by specifying the target_app_id would ensure that the target app would receive a webhook event with the metadata from the calling app.

curl -X POST -H "Content-Type: application/json" -d '{
  "recipient": {
    "id": "<IGSID>"
  },
  "target_app_id":123456789,
  "metadata":"additional content that the caller wants to set" 
}' "https://graph.facebook.com/v8.0/me/pass_thread_metadata?access_token=<PAGE_ACCESS_TOKEN>"
    

Example messaging_handovers Event: pass_metadata

{
  "sender":{
    "id":"<IGSID>"
  },
  "recipient":{
    "id":"<IGID>"
  },
  "timestamp":1458692752478,
   "pass_metadata":{
    "caller_app_id":123456789,
    "metadata":"additional content that the caller wants to set"
  }
}
    

Changing App Roles

Whenever a page admin changes an app’s role to Primary the following messaging_handover_event would be sent to the new primary app.

{
  "recipient":{
    "id":"<IGID>"
  },
  "timestamp":1458692752478,
  "app_roles":{
    "123456789":["primary_receiver"]
  }
}
   

Developer Support