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 .
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" } }
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.
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.
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.
Optionally, the Page admin can define one of the connected apps to be the primary receiver for the Page.
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:
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.
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:
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.
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 |
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"
}
}
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:
1217981644879628
(appid of Instagram inbox).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" } }
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" } }
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" } ] }
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 } } ] }
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>"
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>"
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" } }
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"] } }