Channel Transfer

Channel transfers enable you to move a conversation with a user to another integrated channel, while preserving the conversation history and unifying the user’s identity in the backend of your software. It allows businesses and end-users to have conversations on whichever channel is better suited for the topic at hand and to benefit from a single, continuous, cross-channel conversation thread. Changing channels can be used to:

  • Authenticate users on your website or mobile app to perform sensitive operations
  • Chat on a more private channel (than, say, Facebook Messenger)
  • Move the conversation to a channel that is less costly (eg. move away from SMS)
  • Provide a better user experience by leveraging rich messaging features on modern channels
  • Offer users the option to receive notifications on a more convenient channel

By leveraging the auth code and link request APIs, links can be generated and sent to users to direct them to the channel of your choice.

The guides below cover how to achieve this transfer in either direction:

Transfer to Web & Mobile SDK

The scenario below demonstrates how a customer Sue can begin a conversation with her bank on Facebook, and continue the same conversation on the bank’s own website. The flow chart below summarizes what we’re about to cover:

transfer to web flow chart

Sue is looking to set up a new bank account at Acme Bank. She first reaches out on their Facebook page. Acme Bank’s Facebook page is integrated with Sunshine Conversations, so Sue’s conversation shows up as a new conversation in Acme Bank’s helpdesk software.

The conversation is assigned to Ash, a customer service representative. He offers to guide her through the application process. Ash opens the help desk menu and selects “Send user to banking app”. The help desk inserts a message with an action of type link into the conversation which Sue can use to access the Acme Bank app.

channel transfer from facebook

Sue is now in the Acme banking app, but she hasn’t yet logged in. She does however see the history of messages that were sent between her and Ash over Facebook replicated here.

On Ash’s end, the conversation continues within the same help desk context as before and the help desk indicates that Sue is now talking to him via the Acme banking app. Ash directs Sue to log in.

Ash sees that Sue has logged in and helps her complete the application to set up her bank account.

Once Sue has a Sunshine Conversations userId and an Acme Bank account that she can log in to, the channel transfer process is simpler. The flow chart below shows the difference:

transfer with login

For example, suppose a few years later Sue is shopping for a mortgage. She again contacts Acme Bank over Facebook. This time a different agent named Bishop responds with some rates. Sue finds the rates attractive and wishes to proceed. Bishop once again sends her a link to the Acme banking app.

Sue visits the link and logs in. She can now seamlessly continue her conversation with Bishop from the banking app.

Error Handling

When supplying an expired or otherwise invalid auth code at init time, the init flow will return an error and leave the SDK in an uninitialized state. Your code should account for this possibility and gracefully handle the error. You may also choose to display an error to the user in this case. If you prefer to ignore the error and continue execution anyways, your code should call init again without an auth code in order to trigger a new initialization process as the previously logged in user.

Transfer to Messaging App

In this example we’ll show how a conversation can be transferred from a Sunshine Conversations SDK to a third party messaging app, in this case Facebook Messenger. The flow chart below summarizes this process:

transfer to messaging app

Sue wants to switch to a credit card that offers more points. She browses to her bank’s website and asks a question.

Sue asks a question on the Acme web app

An agent named Ash helps Sue choose a credit card and opens an application for her. Ash tells Sue that the process should take one day to complete.

Ash then invites Sue to link the conversation to a 3rd party messaging channel of her choice so that she can receive a notification as soon as her application completes. In the help desk software, Ash selects a menu option “Transfer to messaging app”. Sue is then presented with a list of channels to choose from.

Sue is presented with list of channels

Sue clicks the Facebook link which takes her into a Facebook Messenger conversation with Acme Bank.

Ash sends Sue another message to let her know she can continue the conversation over Facebook Messenger. Sue sees this message in Facebook Messenger while the conversation log continues to be replicated in her browser chat window.

Sue is now talking to Ash over Facebook Messenger

The following day, Sue’s application completes. Acme Bank sends a notification to let Sue know, and she receives the message via a Facebook Messenger push notification on her phone, and she continues the conversation with Acme Bank from there.

Channel Transfer Events

The following events are associated with channel transfers:

  • client:add
  • client:update
  • client:remove
  • user:merge

These four events reflect all possible outcomes:

  • A client is added to a user when a channel transfer is initiated or when a user logs in to an SDK integration for the first time.
  • A client is already assigned to a user and another user attempts to use that same account. Sunshine Conversations resolves this by either merging the user or updating the client.
  • A client is removed (from a user) when the channel transfer fails, through the API, or when the client is transferred from one user to another.

The following sections describe these events and scenarios in more detail.

Channel Support

Not all channels support link requests. For complete information, see channel capabilities.

Types of Users

Before talking about the v2 events, it is important to quickly review user types as they play an important role in which event is triggered. For detailed information about users, see Introduction to users.

There are two basic types of users in Sunshine Conversations.

  • Anonymous - Users who do not have an assigned external ID.
  • Identified - Users that your business has assigned an external ID, such as an email address, telephone number, GUIDs, and so forth.

A user can be only one type at any given time.

Event Details

The following sections briefly describe how the channel transfer events work. See Scenarios for more examples of when these events are triggered.

Adding a Client

The client:add event is triggered when a new client is added to a user. This occurs when initiating a channel transfer request or when logging in through an SDK integration (iOS, Web, or Android) that isn’t already linked to the user.

For example, Sue visits her bank’s Facebook page to ask questions regarding the latest interest rates. The bank representative sends Sue a link to their chat widget on their website to continue the conversation. The chat widget is created using the Sunshine Conversations SDK. This is the first time Sue uses the bank’s chat widget. When Sue clicks the link and “lands” on the chat widget, the client:add event is triggered.

Here is an example webhook payload:

{
    "app": {
        "id": "60bf823452c2a718162f986a"
    },
    "webhook": {
        "id": "613a338323224aab69eb878c",
        "version": "v2"
    },
    "events": [
        {
            "id": "6148a57e20698d4e576c4786",
            "createdAt": "2021-09-20T15:15:10.239Z",
            "type": "client:add",
            "payload": {
                "user": {
                    "id": "72bb4789027915bdeeb18f20"
                },
                "reason": "authCode",
                "client": {
                    "type": "sdk",
                    "id": "6148a57e20698d4e576c4783",
                    "status": "active",
                    "lastSeen": "2021-09-20T15:15:10.207Z",
                    "linkedAt": "2021-09-20T15:15:10.207Z"
                },
                "source": {
                    "type": "web",
                    "integrationId": "60bf824952c2a718162f989c"
                }
            }
        }
    ]
}

For more information, see Webhook Events, then expand events and select client:add.

Updating a Client

The client:update event is triggered when the client’s status is updated. This occurs when a channel successfully matches the provided externalId, when a channel transfer is complete, or when a user blocks or unsubscribes from a conversation.

The client:update event can also be triggered during the course of a transfer. For example, with reason:matched, the status remains pending before and after an event (see above paragraph.) However, the client:update event can still be triggered when something client-related is updated as part of the transfer process.

For example, Sue is using the hotel’s chat widget (created with the Sunshine Conversations SDK) on their web page and wants to link SMS to the conversation she is having with a hotel representative. Sue clicks the button to link SMS in the chat and enters her phone number. This creates a Twilio client with status:pending and triggers the client:add event. A text message is sent to Sue to confirm/deny (Yes/No) triggering a client:update event with reason:matched. Sue clicks Yes which triggers a client:update event with reason:confirmed indicating that her phone number is successfully linked.

Note that if confirmation.type: immediate was used instead (meaning, no text sent to Sue), the client:update with reason:matched event is not triggered.

Here is an example webhook payload:

{
    "app": {
        "id": "60bf823452c2a718162f986a"
    },
    "webhook": {
        "id": "60c0eeee67951336472cc5c4",
        "version": "v2"
    },
    "events": [
        {
            "id": "60c0ef415a04b5364b8a21cf",
            "createdAt": "2021-06-09T16:41:37.794Z",
            "type": "client:update",
            "payload": {
                "reason": "confirmed",
                "user": {
                    "id": "3350271ca0e348bd1525d59d",
                    "externalId": "sue"
                },
                "conversation": {
                    "id": "59022bc666581de2ec5cba81",
                    "type": "personal"
                },
                "client": {
                    "integrationId": "60bfc8fa67951336472cc57a",
                    "type": "twilio",
                    "externalId": "+15140000000",
                    "id": "60bfcc075a04b5364b8a21cd",
                    "displayName": "+1 514-000-0000",
                    "status": "active",
                    "info": {
                        "city": "MONTREAL",
                        "country": "CA",
                        "phoneNumber": "+15140000000",
                        "state": "QC"
                    },
                    "raw": {
                        "FromZip": "",
                        "FromState": "QC",
                        "FromCity": "MONTREAL",
                        "FromCountry": "CA",
                        "From": "+15140000000"
                    },
                    "lastSeen": "2021-06-10T17:58:31.576Z",
                    "linkedAt": "2021-06-08T19:59:03.667Z"
                }
            }
        }
    ]
}

Removing a Client

The client:remove event is triggered when a client is removed from a user. This occurs when you manually remove a client (using the API), when a channel transfer fails, when a client theft occurs (a client is moved from one user to another), or when the user refuses the link prompt.

For example, suppose Sue is interested in her bank’s car loans and is chatting with Ash, the loan representative, through the bank’s chat widget on their website. The chat widget is created using the Sunshine Conversations SDK. Ash invites Sue to link the conversation to a third-party messaging channel of her choice so that she can review the conversation whenever she wants. Sue clicks the button for SMS which creates a client with status:pending and triggers the client:add event. Sue accidentally enters the wrong phone number and cancels the request. This triggers a client:remove event.

Here is an example webhook payload:

{
    "app": {
        "id": "60bf823452c2a718162f986a"
    },
    "webhook": {
        "id": "613a338323224aab69eb878c",
        "version": "v2"
    },
    "events": [
        {
            "id": "6148a7ed5720554e5aae608f",
            "createdAt": "2021-09-20T15:25:33.441Z",
            "type": "client:remove",
            "payload": {
                "user": {
                    "id": "e58c581e263921222ec129f8"
                },
                "client": {
                    "integrationId": "60bfc8fa67951336472cc57a",
                    "type": "twilio",
                    "externalId": "+15140000000",
                    "id": "6148a7e920698d4e576c4791",
                    "displayName": "+1 514-000-0000",
                    "status": "pending"
                },
                "reason": "sdk",
                "source": {
                    "type": "web",
                    "integrationId": "60bf824952c2a718162f989c"
                }
            }
        }
    ]
}

For more information, see Webhook Events, then expand events and select client:remove.

Transferring a Client

When transferring a client, a client:remove event is triggered when removing a client from a user and a client:update event is triggered when the client is transferred to the new user.

For example, Sue is inquiring about a car and creates an account on the dealer’s website. She uses the dealer’s web chat to talk to a salesperson and during the conversation asks to link this conversation to her Facebook Messenger account. The salesperson generates a link request and redirects Sue to the Messenger app. A few days later, Sue has more questions and starts a conversation with the dealer using their Android app. Sue does not log in and is considered an anonymous user. Sue again wants to link this conversation to her Facebook Messenger account through the same Facebook account as earlier. Sunshine Conversations determines that this Facebook Messenger client is already linked to an identified user. In this example, an anonymous user is trying to link to a client already associated with an identified user and a merge is not allowed. Instead, the Facebook Messenger client is transferred to the anonymous user. Removing the client from the identified Sue triggers the client:remove event. Once she approves the link, the client:update event is triggered.

Merging Users

The user:merge event is triggered when two users are merged. It contains the client that was removed and the client that was kept. Note that merging triggers neither the client:update nor the client:remove events.

For example, Sue is using a store website’s web chat to chat with a sales representative regarding an order. She doesn’t want to remain at her computer for the duration of the session and chooses to continue her conversation on Facebook Messenger. A few days later, Sue returns to the store’s website using a different computer and starts a new conversation with a sales representative. She again chooses to continue her conversation on Facebook Messenger using the same account as before. Sunshine Conversations determines that both Facebook Messenger conversations belong to Sue, merges them, and triggers the user:merge event. In both chats, Sue is considered an anonymous user.

Here is an example webhook payload:

{
    "app": {
        "id": "60bf823452c2a718162f986a"
    },
    "webhook": {
        "id": "613a338323224aab69eb878c",
        "version": "v2"
    },
    "events": [
        {
            "id": "6148ae625720554e5aae60a7",
            "createdAt": "2021-09-20T15:53:06.850Z",
            "type": "user:merge",
            "payload": {
                "mergedUsers": {
                    "surviving": {
                        "id": "022d1469bf801373e43ea6fd"
                    },
                    "discarded": {
                        "id": "2e72fa9bc5440a9378fad4df"
                    }
                },
                "mergedConversations": {
                    "surviving": {
                        "id": "428c83b6cc5c58a5862f7e09",
                        "type": "personal"
                    },
                    "discarded": {
                        "id": "d8375e4387893d2080905054",
                        "type": "personal"
                    }
                },
                "mergedClients": {
                    "surviving": {
                        "integrationId": "61324f8fdd4e49165bf3a66f",
                        "type": "messenger",
                        "externalId": "1395558734359624",
                        "id": "6148ae465720554e5aae6092",
                        "displayName": "Sue",
                        "status": "active",
                        "info": {
                            "avatarUrl": "https://example.com/images/avatar.jpg"
                        },
                        "raw": {
                            "first_name": "Sue",
                            "last_name": "Allen",
                            "profile_pic": "https://example.com/images/profilepic.jpg",
                            "id": "1395558734359624"
                        },
                        "lastSeen": "2021-09-20T15:52:47.766Z",
                        "linkedAt": "2021-09-20T15:52:38.522Z",
                        "avatarUrl": "https://example.com/images/avatar.jpg"
                    },
                    "discarded": {
                        "integrationId": "61324f8fdd4e49165bf3a66f",
                        "type": "messenger",
                        "externalId": "1395558734359624",
                        "id": "6148ae5e5720554e5aae609c",
                        "displayName": "Sue",
                        "status": "pending"
                    }
                },
                "reason": "channelLinking"
            }
        }
    ]
}

For more information on user merges, see How merges work.

Scenarios

This section describes a few scenarios to illustrate how the events are triggered. You can subscribe to these triggers when configuring your own webhook to better understand what is happening and when.

Basic Channel Linking

This scenario describes the simplest form of channel linking.

Sue is setting up a new bank account at Acme Bank and reaches out to them through their web page. This is the first time Sue has interacted with Acme Bank’s web page. Acme Bank’s web page uses a chat widget created with the Sunshine Conversations SDK.

Ash, a customer service representative, offers to guide Sue through the application process and gives Sue the option to link her phone number to this conversation. She agrees, clicks the SMS icon in their current conversation, and enters her phone number. This phone number does not yet exist in Acme Bank’s Helpdesk software. Sue receives a text message on her phone to accept or deny this link request and clicks Yes. Sue has now linked this conversation to her phone number.

Here’s the workflow:

  • When Sue starts the conversation on Acme Bank’s web page, a new anonymous user is created in Sunshine Conversations.
  • When Sue clicks the SMS icon and enters her phone number, a (Twilio) client is created with status:pending and triggers the client:add event.
  • As part of the process of sending Sue the text message, an API call is made to Twilio to confirm the phone number is valid.
  • Once Twilio confirms that the provided phone number is valid, a client:update with reason:matched is triggered.
  • When Sue replies Yes in the text message, it tells Sunshine Conversations that she is allowing this new client. The client changes to status:active and a client:update event is triggered with reason:confirmed.

Suppose Sue accidentally enters a wrong phone number (a number that doesn’t actually belong to any mobile phone.) Twilio now responds with no matching user found. In this scenario, the workflow is:

  • When Sue clicks the SMS icon and enters her phone number, a (Twilio) client is created with status:pending and triggers the client:add event.
  • As part of the process of sending Sue the text message, an API call is made to Twilio to confirm the phone number is valid.
  • Twilio responds that it cannot find this phone number in its database. A client:remove with reason:linkFailed is triggered.
  • Because the bank listened for the client:remove webhook event, Ash sees in the logs that Twilio cannot be linked and asks Sue to re-enter her phone number.

In the above examples, Twilio confirms whether the phone number is valid. However, not all channels have this feature of confirming the externalId. In these cases, Sunshine Conversations assumes the confirmation is valid and does not trigger a client:update with reason:match as in the first workflow above.

Channel Transfer Between Two Identified Users

In this scenario, we’ll examine what happens when two identified users try to use the same client (same externalId).

Chris wants to book a hotel reservation and uses the hotel’s chat widget on their website which is created with the Sunshine Conversations SDK. Ash, who works at the hotel, offers to help. Chris already has an account with this hotel, logs in to the chat widget, and is therefore an identified user. Chris has also already linked Twilio. Due to a conflict in their schedule, two days later his wife Sue logs in to the hotel’s chat widget to update their reservation. Sue is also an identified user, separate from Chris. Ash gives Sue the option to link her phone number to this conversation. Sue agrees, clicks the SMS icon in the chat window, and enters the same phone number that Chris used. She receives a text message on her phone to accept or deny this link request and clicks Yes. Sue has now linked this conversation and the Twilio channel is transferred from Chris to Sue.

The workflow is as follows:

  • Chris, and later Sue, log in to the hotel’s website to use the hotel’s chat widget.
  • When Sue clicks the SMS icon and enters her phone number, a (Twilio) client is created with status:pending and triggers the client:add event.
  • As part of the process of sending Sue the text message, an API call is made to Twilio to confirm the phone number is valid.
  • Twilio confirms that the provided phone number is valid and Sunshine Conversations finds the phone number (the externalId in this case) matches another user, Chris. This triggers a client:matched event.
  • When Sue clicks Yes in the text message, it tells Sunshine Conversations that she is allowing this new client. This removes the Twilio channel from Chris and triggers the client:remove event with reason:theft for him. This also triggers the client:update with reason:confirmed event for Sue.

Channel Transfer Between Two Anonymous Users

In this scenario, we’ll see what happens when an anonymous user tries to use the same client (same externalId) as another anonymous user.

Let’s use the Example business-initiated flow. To recap, Alice sends a message to your business’ configured Twilio phone number. Later, Alice starts a conversation with your business through your iOS application. During Alice’s conversation in iOS, she would like to receive further updates over SMS. The create client API is used to attach the phone number to Alice’s iOS conversation. Sunshine Conversations determines that both Alices share the same phone number and merges the users. Now, the conversation history is shared between iOS and SMS and Alice can reply from either channel.

Here’s the workflow:

  • When Alice sends her first message through your business’ Twilio phone number, a new anonymous user is created in Sunshine Conversations.
  • When Alice messages on her iOS device, a new anonymous user is created in Sunshine Conversations and a new Twilio client is created for Alice.
  • Sunshine Conversations determines that two instances of an anonymous user share the same phone number, merges the users, and triggers the user:merge event with reason:channelLinking.

Next Steps

  • Generate auth codes REST API.
  • Generate link requests REST API.
  • Check out our runnable examples in Node.js to quickly try channel transfers.