Introduction
Messaging connects your consumers with human agents or bots. A key component is enabling conversations across Messaging apps—go where your consumers are. As part of LivePerson's open platform we provide a growing number of out-of-the-box connectors, e.g., for SMS , Facebook Messenger, WhatsApp, and others. In cases where an out-of-the-box solution is not available you can use LivePerson's APIs to build a custom connector.
Use Cases
A common use case for building your own connector to LiveEngage Messaging is SMS integration. LivePerson offers a SMS Twilio connector out-of-the-box, which is an excellent solution for most use cases. However, there are other cases where you want to use another SMS Gateway or similar:
- Integrate a custom SMS gateway.
- Integrate a proprietray chat window.
- Integrate a mobile application when the LivePerson Mobile SDK is not applicable.
Connectors are server applications. If you are planning to build a client-side application, please refer to the Messaging Window API .
About Messaging
Messaging is centered around conversations. When a consumer first connects to LiveEngage, they will do so by creating a conversation. A new conversation is assigned to an agent or bot. Not every Messaging app has a notion of conversation—in the case of SMS messages are of exchanged in a sequence.
A conceptual data model of Messaging is depicted below:
A conversation contains one or more dialogs. When a conversation is created a standard dialog of type MAIN
is opened by default. Every conversation has exactly one consumer. A consumer can send messages to the open MAIN
dialog. If a new conversation and dialog is created, Messaging will route to a bot or human agent. An agent can have an agent or manager role. While there can be only one consumer in an open dialog, there can be many agents or agent managers sending messages to the consumer. However, only one agent with the role 'agent' be assigned to a dialog at a time.
Conversations can be created or closed, and each consumer can only have one open conversation at a time. Agents and bots, on the other hand, can respond to multiple conversations. A conversation is closed when the dialog is completed, e.g., the agent has resolved the case and closes the conversation. There are also cases when a conversation is closed by the Messaging system, for example, when a consumer is no longer responding ('auto close').
Conversations can be split into dialogs of different types. The MAIN
dialog is the one that holds the actual messaging exchange, however, depending on the application there could be more dialog types such as CoBrowse or Survey.
Consumers, agents, agent managers, or bots are all identifiable participants in a conversation. Often consumers are not only introduced using an ID but carry additional information, such as name and contact data. This information is sent by using Engagement Attributes.
Prerequisites
Install an application
Manifest example (JSON):
{
"client_name": "App name",
"description": "App description",
"grant_types": [
"client_credentials"
],
"scope": "msg.consumer",
"capabilities": {
"webhooks": {
"ms.MessagingEventNotification.ContentEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"ms.MessagingEventNotification.RichContentEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"ms.MessagingEventNotification.AcceptStatusEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"ms.MessagingEventNotification.ChatStateEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"cqm.ExConversationChangeNotification": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
}
},
"engagement": {
"design_engagement": false,
"design_window": false,
"entry_point": [
"section"
],
"visitor_behavior": [
"visited_location",
"time_on_location",
"flow",
"engaged_in_session",
"about_to_abandon",
"cart_value",
"cart_items",
"visitor_error",
"viewed_products",
"service_activity"
],
"target_audience": [
"external_referral",
"search_keywords",
"ip",
"platform",
"geo_location",
"returning_visitors",
"marketing_source",
"customer_type",
"age",
"balance",
"customer_id",
"gender",
"store_zip_code",
"store_number",
"company_size",
"registration_date"
],
"goal": [
"url",
"purchase_total",
"num_of_pages",
"lead",
"service_activity"
],
"consumer_identity": [
"auth"
],
"language_selection": false
}
}
}
{
"client_name": "App name",
"description": "App description",
"grant_types": [
"client_credentials"
],
"scope": "msg.consumer",
"capabilities": {
"webhooks": {
"ms.MessagingEventNotification.ContentEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"ms.MessagingEventNotification.RichContentEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"ms.MessagingEventNotification.AcceptStatusEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"ms.MessagingEventNotification.ChatStateEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"cqm.ExConversationChangeNotification": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
}
},
"engagement": {
"design_engagement": false,
"design_window": false,
"entry_point": [
"section"
],
"visitor_behavior": [
"visited_location",
"time_on_location",
"flow",
"engaged_in_session",
"about_to_abandon",
"cart_value",
"cart_items",
"visitor_error",
"viewed_products",
"service_activity"
],
"target_audience": [
"external_referral",
"search_keywords",
"ip",
"platform",
"geo_location",
"returning_visitors",
"marketing_source",
"customer_type",
"age",
"balance",
"customer_id",
"gender",
"store_zip_code",
"store_number",
"company_size",
"registration_date"
],
"goal": [
"url",
"purchase_total",
"num_of_pages",
"lead",
"service_activity"
],
"consumer_identity": [
"auth"
],
"language_selection": false
}
}
}
The Connector API uses JSON Web Tokens (JWT) allow access to the API. The JWTs are requested using obtain clientId
and clientSecret
. In order to obtain these intitially you have to register a new LiveEngage application.
You can define several Webhook applications for your account:
Your application is installed using a manifest specified in JSON. An example manifest is shown on the right. The following attibutes should be defined:
Parameter | Description | Mandatory |
---|---|---|
client_name | Name of your connector application | Yes |
description | Client secret of your installed application | No |
webhook | Defines the webhook configuration of your application | Yes |
endpoint | Defines the URL of your webhook endpoint. Must start with HTTPS. | Yes. The notification types are optional. |
max_retries | Number of retries if a notification cannot be delivered to your Webhook endpoint. Max = 5. | No |
engagement | Defines an engagement for your application that will later be used in a campaign | Recommended for reporting |
After filling in the JSON Template with the required data, please contact your Account Management team to register your connector application.
Result
If the application installation is successful you will receive the client id token and the client secret token, which is confidential:
Parameter | Description |
---|---|
client_id | Client id obtained of your installed application. |
client_secret | Client secret of your installed application. |
Modify the endpoint URLs
Once the inital application manifest has been deployed and you have client_id
and client_secret
you can login to the Demo Connector with admin privileges and change the URLs of your webhook endpoints.
Required and optional APIs
Implementing a custom connector requires several LivePerson APIs—depending on functional scope of your server application. Most of the required functionality is covered by Connector API, which is responsible for receiving and sending messages. Consumer messages are encoded as JSON and sent via HTTPS. If an agent or bot answers a notification is sent to your configured Webhook endpoint.
The purpose of the Domain API is to retrieve the base URIs required to authenticate and communicate with Connector API, among others. Enter your account ID here to retrieve your base URIs:
Authentication
The Connector API uses JWTs (JSON Web Token) to control access to the API. After you have obtained a clientId
and clientSecret
by installing an application manifest, you can use these to obtain a secure token, which is subsequently used in all Connector API requests. This token is a JSON Web Token (JWT). A JWT gives you the permission to send messages on behalf of consumers within a LiveEngage account. JWTs are only valid for a specific account and limited time duration.
To authenticate, use this code:
curl -X POST \
'https://${authDomain}/sentinel/api/account/${accountId}/app/token?v=1.0' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}'
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "grant_type=client_credentials&client_id="+ clientId +"&client_secret="+ clientSecret);
Request request = new Request.Builder()
.url("https://"+ authDomain +"/sentinel/api/account/"+ accountId +"/app/token?v=1.0)
.post(body)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build();
Response response = client.newCall(request).execute();
Make sure to replace
${accountId}
,${clientId}
, and${clientId}
with your keys.You receive a response like this:
{
"access_token": "eyJraWQiOiJhcHBqd3QtMTMtMDUtMTciLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiI1MzEzODQ2IiwiYXpwIjoiODJjNzMwNTMtZDc2My00NzUxLTkyNTYtZjNhNzk5YmM1NGM0Iiwic2NvcGUiOiJtc2cuY29uc3VtZXIiLCJpc3MiOiJTZW50aW5lbCIsImV4cCI6MTU1Mjg5OTM3OSwiaWF0IjoxNTUyODk1Nzc5fQ.rbnof2fWnMxFsubazxcGuAqxj04fwp4MgIgh3FjBv1pFoYmXOxCGjrq62x3SIab2Mp4pLdaWKI6UktatIsWK6cNnTvdJ_NQGE4I-8zC-fMk5fRp1CVFbVjxz0bgPeGPVzpWbgJGmhDVQMuqc2rGI8Rk9uP_aRwFDVPVZDOZ1AtAbGMigdjy7tdBD7Lr4w4vvMT6XW7lhHT0MJLJCQLACYAXbM0Q8ZLovq7vk2f-37BiHknP5LmAS1L_jRIL2encOINslYPNTjrPSEusKlJE2qpzbqvBFNlQlg62vzmdAj0xKKglmfOGdNHkKDEgH6haimxxN_LmzIN99Ew0I1ocJWg",
"token_type": "Bearer"
}
{
"access_token": "eyJraWQiOiJhcHBqd3QtMTMtMDUtMTciLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiI1MzEzODQ2IiwiYXpwIjoiODJjNzMwNTMtZDc2My00NzUxLTkyNTYtZjNhNzk5YmM1NGM0Iiwic2NvcGUiOiJtc2cuY29uc3VtZXIiLCJpc3MiOiJTZW50aW5lbCIsImV4cCI6MTU1Mjg5OTM3OSwiaWF0IjoxNTUyODk1Nzc5fQ.rbnof2fWnMxFsubazxcGuAqxj04fwp4MgIgh3FjBv1pFoYmXOxCGjrq62x3SIab2Mp4pLdaWKI6UktatIsWK6cNnTvdJ_NQGE4I-8zC-fMk5fRp1CVFbVjxz0bgPeGPVzpWbgJGmhDVQMuqc2rGI8Rk9uP_aRwFDVPVZDOZ1AtAbGMigdjy7tdBD7Lr4w4vvMT6XW7lhHT0MJLJCQLACYAXbM0Q8ZLovq7vk2f-37BiHknP5LmAS1L_jRIL2encOINslYPNTjrPSEusKlJE2qpzbqvBFNlQlg62vzmdAj0xKKglmfOGdNHkKDEgH6haimxxN_LmzIN99Ew0I1ocJWg",
"token_type": "Bearer"
}
Request a JWT
POST https://${authDomain}/sentinel/api/account/${accountId}/app/token?v=1.0 &grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}
Headers
Key | Value |
---|---|
Content-Type | application/json |
Request
Variable | Description | Mandatory |
---|---|---|
authDomain | CSDS domain of authentication service 'sentinel' | true |
brandId | Your account id | true |
clientId | Client id obtained of your installed application. | true |
clientSecret | Client secret of your installed application. | true |
Response
If the login is successful the connector receives a HTTPS 200 response.
Variable | Description |
---|---|
access_token | JWT |
token_type | Type of the token, i.e., Bearer |
Parse the expiration date from the JWT like this:
echo $LP_JWT | sed -e 's/.*\.\(.*\)\..*/\1/' | base64 --decode | grep -Eo '"exp":(\d*)' | cut -d: -f
echo $LP_JWT | sed -e 's/.*\.\(.*\)\..*/\1/' | base64 --decode | grep -Eo '"exp":(\d*)' | cut -d: -f
String token = "...";
try {
DecodedJWT jwt = JWT.decode(token);
Date expiresAt = jwt.getExpiresAt();
} catch (JWTDecodeException exception){
//Invalid token
}
JWT expiration
JWTs expire after a short time duration such as 1 hour. The expiration timestamp of the JWT can be extracted from the token itself.
In order to retrieve a new JWT before it expires login must be repeated. Subsequently, the newly issued AppJWT is sent with all requests.
Use a JWT
Having obtained a valid JWT, you must set an Authentication
header in all subsequent Connector API HTTPS requests:
Key | Value |
---|---|
Authorization | JWT value |
Consumer identity
The JWT authorizes your connector to perform actions on behalf of a consumer, e.g., to create conversations and send messages. The identity of the consumer itself is defined in a JSON Web Signature (JWS). This token has to be obtained separately, and used in all subsequent requests for a specific consumer.
curl -X POST \
'https://${idpDomain}/api/account/${accountId}/consumer?v=1.0' \
-H 'Authorization: ${JWT} \
-H 'Content-Type: application/json' \
-d '{
"ext_consumer_id": "${consumerId}"
}'
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"ext_consumer_id\":\"vf-random_id0.33113136892746214548813983913\"\n}");
Request request = new Request.Builder()
.url("https://" + idpDomain + "/api/account/"+ accountId +"/consumer?v=1.0")
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", jwt)
.build();
Response response = client.newCall(request).execute();
If succcessful a 201 response is returned with the JWS:
{
"token": "eyJraWQiOiJhcHBqd3QtMTMtMDUtMTciLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhY2NvdW50X2lkIjoiNTMxMzg0NiIsImV4dF9jb25zdW1lcl9pZCI6InZmLXJhbmRvbV9pZDAuNjg5Mjc0NjIxNDM0MTM0MzI0IiwibHBfY29uc3VtZXJfaWQiOiJhYjMxNzNiZDAxY2IyMDAzMjM4YzM5NTI1ZjE5NDQ0MmM2YmQzMmM2YWYwZTZiYjAyZjY1ZGE2MWI5NmI1ZjIyIn0.SoHQAmoNqCxut73EEFgqYX1y5JOD4skDhGpzko8TMcFxFJnwJChvpKwGTRFIpBFfP0JPItqpKNUs7CrwtpZO4GCTZ9nRJXDMgJ6zpL_-8_aJTxDkryWLk4q1NdqJy7KMebFIRCmzGhcmRGiRcJbceqIgX4hkmcY_tSFLQjVk8_oSrw8w_sv1uarOvFn7q-1XX3bt2eTqJDlq1qT7tAwxiaLESWipjX9H3DajmcUlknTcmyLINAZ3FD5bDtKE6Q_wFM43TCK952kCbjUnJN9txblX-Z1D5LHuV3rsKKUYAYDq09A4_D5G8b3RZggF72llsDUc8JS2mFTrmpoh54hVcg"
}
{
"token": "eyJraWQiOiJhcHBqd3QtMTMtMDUtMTciLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhY2NvdW50X2lkIjoiNTMxMzg0NiIsImV4dF9jb25zdW1lcl9pZCI6InZmLXJhbmRvbV9pZDAuNjg5Mjc0NjIxNDM0MTM0MzI0IiwibHBfY29uc3VtZXJfaWQiOiJhYjMxNzNiZDAxY2IyMDAzMjM4YzM5NTI1ZjE5NDQ0MmM2YmQzMmM2YWYwZTZiYjAyZjY1ZGE2MWI5NmI1ZjIyIn0.SoHQAmoNqCxut73EEFgqYX1y5JOD4skDhGpzko8TMcFxFJnwJChvpKwGTRFIpBFfP0JPItqpKNUs7CrwtpZO4GCTZ9nRJXDMgJ6zpL_-8_aJTxDkryWLk4q1NdqJy7KMebFIRCmzGhcmRGiRcJbceqIgX4hkmcY_tSFLQjVk8_oSrw8w_sv1uarOvFn7q-1XX3bt2eTqJDlq1qT7tAwxiaLESWipjX9H3DajmcUlknTcmyLINAZ3FD5bDtKE6Q_wFM43TCK952kCbjUnJN9txblX-Z1D5LHuV3rsKKUYAYDq09A4_D5G8b3RZggF72llsDUc8JS2mFTrmpoh54hVcg"
}
Retrieve a JWS
Use the domain API to retrieve the domain of the LivePerson IDP service. The accountId
is specified as a variable in the path.
Request
POST https://${idpDomain}/api/account/${accountId}/consumer?v=1.0'
Headers
Key | Value |
---|---|
Authorization | JWT value |
Content-Type | application/json |
Request body
The request body defines the consumer's id in ext_consumer_id
:
Response
If the request is successful a HTTPS 201 Created
is returned with the JWS token
in the body.
Use the JWS
Having obtained a valid JWS, you must set an X-LP-ON-BEHALF
header in all subsequent requests to Connector API:
Key | Value |
---|---|
X-LP-ON-BEHALF | JWS value |
Authorization | JWT value |
Content-Type | application/json |
Conversation
Create a conversation
curl -X POST \
'https://va-at.msg.liveperson.net/api/account/5313846/messaging/consumer/conversation?v=3' \
-H 'Content-Type: application/json' \
-H 'Authorization: ${JWT}' \
-H 'X-LP-ON-BEHALF: ${JWS}' \
-d '[{
"kind": "req",
"id": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57",
"type": "userprofile.SetUserProfile",
"body": {
"authenticatedData": {
"lp_sdes": [
{
"type": "ctmrinfo",
"info": {
"customerId": "138766AZE",
"socialId": "1125632",
"imei": "35433545688",
"userName": "user000"
}
},
{
"type": "personal",
"personal": {
"firstname": "John",
"lastname": "Doe"
}
}
]
}
}
},
{
"kind": "req",
"id": "533575ec-b092-4ea6-ba13-25a98095e79f",
"type": "cm.ConsumerRequestConversation",
"body": {
"channelType": "MESSAGING",
"brandId": "${accountId}"
}
}
]'
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "[{
"kind": "req",
"id": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57",
"type": "userprofile.SetUserProfile",
"body": {
"authenticatedData": {
"lp_sdes": [
{
"type": "ctmrinfo",
"info": {
"customerId": "138766AZE",
"socialId": "1125632",
"imei": "35433545688",
"userName": "user000"
}
},
{
"type": "personal",
"personal": {
"firstname": "John",
"lastname": "Doe"
}
}
]
}
}
},
{
"kind": "req",
"id": "533575ec-b092-4ea6-ba13-25a98095e79f",
"type": "cm.ConsumerRequestConversation",
"body": {
"channelType": "MESSAGING",
"brandId": accountId
}
}
]");
Request request = new Request.Builder()
.url("https://va-at.msg.liveperson.net/api/account/5313846/messaging/consumer/conversation?v=3")
.post(body)
.addHeader("Authorization", jwt)
.addHeader("X-LP-ON-BEHALF", jws)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
If succcessful a 200 response is returned:
[
{
"code": "OK",
"body": {
"msg": "OK User Profile set successfully"
},
"reqId": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57"
},
{
"code": "OK",
"body": {
"conversationId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747"
},
"reqId": "533575ec-b092-4ea6-ba13-25a98095e79f"
}
]
[
{
"code": "OK",
"body": {
"msg": "OK User Profile set successfully"
},
"reqId": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57"
},
{
"code": "OK",
"body": {
"conversationId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747"
},
"reqId": "533575ec-b092-4ea6-ba13-25a98095e79f"
}
]
A new conversation is created by sending a HTTPS POST request to the Connector API /conversation
endpoint. The URL includes the domain of the Messaging Service and the accountId
. The query parameter v=3
specifies the API version. In the HTTP headers both the authentication JWT and consumer JWS must be included.
Every event has a type
and an id
. To generate the id
in each request please use a UUID library of your choice to automatically generate an ID that adheres to the Universally Unique Identifier (UUID) v4 standard.
Request
POST https://${messagingDomain}/api/account/${accountId}/messaging/consumer/conversation?v=3
HTTPS headers
Key | Value |
---|---|
X-LP-ON-BEHALF | JWS value |
Authorization | JWT value |
Content-Type | application/json |
Payload
The request payload is an array containing the following payloads. The payloads is ordered in a JSON array as follows:
Request object | Description | Mandatory |
---|---|---|
userprofile.SetUserProfile | Set the user profile. lp-sdes defines engagement attributes that can hold customer type=ctmrinfo or personal type=personal information |
true |
cm.ConsumerRequestConversation | Request a conversation | true |
The allowed Engagement Attributes are ctmrinfo
and personal
.
Response
If successsul a 200 response is returned with a JSON array in the same order as the events in the request. In the second response object the conversationId
is wrapped as part of the body. The connector will subsequently use this conversationId
for in all messages for this consumer.
Create a conversation with skill routing
curl -X POST \
'https://${messagingDomain}/api/account/${accountId}/messaging/consumer/conversation?v=3' \
-H 'Content-Type: application/json' \
-H 'Authorization: ${JWT}' \
-H 'X-LP-ON-BEHALF: ${JWS}' \
-d '[{
"kind": "req",
"id": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57",
"type": "userprofile.SetUserProfile",
"body": {
"authenticatedData": {
"lp_sdes": [
{
"type": "personal",
"personal": {
"firstname": "John",
"lastname": "Doe"
}
}
]
}
}
},
{
"kind": "req",
"id": "533575ec-b092-4ea6-ba13-25a98095e79f",
"type": "cm.ConsumerRequestConversation",
"body": {
"channelType": "MESSAGING",
"brandId": "${accountId}"
"campaignInfo": {
"campaignId": "${campaignId}",
"engagementId": "${engagementId}"
}
}
}
]'
If succcessful a 200 response is returned:
[
{
"code": "OK",
"body": {
"msg": "OK User Profile set successfully"
},
"reqId": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57"
},
{
"code": "OK",
"body": {
"conversationId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747"
},
"reqId": "533575ec-b092-4ea6-ba13-25a98095e79f"
}
]
[
{
"code": "OK",
"body": {
"msg": "OK User Profile set successfully"
},
"reqId": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57"
},
{
"code": "OK",
"body": {
"conversationId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747"
},
"reqId": "533575ec-b092-4ea6-ba13-25a98095e79f"
}
]
Skill routing is decided upon conversation creation. If you are planning to route a consumer to a specific skill then you should use a campaign with engagement for this.
It is recommended to set up skill routing with an engagement and campaign. For this, it is required to add a conversationContext
object to the request. It specifies the engagementId
and campaignId
. If you do not have a campaign defined yet, you should create one for the connector.
Campaigns and engagement can be created in two different ways:
Programatically with the Mononitoring API
Manually with the "Campaign" tab in LiveEngage
In LiveEngage, the engagementId
and campaignId
are shown as seen below:
Conversation already exists
If a conversation already exists you will receive a response like this:
[
{
"code": "OK",
"body": {
"msg": "OK User Profile set successfully"
},
"reqId": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57"
},
{
"code": "BAD_REQUEST",
"body": {
"msg": "Consumer request conversation failed: User 77d338e4b6bf02affbf9bf00a779cbf06b0fcd7fb1674028e8739acdfa6ae7a2 already has open conversation. Can't open another one."
},
"reqId": "533575ec-b092-4ea6-ba13-25a98095e79f"
}
]
[
{
"code": "OK",
"body": {
"msg": "OK User Profile set successfully"
},
"reqId": "4b91dd19-9b0c-4354-8fef-4f58a45a9c57"
},
{
"code": "BAD_REQUEST",
"body": {
"msg": "Consumer request conversation failed: User 77d338e4b6bf02affbf9bf00a779cbf06b0fcd7fb1674028e8739acdfa6ae7a2 already has open conversation. Can't open another one."
},
"reqId": "533575ec-b092-4ea6-ba13-25a98095e79f"
}
]
If a conversation already exists a 400 Bad Request
response is returned. It is expected that the conversationId
is managed by the connector.
Close conversation
A conversation is closed by sending a state update event:
curl -X POST \
'https://${messagingDomain}/api/account/${accountId}/messaging/consumer/conversation/send?v=3' \
-H 'Content-Type: application/json' \
-H 'Authorization: ${JWT}' \
-H 'X-LP-ON-BEHALF: ${JWS}' \
-d '{
"kind": "req",
"id": "c4255004-9c50-4405-8cba-475d761fab1b",
"body": {
"conversationId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747",
"conversationField": {
"field": "ConversationStateField",
"conversationState": "CLOSE"
}
},
"type": "cm.UpdateConversationField"
}'
You get the following response if successfull:
{
"code": "OK",
"body": {
"msg": "OK Conversation resolved successfully"
},
"reqId": "c4255004-9c50-4405-8cba-475d761fab1b"
}
{
"code": "OK",
"body": {
"msg": "OK Conversation resolved successfully"
},
"reqId": "c4255004-9c50-4405-8cba-475d761fab1b"
}
A custom connector can close a conversation at any time. Typically, conversations are closed when the consumer's request is resolved. Because many Messaging apps do not have a notion of "close" or "resolve" you may choose not to close conversations by the connector at all. However, it is still possible that an agent or the system closes a conversation state—conversation state changes by other participants are tracked by analyzing Webhook notifcations.
Request
POST https://${messagingDomain}/api/account/${accountId}/messaging/consumer/conversation/send?v=3'
HTTPS headers
Key | Value |
---|---|
X-LP-ON-BEHALF | JWS value |
Authorization | JWT value |
Content-Type | application/json |
Payload
The request payload is an array containing the following payloads. The payloads is ordered in a JSON array as follows:
Request object | Description | Mandatory |
---|---|---|
cm.UpdateConversationField | Updates the conversation state in the body field. Required inputs are the conversationId and conversationField with the conversationState = "CLOSE" |
true |
Response
If successsul a 200 OK
response is returned with code="OK"
in the JSON response body.
Resume a closed conversation
You get the following error message when trying to send a message into a closed conversation:
"code": "BAD_REQUEST",
"body": {
"msg": "Bad Request, Conversation is close"
},
"reqId": "c4255004-9c50-4405-8cba-475d761fab1b"
}
"code": "BAD_REQUEST",
"body": {
"msg": "Bad Request, Conversation is close"
},
"reqId": "c4255004-9c50-4405-8cba-475d761fab1b"
}
A conversation can be closed by consumer, agent, or automatically closed by the Messaging system. State changes are tracked by your WebHook endpoint listening to cqm.ExConversationChangeNotification
. When a state change is observed, update the client's internal state accordingly. If your client has not updated its internal state but tries to send a consumer message, it will receive a BAD_REQUEST
error message. In this case, it is required to open a new conversation to send new messages.
Send a message
Send a plain text message:
curl -X POST \
'https://${messagingDomain}/api/account/${accountId}/messaging/consumer/conversation/send?v=3' \
-H 'Authorization: ${JWT}' \
-H 'X-LP-ON-BEHALF: ${JWS}' \
-H 'Content-Type: application/json' \
-d '{
"kind": "req",
"type": "ms.PublishEvent",
"id": "1556852a-4bb3-11e9-8646-d663bd873d93",
"body": {
"conversationId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747",
"dialogId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747",
"event": {
"type": "ContentEvent",
"contentType": "text/plain",
"message": Hello world!"
}
}
}'
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{
"kind": "req",
"type": "ms.PublishEvent",
"id": "1556852a-4bb3-11e9-8646-d663bd873d93",
"body": {
"conversationId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747",
"dialogId": "cbf6e739-dfe6-4e3c-a544-2504afbe8747",
"event": {
"type": "ContentEvent",
"contentType": "text/plain",
"message": Hello world!"
}
}
}");
Request request = new Request.Builder()
.url("https://"+ messagingDomain +"/api/account/"+ accountId +"/messaging/consumer/conversation/send?v=3")
.post(body)
.addHeader("Authorization", jwt)
.addHeader("X-LP-ON-BEHALF", jws)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
A
200 OK
with the following JSON response is returned:
{
"code": "OK",
"body": {
"sequence": 0
},
"reqId": "1556852a-4bb3-11e9-8646-d663bd873d93"
}
{
"code": "OK",
"body": {
"sequence": 0
},
"reqId": "1556852a-4bb3-11e9-8646-d663bd873d93"
}
The Connector API /send
endpoint is used to send messages in an open conversation. A text message is published by sending a PublishEvent
event object.
Request
POST https://${messagingDomain}/api/account/${accountId}/messaging/consumer/conversation/send?v=3
HTTPS headers
Key | Value |
---|---|
X-LP-ON-BEHALF | JWS value |
Authorization | JWT value |
Content-Type | application/json |
Payload
Request object | Description | Mandatory |
---|---|---|
ms.PublishEvent | Event type for publishing messages in a conversation the contentType text/plain indicates a text event | true |
The request object defines both a conversationId
and dialogId
. When a conversation is opened, the system automatically creates a MAIN dialog with the same id. Depending on the functional scope there may multiple dialogs. For example, if a survey is initiated the MAIN dialog is closed and a new dialog POST_SURVEY is opened. If your connector shall support surveys, it has track conversation and dialog changes using Webhook notifications.
Response
Attribute | Description |
---|---|
code | 'OK' indicates that the message is successfully sent |
reqId | The request id in the response |
sequenceId | ordered no. of the message within the conversation, the first message's sequenceId is 0 |
If a message exceeds the maximum size a
400 Bad Request
is returned:
{
"code": "BAD_REQUEST",
"body": {
"msg": "Bad Request"
},
"reqId": "1556852a-4bb3-11e9-8646-d663bd873d93"
}
{
"code": "BAD_REQUEST",
"body": {
"msg": "Bad Request"
},
"reqId": "1556852a-4bb3-11e9-8646-d663bd873d93"
}
Webhooks
Connector API /conversation
and /send
endpoints provide you with the means to send consumer messages to LiveEngage Messaging. If you want to receive updates on a conversation, e.g. messages sent by an agent, you have to expose a public HTTPS POST Webhook endpoint to receive those notifications.
Requirements
The Webhook notifications are sent as POST requests over SSL only (HTTPS). The application endpoint is required to be set up with a valid web-server TLS/SSL certificate.
The application endpoint is expected to immediately respond to each a notification request. A response delay can lead to a timeout of that notification request.
The application endpoint is expected to respond with either a 200 OK
or 201 Created
HTTPS response code to each a notification request. Any other response code will be considered as a notification request failure.
Authentication
Authentication is verified by your Webhook endpoint based on the clientId
and clientSecret
of your Webhook notification. For authentication it is required to analyze all HTTPS POST request headers and check the SHA1 signature of the payload using clientSecret
as the key.
Request headers
Header | Description |
---|---|
x-liveperson-account-id | The unique LivePerson account identifier. Can be used to differentiate registration of different accounts, when the same url is used for multiple accounts. |
x-liveperson-client-id | The unique client application identifier. The client_id that the consumer receives from their account manager after the App Installation process. |
x-liveperson-signature | A token generated by signing the payload using the client-secret. A SHA1 signature of the payload and the client_secret (given by the account manager in the Application Installation process) preceded with “sha1=”. |
Notification types
The notification types that your connector subscribes to as defined in the application manifest .
Notification type | Description |
---|---|
cqm.ExConversationChangeNotification | Notification on conversation state changes, e.g. a conversation is created, a participant (consumer or agent) has changed, a conversation is closed, or the CSAT score is updated. |
ms.MessagingEventNotification.ContentEvent | Notification on text-based messages in a conversation. This includes messages by all participants, agents and consumers. |
ms.MessagingEventNotification.RichContentEvent | Notification on messages with Rich Content (a.k.a Structured Content) in a conversation. |
ms.MessagingEventNotification.AcceptStatusEvent | Notification on status events, e.g. a participant accepted or read one to many messages. |
ms.MessagingEventNotification.ChatStateEvent | Notification on the activity state of a participant. For example, the notification indicates whether a participant is composing a message, becomes active or inactive. |
Conversation created
A new conversation is created:
{
"kind":"notification",
"body":{
"subscriptionId":"ea7ecc5a-58c4-4a16-9510-4868bef08d79",
"changes":[
{
"type":"UPSERT",
"result":{
"convId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"effectiveTTR":1553590349893,
"conversationDetails":{
"skillId":"558327413",
"participants":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER"
}
],
"dialogs":[
{
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"participantsDetails":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER",
"state":"ACTIVE"
}
],
"dialogType":"MAIN",
"channelType":"MESSAGING",
"state":"OPEN",
"creationTs":1553589749650,
"metaDataLastUpdateTs":1553589749650
}
],
"brandId":"${accountId}",
"state":"OPEN",
"stage":"OPEN",
"startTs":1553589749650,
"metaDataLastUpdateTs":1553589749650,
"ttr":{
"ttrType":"PRIORITIZED",
"value":600
},
"conversationHandlerDetails":{
"accountId":"${accountId}",
"skillId":"558327413"
}
}
}
}
]
},
"type":"cqm.ExConversationChangeNotification"
}
{
"kind":"notification",
"body":{
"subscriptionId":"ea7ecc5a-58c4-4a16-9510-4868bef08d79",
"changes":[
{
"type":"UPSERT",
"result":{
"convId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"effectiveTTR":1553590349893,
"conversationDetails":{
"skillId":"558327413",
"participants":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER"
}
],
"dialogs":[
{
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"participantsDetails":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER",
"state":"ACTIVE"
}
],
"dialogType":"MAIN",
"channelType":"MESSAGING",
"state":"OPEN",
"creationTs":1553589749650,
"metaDataLastUpdateTs":1553589749650
}
],
"brandId":"${accountId}",
"state":"OPEN",
"stage":"OPEN",
"startTs":1553589749650,
"metaDataLastUpdateTs":1553589749650,
"ttr":{
"ttrType":"PRIORITIZED",
"value":600
},
"conversationHandlerDetails":{
"accountId":"${accountId}",
"skillId":"558327413"
}
}
}
}
]
},
"type":"cqm.ExConversationChangeNotification"
}
If the application subscribes to ExConversationChangeNotification
events, the webhook endpoint receives the following payload after a conversation was successfully created.
Name | Value | Description |
---|---|---|
kind | notification | Defines payload as 'notification' |
type | cqm.ExConversationChangeNotification | Describes the type of notification |
body | changes | Changes as an array of state updates |
convId | uuid | The unique identifier of the conversation. The value equals the dialogId value with dialogType MAIN defined within the same object |
stage | OPEN | Defines the inital state of the conversation as OPEN |
Agent joined
Agent is added as a new participant to the conversation:
{
"kind":"notification",
"body":{
"subscriptionId":"ea7ecc5a-58c4-4a16-9510-4868bef08d79",
"changes":[
{
"type":"UPSERT",
"result":{
"convId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"effectiveTTR":1553590349893,
"conversationDetails":{
"skillId":"558327413",
"participants":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER"
},
{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT"
}
],
"dialogs":[
{
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"participantsDetails":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER",
"state":"ACTIVE"
},
{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT",
"state":"ACTIVE"
}
],
"dialogType":"MAIN",
"channelType":"MESSAGING",
"state":"OPEN",
"creationTs":1553589749650,
"metaDataLastUpdateTs":1553589749650
}
],
"brandId":"${accountId}",
"state":"OPEN",
"stage":"OPEN",
"startTs":1553589749650,
"metaDataLastUpdateTs":1553590954025,
"ttr":{
"ttrType":"PRIORITIZED",
"value":600
},
"conversationHandlerDetails":{
"accountId":"${accountId}",
"skillId":"558327413"
}
}
}
}
]
},
"type":"cqm.ExConversationChangeNotification"
}
{
"kind":"notification",
"body":{
"subscriptionId":"ea7ecc5a-58c4-4a16-9510-4868bef08d79",
"changes":[
{
"type":"UPSERT",
"result":{
"convId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"effectiveTTR":1553590349893,
"conversationDetails":{
"skillId":"558327413",
"participants":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER"
},
{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT"
}
],
"dialogs":[
{
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"participantsDetails":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER",
"state":"ACTIVE"
},
{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT",
"state":"ACTIVE"
}
],
"dialogType":"MAIN",
"channelType":"MESSAGING",
"state":"OPEN",
"creationTs":1553589749650,
"metaDataLastUpdateTs":1553589749650
}
],
"brandId":"${accountId}",
"state":"OPEN",
"stage":"OPEN",
"startTs":1553589749650,
"metaDataLastUpdateTs":1553590954025,
"ttr":{
"ttrType":"PRIORITIZED",
"value":600
},
"conversationHandlerDetails":{
"accountId":"${accountId}",
"skillId":"558327413"
}
}
}
}
]
},
"type":"cqm.ExConversationChangeNotification"
}
When an agent joins a conversation, this triggers an cqm.ExConversationChangeNotification
update.
Name | Value | Description |
---|---|---|
kind | notification | Defines payload as 'notification' |
type | cqm.ExConversationChangeNotification | Describes the type of notification |
body | changes | Changes as an array of state updates |
stage | OPEN | Defines the inital state of the conversation as OPEN |
participants | ARRAY | Adds a participant with the role ASSIGNED_AGENT, AGENT_MANAGER, or ASSIGNED_MANAGER. Other possible roles are CONSUMER, READER, and CONTROLLER. |
Message by agent
Agent sends text message
{
"kind":"notification",
"body":{
"changes":[
{
"sequence":5,
"originatorId":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"originatorMetadata":{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT"
},
"serverTimestamp":1553593406049,
"event":{
"type":"ContentEvent",
"message":"This is a reply!",
"contentType":"text/plain"
},
"conversationId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6"
}
]
},
"type":"ms.MessagingEventNotification"
}
{
"kind":"notification",
"body":{
"changes":[
{
"sequence":5,
"originatorId":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"originatorMetadata":{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT"
},
"serverTimestamp":1553593406049,
"event":{
"type":"ContentEvent",
"message":"This is a reply!",
"contentType":"text/plain"
},
"conversationId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6"
}
]
},
"type":"ms.MessagingEventNotification"
}
When an agent sends a message to a conversation, a ms.MessagingEventNotification
is triggered.
Name | Value | Description |
---|---|---|
kind | notification | Defines payload as 'notification' |
type | ms.MessagingEventNotification | Describes the type of notification |
body | changes | Changes as an array of state updates |
sequence | NUM VALUE | The sequence number of this message in this conversation |
originatorId | UUID | The originator of this message update |
event.type | ContentEvent | The type of the event |
event.contentType | text/plain | Content type of the event |
event.message | STRING VALUE | The actual message content |
conversationId | UUID | The unique identifier of the conversation |
dialogId | UUID | The unique identifier of the dialog in which the message was sent. Implicitly, dialogId and conversationId are the same for the MAIN dialog. |
Skill transfer
Conversation is transferred to another skill:
{
"kind":"notification",
"body":{
"subscriptionId":"ea7ecc5a-58c4-4a16-9510-4868bef08d79",
"changes":[
{
"type":"UPSERT",
"result":{
"convId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"effectiveTTR":1553598420199,
"conversationDetails":{
"skillId":"99999999",
"participants":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER"
}
],
"dialogs":[
{
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"participantsDetails":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER",
"state":"ACTIVE"
}
],
"dialogType":"MAIN",
"channelType":"MESSAGING",
"state":"OPEN",
"creationTs":1553589749650,
"metaDataLastUpdateTs":1553589749650
}
],
"brandId":"${accountId}",
"state":"OPEN",
"stage":"OPEN",
"startTs":1553589749650,
"metaDataLastUpdateTs":1553597820083,
"ttr":{
"ttrType":"PRIORITIZED",
"value":600
},
"conversationHandlerDetails":{
"accountId":"${accountId}",
"skillId":"99999999"
}
}
}
}
]
},
"type":"cqm.ExConversationChangeNotification"
}
{
"kind":"notification",
"body":{
"subscriptionId":"ea7ecc5a-58c4-4a16-9510-4868bef08d79",
"changes":[
{
"type":"UPSERT",
"result":{
"convId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"effectiveTTR":1553598420199,
"conversationDetails":{
"skillId":"99999999",
"participants":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER"
}
],
"dialogs":[
{
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"participantsDetails":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER",
"state":"ACTIVE"
}
],
"dialogType":"MAIN",
"channelType":"MESSAGING",
"state":"OPEN",
"creationTs":1553589749650,
"metaDataLastUpdateTs":1553589749650
}
],
"brandId":"${accountId}",
"state":"OPEN",
"stage":"OPEN",
"startTs":1553589749650,
"metaDataLastUpdateTs":1553597820083,
"ttr":{
"ttrType":"PRIORITIZED",
"value":600
},
"conversationHandlerDetails":{
"accountId":"${accountId}",
"skillId":"99999999"
}
}
}
}
]
},
"type":"cqm.ExConversationChangeNotification"
}
A skill transfer consists of two state changes in the notification: the agent is removed as a participant and the skill id is updated.
Name | Value | Description |
---|---|---|
kind | notification | Defines payload as 'notification' |
type | cqm.ExConversationChangeNotification | Describes the type of notification |
body | changes | Changes as an array of state updates |
conversationId | UUID | The unique identifier of the conversation |
skillId | NUM VALUE | The updated skill id |
participants | ARRAY | The updated list of participants. In this case, the participant list only includes the consumer because the agent is removed as a participant as part of the transfer |
Conversation closed by agent
{
"kind":"notification",
"body":{
"subscriptionId":"0ce06a28-455d-4a31-81f1-e3a9de585e43",
"changes":[
{
"type":"UPSERT",
"result":{
"convId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"effectiveTTR":-1,
"conversationDetails":{
"skillId":"558327413",
"participants":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER"
},
{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT"
}
],
"dialogs":[
{
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"participantsDetails":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER",
"state":"ACTIVE"
},
{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT",
"state":"ACTIVE"
}
],
"dialogType":"MAIN",
"channelType":"MESSAGING",
"state":"CLOSE",
"creationTs":1553589749650,
"endTs":1553599771074,
"metaDataLastUpdateTs":1553599771074,
"closedBy":"AGENT"
}
],
"brandId":"5313846",
"state":"CLOSE",
"stage":"CLOSE",
"closeReason":"AGENT",
"startTs":1553589749650,
"metaDataLastUpdateTs":1553599771074,
"ttr":{
"ttrType":"PRIORITIZED",
"value":600
},
"conversationHandlerDetails":{
"accountId":"5313846",
"skillId":"558327413"
}
}
}
}
]
},
"type":"cqm.ExConversationChangeNotification"
}
{
"kind":"notification",
"body":{
"subscriptionId":"0ce06a28-455d-4a31-81f1-e3a9de585e43",
"changes":[
{
"type":"UPSERT",
"result":{
"convId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"effectiveTTR":-1,
"conversationDetails":{
"skillId":"558327413",
"participants":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER"
},
{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT"
}
],
"dialogs":[
{
"dialogId":"f2384f56-57d5-4087-bd47-8df0ec3102f6",
"participantsDetails":[
{
"id":"5b0f3b3574c1a8eb71aebf79cf437cb3f6010b9a6df94771c22e5c637285f5f2",
"role":"CONSUMER",
"state":"ACTIVE"
},
{
"id":"e9b2867c-f984-5727-b034-fc9c6800bd9c",
"role":"ASSIGNED_AGENT",
"state":"ACTIVE"
}
],
"dialogType":"MAIN",
"channelType":"MESSAGING",
"state":"CLOSE",
"creationTs":1553589749650,
"endTs":1553599771074,
"metaDataLastUpdateTs":1553599771074,
"closedBy":"AGENT"
}
],
"brandId":"5313846",
"state":"CLOSE",
"stage":"CLOSE",
"closeReason":"AGENT",
"startTs":1553589749650,
"metaDataLastUpdateTs":1553599771074,
"ttr":{
"ttrType":"PRIORITIZED",
"value":600
},
"conversationHandlerDetails":{
"accountId":"5313846",
"skillId":"558327413"
}
}
}
}
]
},
"type":"cqm.ExConversationChangeNotification"
}
Name | Value | Description |
---|---|---|
kind | notification | Defines payload as 'notification' |
type | cqm.ExConversationChangeNotification | Describes the type of notification |
body | changes | Changes as an array of state updates |
conversationId | UUID | The unique identifier of the conversation |
stage | CLOSED | Defines the state of the conversation as CLOSED |
participants | ARRAY | The updated list of participants. In this case, the participant list only includes the consumer because the agent is removed as a participant as part of the transfer |