The aim of this document is to collect all useful technical information about the Connector API and its implementation and use in LivePerson projects, helping engineers and developers to understand well the basic concepts and what is possible to offer to clients.
Terminology
Term | Meaning |
---|
Kafka | Cluster of servers that can handle hundreds of megabytes of reads and writes per second. It receives events created in the system, being the central data backbone of LivePerson. |
Send API | REST interface that allows consumers to establish conversations via REST interface to UMS. |
Messaging Window API | Protocol that allows complete control over the messaging window look, behavior and implementation source.
It leverages peripheral REST APIs – like Domain Discovery, Token creation, Agent Profile – and Messaging API, that helps establish the WebSocket connection between the Messaging Window and LivePerson’s UMS Messaging service. |
Messaging API | WebSocket interface with which is possible to connect to the UMS Messaging service, creating and maintaining conversations. |
Webhooks Notification Service | Channel with which Conversational Cloud sends messaging related events to the connector application (forwards UMS events to the configured endpoints). |
Connector application | Brands’ custom app which implements the Connector API to enable their external messaging source with Conversational Cloud. |
AppJWT | Json Web Token which contains the OAuth2.0 bearer token to be used within the Connector API’s calls. AppJWT is used to request a ConsumerJWS for each identifiable consumer. |
ConsumerJWS | Unique token which identifies the brand’s consumer along their custom identifier in their Conversational Cloud account. |
External Consumer ID | Brands’ unique custom identifier for their consumers. |
LivePerson Consumer ID | Conversational Cloud default unique consumer identifier. |
What is the Connector API?
The Connector API enables developers to build applications that connect common messaging channels with Conversational Cloud.
A connector is a broker between Conversational Cloud data and a messaging channel's messages and data. The connector receives messages and events from a messaging platform, transforms them into the Conversational Cloud language and passes it to the agent.
The Connector API allows to create/open and close conversations, pass messages to and from the agents, set the consumer profile upon conversation creation.
In addition, the connector can also make sure that the consumer will be notified of agent activity during the conversation, and vice versa, using Webhooks notifications.
From brands perspective, the Connector API consists of two main components:
- Send API: with which is possible to send HTTPS requests based on the Messaging Window API framework. This component of the Connector API handles communication between the Connector and Conversational Cloud, allowing to communicate events from the third party application to Conversational Cloud.
- Webhooks Notification Service: this component sends notifications from Conversational Cloud based on the Messaging Window API framework to the connector Webhooks HTTPS-endpoints. These notifications communicate any messaging events both from the agent and consumer to the connector, such as agent/consumer replies, closed conversation, typing and so on.
Why do we use the Connector API?
By providing brands the Connector API, we allow them to keep their messaging implementations - external bot, custom messaging source connectors - outside of LivePerson.
For example: a brand can have a bot talking to a consumer on a given channel with no involvement from LivePerson. When the bot needs a human to be involved, it can use the Connector API to create a conversation and inform LivePerson of any consumer messages.
Indeed, there are two primary reasons / use cases to utilize the Connector API:
- Brands - To create their own custom connectors. This will enable their consumers to engage with them via many distribution channels whilst using more than one device, not using our out of the box dedicated connectors. Another example would be a connector for an SMS Gateway of their choice, different from Twilio. A connector developed by a brand would normally be hosted on the brand's servers.
- Product solutions - Connector applications developed by LivePerson, focusing on the same functionalities as the above use case except that we are providing it to them. In this case, our deliverables will be hosted by our cloud solutions.
Here below and example of Connector API solution:
Pros and cons
Here are summarized the positive and negative consequences of brand adopting of Connector API:
Pros | Cons |
---|
Cheaper for the brand as they don’t pay credits for conversations that were fully resolved by the bot. | LivePerson makes less earnings from bots being outside of the platform. |
The Connector API works with any and every platform and technology stack |
|
Not much work on LivePerson side outside of consulting |
|
Capabilities enabled by the Connector API
Consumer side
Capability | Achieved by | Endpoint |
---|
Create a new conversation and send SDEs in one step | Messaging SEND API | CONVERSATION |
Send text messages | Messaging SEND API | SEND |
Send images | Messaging SEND API | SEND |
See SENT, READ and RECEIVED indications | Webhooks | N/A |
Send chat state events (COMPOSING (i.e. Consumer is typing), ACTIVE, INACTIVE etc.) | Messaging SEND API | SEND |
See chat state events (COMPOSING (i.e. Agent is typing), ACTIVE, INACTIVE etc.) | Webhooks | N/A |
Send conversation metadata - Structured content identifier metadata | Messaging SEND API | SEND |
Close conversation | Messaging SEND API | SEND |
Send CSAT (Customer Satisfaction) & FCR (First Contact Resolution) ratings | Messaging SEND API | SEND |
Agent side
Being the Connector API implementation dedicated only for applications/connectors on the consumer side, the below agent capabilities are the ones already provided out of the box by Conversational Cloud and the Agent Workspace. Connector API currently support all of these:
- Resume a conversation
- Transfer a conversation to a different skill
- Send a text message
- Send structured content
- See SENT, READ and RECEIVED indications
- See indication that the consumer is typing
- Close a conversation
In other words, the Connector API brings new functionality (via the Messaging Send API and Webhooks) only to the consumer side. On the agent side, it simply supports some of the already existing Conversational Cloud capabilities and allows them to be used in connector applications.
Technical Details [LivePerson]
From LivePerson developers point of view, Connector API consist of:
- The inbound channel, represented by the Send API
- The outbound channel, done by the WebHooks Notification Service
The configuration service, containing the configuration with Houston.
The must-have dependencies are AppJWT and AC AppInstall.
Here below the high level architecture of the Connector API:
javascript:
{
"client_name": "App name",
"description": "App description",
"grant_types": [
"client_credentials"
],
"scope": "msg.consumer",
"logo_uri": "/src/modules/campaigns/assets/img/software/Mobile-App.png",
"capabilities": {
"webhooks": {
"ms.MessagingEventNotification.ContentEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 3
},
"ms.MessagingEventNotification.RichContentEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 5
},
"ms.MessagingEventNotification.AcceptStatusEvent": {
"endpoint": "https://your/webhooks/endpoint",
"max_retries": 1
},
"ms.MessagingEventNotification.ChatStateEvent": {
"endpoint": "https://your/webhooks/endpoint"
},
"cqm.ExConversationChangeNotification": {
"endpoint": "https://your/webhooks/endpoint"
}
},
"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
}
}
}
1 - Onboard the connector [Brand + LivePerson]
The connector is a server application used to make HTTPS calls on behalf of consumers to Conversational Cloud. For that purpose, the application must be registered and known to Conversational Cloud for authorization and user validation. This process can happen even before any connector development.
In order to register the application, brands should contact us: they need to provide details regarding their connector application, via a predetermined JSON schema (known as the Application Installation Manifest).
Here the Application Installation Manifest JSON template to be filled by the brand:
The main sections to be filled are:
client_name
- name of brand’s Connector Application. This will also be shown to the agent as the source of the conversation in the Consumer Info widget.description
- optional key.- Webhooks URL endpoints - these will be used as URL endpoints for Conversational Cloud to send its notification events to the brand's connector. Note: these endpoints must be exposed as HTTPS.
max_retries
- optional key. Used to configure the maximum number of retries which our Webhooks service will attempt in case of a failed request.- Engagement related fields - this affects the Engagement design possibilities when designing a campaign for messaging. Without a clear reason to change them, brands can use the default values found in the schema.
After the brand completes the JSON Template with the required data, the LivePerson team will register that connector application.
As an alternative to writing the whole JSON payload, brands can login into the Connector Hub using their account Id credentials. In this page, is it possible to create the Connector application using our UI, specifying step by step the data needed.
With this tool, brands can autonomously get their App credentials without involving the LivePerson engineering team, so the next step 2 can be avoided.
2 - Creating the brand application on Houston [LivePerson]
You must reach out to your LivePerson Account Manager to configure on Houston.
3 - Getting an application JWT [Brand]
LivePerson uses OAuth 2.0 grant type Client Credentials in order to allow apps to access the Send API. The responsible Authorization Server Sentinel generates access tokens for any rightfully authorized client. The access token is a JSON Web Token (JWT) encoding information about the granted access and must be attached to any follow-up request to the Send API. The AppJWT identifies the connector to be a valid application, which is allowed to identify consumers and send consumer events to the messaging service.
So, after LivePerson successfully registered the connector, brands will receive two important parameter values which will serve to authorize the connector application prior to using the Connector API:
- The app installation id, also named as
client_id
- Example value
75588e18-0213-4e33-8174-883acac7e3c4
- The app secret, also named as
client_secret
- Example value
kgvbkk7glku72jgtmpi6l4a872
These will be used for the first authorization request to Conversational Cloud in order to identify the brand connector and provide it with an AppJWT.
Here below the HTTPS request to get the AppJWT token:
Method: POST
URL:
https://{{sentinelDomain}}/sentinel/api/account/{{accountID}}/app/token?v=1.0&grant_type=client_credentials&client_id={{client_id}}&client_secret={{client_secret}}
Content-Type: application/x-www-form-urlencoded
|
---|
|
sentinelDomain
is retrievable from Domain API searching for sentinel
The sentinel service will answer in accordance with OAuth 2.0, providing the AppJWT as a bearer token, in this form:
{
"access_token": "----AppJWT----",
"token_type": "Bearer"
}
|
---|
|
The AppJWT has an expiration time of 1 hour, not editable.
4 - Getting a consumer JWS [Brand]
The AppJWT is not sufficient to identify a consumer with Conversational Cloud. Using a valid AppJWT, brands can obtain a consumer JWS (JSON Web Signature) to identify the customers in Conversational Cloud.
- The Consumer JWS is the unique identifier of the user (customer) and used by the connector in conjunction with the AppJWT to access Conversational Cloud on behalf of the consumer. Both the ConsumerJWS and the AppJWT will be passed in the headers of both the conversation and send requests to Conversational Cloud in order to authenticate the request.
Here below the HTTPS request to get the ConsumerJWS token:
Method: POST
URL:
https://{{idpDomain}}/api/account/{{accountID}}/consumer?v=1.0
Content-Type: application/json
Authorization: ----AppJWT----
Body:
{
"ext_consumer_id":"---external_consumer_identifier---"
}
|
---|
|
idpDomain
is retrievable from Domain API searching for idp
As response body:
{
"token": " ----ConsumerJWS---- "
}
|
---|
|
The ConsumerJWS structure, if decoded, is:
{
"account_id" : "---LP_CC_Account_id---" ,
"ext_consumer_id" : "---external_consumer_identifier---" ,
"lp_consumer_id" : "---standard_LP_user_id---"
}
|
---|
|
Which contains the userId
value to correctly recognize the customer within the Conversational Cloud. The ConsumerJWS has no expiration time.
5 - Develop and run the connector [Brand]
The previously obtained AppJWT and ConsumerJWS will be passed together in the requests’ headers of every API call to Conversational Cloud, respectively in the HttpHeader.Authorization
and HttpHeader.X-LP-ON-BEHALF
for authorization of the connector and identification of the consumer.
6 - Architectural view of initial configuration [LivePerson]
Here below two schematic overview of the previous explained steps:
Send API
The Send API consists of two types of calls:
- CONVERSATION - Batch Payload. This API call creates/opens a new conversation and sets the consumer profile.
- SEND - One Payload. This API call can be used to send a message and close a conversation or set the consumer profile.
Message format
Every message sent by the brand’s client or by the server should be translated into an appropriate JSON format.
The kind of message is denoted by the kind property in the top level of the JSON object, and can be any of the following:
req
, a message sent from the client/connector. The server will reply with a response message.resp
, a message sent by the server in response to a client/connector request message.notification
, a message sent from the server to the client/connector.
Every message has a type. The structure of the body of the message can be changed for different types. The type of message is denoted by the type property in the top level of the JSON object.
Below is an example of a request message with the type of ms.PublishEvent
:
{
"kind": "req" ,
"id": "1",
"type": "ms.PublishEvent" ,
"body": {
"dialogId": " {{conversationId}} ",
"event": {
"type": "ContentEvent",
"contentType": "text/plain",
"message": "Text message from messaging connector"
}
}
}
|
---|
|
Below is an example of a request message with the type of cm.UpdateConversationField
:
{
"kind": "req" ,
"id": 5,
"type": "cm.UpdateConversationField" ,
"body": {
"conversationId": " {{conversationId}} ",
"conversationField": {
"field": "CSATRate",
"csatRate": 5,
"csatResolutionConfirmation": true,
"status": "FILLED"
}
}
}
|
---|
|
General response format
Responses are sent with some kind of correlation to the request that they are answering. Every request message must state the id
string for the request. The server will reply with the same id
in the response message as the value of the reqId
field in the top level JSON object of the response message.
The sequence
field is an optional counter. For example, tracking the times that the same request has been sent to Conversational Cloud, doubles its value, starting with zero value for the first request, two for the second request, four for the third request, etc.
The response message will also contain a code
field. This field will be populated with the status code of the request, following the HTTP semantics.
Below is an example of a response message to the previous shown ms.PublishEvent
request (reqId
= 1):
{
"code": "OK" ,
"body": {
"sequence": 0
},
"reqId": "1"
}
|
---|
|
HTTP Status codes list:
Code | Description |
---|
200 | Successful response. Returns a message and a ConversationID. |
400 | The input was invalid, please check the JSON body. |
401 | Unauthorized. Check headers orAppJWT expiration time or theConsumerJWS validity. |
429 | Too many requests. API limit reached. |
Errors responses
The Send API returns an error response for every authorization or authentication failure. Any error response contains a JSON payload which details the error title, details about the error and both an HTTP error code and a specific code for the type of error encountered.
Here below a response example if the AppJWT is missing:
{
"kind": "resp",
"code": 401,
"body": {
"title": "AppJWT is missing",
"details": "AUTHORIZATION header is not present",
"errorCode": 40104
},
"type": ".ReqBody$ErrorResp"
}
|
---|
|
The following table shown error response body structure:
Property | Description | Value Type | Notes |
---|
kind | The messaging event kind. | String: “resp” | Always userespfor responses. |
code | The HTTP status code. | Integer: 401 | See the next table for the error codes |
body | JSON body detailing the error. | Object: see below rows |
|
body.title | Title of the error response. | String: “AppJWT is missing” |
|
body.details | Details about the error. | String: “AUTHORIZATION header is not present” |
|
body.errorCode | A unique code identifying each possible error response. | Integer: 40104 | The first three digits represent the HTTP status code and the last two digits are a changing number. See the next table for further details. |
type | The type of the response. | String: .ReqBody$ErrorResp | Always.ReqBody$ErrorRespfor error response. |
Error Code | Title | Details | Comment |
---|
40001 | Missing parameter | Brand Id is missing | This response will also be generated when mandatory claims in the AppJwt are missing. For example, when claim iss is not present or does not have the value sentinel. |
40102 | Invalid AppJWT | AppJWT has expired or is invalid |
|
40103 | Invalid ConsumerJWS | ConsumerJWS is invalid |
|
40104 | ConsumerJWS is missing | X_ON_BEHALF_HEADER is not present |
|
40105 | AppJWT is missing | AUTHORIZATION header is not present |
|
CONVERSATION
The CONVERSATION method is a batch-endpoint (this means that the body can contain several payloads). It takes a set of at least two JSON payloads.
The order of the array is important, since Conversational Cloud expects to receive these payloads in that order. It returns an array of corresponding JSON payloads in the response.
The most important value obtained by this endpoint is the conversationId
which will be used for the subsequent SEND calls to Conversational Cloud.
Request details
Method: POST
URL:
https://{{domain}}/api/account/{{accountID}}/messaging/consumer/conversation?v=3
Header:
Content-Type: application/json
Authorization: {{AppJWT}}
X-LP-ON-BEHALF: {{ConsumerJWS}}
Body:
See the next paragraphs
|
---|
|
domain
is retrievable from Domain API searching for asyncMessagingEnt
.
This method expects a set of JSON payloads, each representing a different type of request to the Conversational Cloud messaging service. The order of the payloads is important in order to create a new conversation.
- First, the payload with the type
userprofile.SetUserProfile
appears; - Then, the payload with the type
cm.ConsumerRequestConversation
appears.
The payload with the type userprofile.SetUserProfile
is mandatory. Its body can essentially be passed empty or with some engagement attributes in order for the Agent to see the Consumer Info in the Conversational Cloud Agent Workspace.
For the sake of simplicity, the next request body example illustrates the minimal JSON payload which is mandatory for conversation creation in Conversational Cloud:
[
{
"kind": "req",
"id": "1,",
"type": " userprofile.SetUserProfile ",
"body": {}
},
{
"kind": "req",
"id": "2,",
"type": " cm.ConsumerRequestConversation ",
"body": {
"brandId": " {{accountID}} "
}
}
]
|
---|
|
The above payloads are only shown for example purposes. We strongly recommend not to create conversations in that way, without user information passed in the body of the both payloads.
As best practice, we recommend always adding users information through the conversation creation, in order to enable the routing / targeting of the right skill or engagement in Conversational Cloud.
Passing user information is done through the payload with the type userprofile.SetUserProfile
:
- If the
authenticatedData
object in the body
is not passed (left blank or deleted altogether), there will be no consumer information for the Agent in Conversational Cloud's Agent Workspace. - Under the
authenticatedData
object, you can pass an lp_sdes
array. This array is used to send engagement attributes (SDEs) to Conversational Cloud. - The SDEs are used to populate the consumer information widget for the Agent, in Conversational Cloud's Agent Workspace.
Again, as a best practice we strongly recommend to pass SDEs when creating a new conversation.
The SDEs supported for sending are the Customer Info.
Here a request body example illustrating how to create a conversation and send SDEs in one request:
[{
"kind": "req",
"id": "1,",
"type": " userprofile.SetUserProfile ",
"body": {
"authenticatedData": {
"lp_sdes": [
{
"type": "ctmrinfo",
"info": {
"socialId": "1234567890",
"ctype": "vip"
}
},
{
"type": "personal",
"personal": {
"firstname": "John",
"lastname": "Doe",
"gender": "MALE"
}
}
]
}
}
},
{
"kind": "req",
"id": "2,",
"type": " cm.ConsumerRequestConversation ",
"body": {
"brandId": " {{accountID}} "
}
}]
|
---|
|
In the following table, are listed every properties you can add to the cm.ConsumerRequestConversation.body
payload:
Property | Description | Value Type | Mandatory |
---|
ttrDefName | Defines the urgency of the conversation | String: "NORMAL" / "URGENT" / "PRIORITIZED" /null | x |
campaignInfo | Contains the campaignId and engagementId fields | Strings: { "campaignId": "99999", "engagementId": "888888" } |
x |
channelType | Which channel type is used | String: Always use "MESSAGING” | ✓ |
brandId | LivePerson site ID - Account ID | String | ✓ |
skillId | Skill ID you would like to route the conversation to | String: use “-1” as default to target all skills available | x |
conversationContext | Describes the conversation environment | SharkContextobjectmade of strings. In the next section will be shown in details | x |
The cm.ConsumerRequestConversation.body
payload can contain the conversationContext
field: its elements are related to the consumer session, with all details needed for monitoring and reporting purposes. Here below the list:
Property | Description | Value Type | Mandatory |
---|
visitorId | The LivePerson identifier to the current consumer device | String: "A3ZTY3Zjk1MDExZTczYTU4" | x |
sessionId | The LivePerson identifier to the current monitor session of this consumer device | String: "ys2wSqaSRSOJGki7VhEDKQ" |
x |
interactionContextId | contextIdretrieved by the Engagement Monitoring API endpoint | String: “2” | x |
type | Type of conversationContext | String: Always use "SharkContext" when using Monitoring API properties | x |
lang | The conversation language, according to the IETF (ISO-639-1 and ISO-3166) | String: "en-US" Check first if the language used is configured for the engagement | x |
Response details
An example of successful response (Code status 200). The response array will contains single payloads for every request payloads sent (reqIDs):
[
{
"code": "OK",
"body": {
"msg": "OK User Profile set successfully"
},
"reqId": "1,"
},
{
"code": "OK",
"body": {
"conversationId": "8602832d-dce1-446b-8445-0d51f5926a42"
},
"reqId": "2,"
}
]
|
---|
|
Authentication
Connector API doesn’t support authentication, like we usually do with oAuth2.0 Code or Implicit flow. The CONVERSATION call is not able to federate any brand’s authentication.
The presence of the authenticatedData
field in the userprofile.SetUserProfile
payload only indicates the type of SDEs passed: this object can contain Customer Info and Personal Info fields, which LivePerson usually links to any authenticated data. In this case the entire object only adds customers information, needed by the brand for their Agents.
This means the Conversational Cloud will show any of these data as “authenticated”, with the blue tick, but actually they won't be, as no oAuth2.0 flow is used.
Routing settings
In the conversation creation phase, i.e. through the first CONVERSATION call, it is possible to enforce routing in three ways:
- Using the
SkillID
field in the cm.ConsumerRequestConversation.body
. With this brands can directly route conversations to the target skills. - Using the SDEs rules on Houston. In this way is possible to create routing rules basing on:
CustomerInfo.CustomerType
CustomerInfo.CompanyBranch
PersonalInfo.Gender
PersonalInfo.Language
This configuration has to be done by LivePerson on the brand’s account backend.
- Setting up campaigns and engagements as usual and use the Campaign ID and the Engagement ID to the Conversational Cloud through the
campaignInfo
field in the cm.ConsumerRequestConversation.body
. In this way it is possible to route the consumer conversation to the desired skill as designed by the Campaign Builder. This will also allow the Agent to see the name of the brand connector as the source of the conversation in the Consumer info widget
The best practice recommended by LivePerson is to use the third way. For that, in order to retrieve the campaign properties, you must use the Monitoring API.
The Engagement method of the Monitoring API allows brands to obtain an engagement for a consumer only if both the following apply:
- There is no active conversation for this consumer;
- The consumer is eligible for an engagement.
By sending the user required information, will be returned the engagement properties: campaignId
, engagementId
, visitorId
, sessionId
and more, to fill the campaignInfo
field and the conversationContext
object in the cm.ConsumerRequestConversation.body
payload of the CONVERSATION call.
The following request body example shows how to use these data for routing:
[{
"kind": "req",
"id": "1,",
"type": " userprofile.SetUserProfile ",
"body": {
"authenticatedData": {
"lp_sdes": [
{
"type": "ctmrinfo",
"info": {
"socialId": "1234567890",
"ctype": "vip"
}
},
{
"type": "personal",
"personal": {
"firstname": "John",
"lastname": "Doe",
"gender": "MALE"
}
}
]
}
}
},
{
"kind": "req",
"id": "2,",
"type": " cm.ConsumerRequestConversation ",
"body": {
"ttrDefName": "NORMAL",
"campaignInfo": {
"campaignId": "99999",
"engagementId": "888888"
} ,
"conversationContext": {
"visitorId": "A3ZTY3Zjk1MDExZTczYTU4",
"sessionId": "ys2wSqaSRSOJGki7VhEDKQ",
"interactionContextId": "2",
"type": "SharkContext",
"lang": "en-US"
},
"channelType": "MESSAGING",
"brandId": " {{accountID}} ",
"skillId": "-1"
}
}
]
|
---|
|
SEND
The SEND method allows sending a JSON payload to the Conversational Cloud. This method, differently from the CONVERSATION endpoint, is used mainly to send a message from the consumer to the agent or to close a conversation.
The connector application can use this method for one action at a time:
- Send a text message
- Close a conversation
- Send metadata
- Set user profile (send SDEs)
- Send chat-state events (e.g. consumer is typing)
Request details
Method: POST
URL:
https://{{domain}}/api/account/{{accountID}}/messaging/consumer/conversation/send?v=3
Header:
Content-Type: application/json
Authorization: {{AppJWT}}
X-LP-ON-BEHALF: {{ConsumerJWS}}
Body:
Messaging Window API JSON payload .
This payload would normally have one of these types:
ms.PublishEvent cm.UpdateConversationField
See the next paragraphs for request examples
|
---|
|
domain
is retrievable from Domain API searching for asyncMessagingEnt
.- For the JSON Body payload, see the next Messaging Window API section with the examples. For a more complete list use the Request Builder to get an example of the accepted payloads.
Payload structures
In the following table, are listed main properties you can add to the ms.PublishEvent
type body payload:
Property | Description | Value Type | Mandatory |
---|
dialogId | The conversationId created by CONVERSATION request | String: "8602832d-dce1-446b-8445-0d51f5926a42" | ✓ |
event | The messaging event object | It contains different types of events, with related fields. Below there is a detailed list of the data to be passed. | ✓ |
Based on the event.type
, it will be sent different payload structures depending on the use case chosen. Here a comprehensive list:
1 - Send a text message (consumer to agent)
Property | Description | Value Type | Mandatory |
---|
type
| The messaging event type | ContentEvent | ✓ |
contentType | Which content is sent | String: "text/plain" for text message | ✓ |
message | Text/content message | String | ✓ |
JSON example
{
"kind":"req",
"id":"1",
"type":"ms.PublishEvent",
"body":{
"dialogId":" {{conversationId}} ",
"event":{
" type ":" ContentEvent ",
" contentType ":"text/plain",
" message ":"Hi from Send Message only - Send a line"
}
}
}
|
---|
|
2 - Send a file (consumer to agent)
To successfully enable a brand’s consumer to send a file (images) during a conversation, the brand’s connector application needs to follow these steps:
- Request an upload URL for the consumer file using the payload type
ms.GenerateURLForUploadFile
, to subsequently send the consumer file in the LivePerson Swift storage service.
Here below the payload body details:
Property | Description | Value Type | Mandatory |
---|
fileSize
| File size given in Bytes. Limited to 3MB. Oversized requests will be rejected | String | ✓ |
fileType | Which content is sent | String: “JPG” / “JPEG” / “PNG” / “GIF” | ✓ |
{
"kind":"req"
"id":"3",
"type":" ms.GenerateURLForUploadFile ",
"body":{
" fileSize ":"1024",
" fileType ":"JPG"
},
}
|
---|
|
Extract relativePath
, temp_url_sig
, temp_url_expires
from the response, to use them in the next request. Here below a response example:
{
"code": "OK",
"body": {
" relativePath ": "/v1/AUTH_async-images/64467156/6be59ddb8f54d88845a4fd4987cf5717878eacd2f893b7a7331717f113d2589f_uuid_326931e5-062f-46cb-b981-a383040d2cb8_04-06-2018_04-10-59-845.PNG",
"queryParams": {
" temp_url_sig ": "dd9e3bdb2bebbc254653f0d090922b40489ca6e",
" temp_url_expires ": "1528099919"
}
},
"reqId": "3"
}
|
---|
|
- Upload the file to the storage (as binary using the swift storage)
Method: PUT
URL:
https://{{swiftDomain}}/{{relativePath}}?temp_url_sig={{temp_url_sig}}&temp_url_expires={{temp_url_expires}}
|
---|
|
swiftDomain
is retrievable from Domain API searching for swift
.relativePath
, temp_url_sig
, temp_url_expires
from the previous response (file expiration is set to 1 minute by default).- Successful response will give HTTP code status 201, else 401 for failure.
- Publish the file as a message inside the conversation
Once the consumer file is saved in storage, the connector app will publish the file URL along with an optional caption and thumbnail as a message for the agent.
To send the optional thumbnail, the connector app needs to convert the image file to base64. The output will populate the parameter imageData
.
Here below the payload body details:
Property | Description | Value Type | Mandatory |
---|
dialogId
| The conversationId created by CONVERSATION request | String: "8602832d-dce1-446b-8445-0d51f5926a42" | ✓ |
type | The messaging event type | String: “ContentEvent” | ✓ |
contentType | Which content is sent | String: "hosted/file" | ✓ |
message | Array of properties describing the file | Object: see below rows | ✓ |
message.caption | Description | String: "File logo" | x |
message.relativePath | Path extracted on step 2 | String | ✓ |
message.fileType | Same type of the step 1 | String: “JPG” / “JPEG” / “PNG” / “GIF” | ✓ |
message.preview | The base64 data conversion of the file | String: "data:image/png;base64,{{imageData}}" | x |
Here below an example of the request for publishing the image file link:
{
"kind": "req",
"id": "3",
"type": "ms.PublishEvent",
"body": {
"dialogId": "{conversationId}",
"event": {
"type": "ContentEvent",
"message": {
" caption ": "File logo",
" relativePath ": " {{relativePath}} ",
" fileType ": "JPEG",
" preview ": "data:image/png;base64, {{imageData}} "
},
"contentType": " hosted/file "
}
}
}
|
---|
|
- Request a download URL for the consumer file using the payload type
ms.GenerateURLForDownloadFile
. Here the payload body details:
Property | Description | Value Type | Mandatory |
---|
relativePath
| Path extracted on step 2 | String | ✓ |
Example request:
{
"kind": "req",
"id": "3",
"type": " ms.GenerateURLForDownloadFile ",
"body": {
" relativePath ": " {{relativePath}} "
}
}
|
---|
|
The response details will contain relativePath
, temp_url_sig
, temp_url_expires
(like the upload step), to be used for the next step. Here an example:
{
"code": "OK",
"body": {
" relativePath ": "/v1/AUTH_async-images/64467156/5f3aab9eb95ff60f159cab500e3a83f1aba98a99749c07143fbda2dece70e601_uuid_5c68d4e8-3bde-40ac-86c2-1e5f43089cd4_07-06-2018_09-47-15-947.JPEG",
"queryParams": {
" temp_url_sig ": "384bcb0b188920909d4a068473824e964ecbffcd",
" temp_url_expires ": "1528379356"
}
},
"reqId": "3"
}
|
---|
|
- Download the file from the storage (use this call like for the upload step)
Method: GET
URL:
https://{{swiftDomain}}/{{relativePath}}?temp_url_sig={{temp_url_sig}}&temp_url_expires={{temp_url_expires}}
|
---|
|
swiftDomain
is retrievable from Domain API searching for swift
.relativePath
, temp_url_sig
, temp_url_expires
from the previous response (file expiration is set to 1 minute by default).- Successful response will give HTTP code status 200, else 401 for failure.
3 - Send messaging State Events
Property | Description | Value Type | Mandatory |
---|
type
| The messaging event type | String: “ContentEvent” | ✓ |
contentType | Which content is sent | String: "text/plain" for text message | ✓ |
message | Text/content message | String | ✓ |
JSON example
{
"kind":"req",
"id":"1",
"type":" ms.PublishEvent ",
"body":{
"dialogId":" {{conversationId}} ",
"event":{
" type ":"ContentEvent",
" contentType ":"text/plain",
" message ":"Hi from Send Message only - Send a line"
}
}
}
|
---|
|
4 - Consumer accepted a message
Property | Description | Value Type | Mandatory |
---|
type
| The messaging event type | String: “AcceptStatusEvent” | ✓ |
status | Acceptance status of the message sent by the Agent to the Consumer | String: "ACCEPT" (message was accepted by the consumer) "READ" (message was read by the consumer) "ACCESS" (Consumer has accessed the file) "NACK" (message not received) "ACTION" (used in conjunction with metadata to reply on structured content sent by the Agent) | ✓ |
sequenceList | List of sequence values | Array of integers: [1,2] | ✓ |
JSON example
{
"kind":"req",
"id": "0",
"type": "ms.PublishEvent ",
"body": {
"dialogId": " {{conversationId}} ",
"event": {
" type ": "AcceptStatusEvent",
" status ": "ACCEPT",
" sequenceList ": [1,2]
}
}
}
|
---|
|
5 - Close a conversation
Here below the two ways to close a conversation:
{
"kind":"req",
"id":1,
"type":"cm.UpdateConversationField",
"body": {
"conversationId":" {{conversationId}} ",
"conversationField":{
" field ":"ConversationStateField",
" conversationState ":"CLOSE"
}
}
}
|
---|
|
- Close the dialog - for triggering PCS bots
{
"kind": "req",
"id": 1,
"type": "cm.UpdateConversationField"
"body": {
"conversationId": " {{conversationId}} ",
"conversationField": {
" field ": "DialogChange",
" field ": "UPDATE",
" dialog ": {
"dialogId": " {{conversationId}} ",
"state": "CLOSE",
"closedCause": "Closed by consumer"
}
}
}
}
|
---|
|
6 - General JSON examples
Consumer is typing
{
"kind":"req",
"id":"1",
"type":" ms.PublishEvent ",
"body":{
"dialogId":" {{conversationId}} ",
"event":{
"type":"ChatStateEvent",
"chatState":"COMPOSING"
}
}
}
|
---|
|
Consumer has accepted the message
{
"kind":"req",
"id": "0",
"type": " ms.PublishEvent ",
"body": {
"dialogId": " {{conversationId}} ",
"event": {
"type": "AcceptStatusEvent",
"status": "ACCEPT",
"sequenceList": [1,2]
}
}
}
|
---|
|
Webhooks Notification Service
Webhooks limitations
Brands should consider that:
- Webhooks events order is on best effort basis and it is not guaranteed;
- For example, if a notification of a certain event failed the first time and was only delivered successfully after one or more retries, then it is possible that a subsequent event will be delivered before.
- As long as the retry policy is not exhausted, then event duplications are possible.
- Data event loss is possible;
- For example, when a failed notification request is retried, once the retry policy is exhausted - e.g. all the retry attempts fail, the event will be dropped.
Webhooks best practises
On the brand’s servers it is important that the Webhook endpoint is highly available and resilient. In order to reduce the probability of losing events, brands should decouple receiving notifications from business logic, e.g. by placing incoming notifications in a queue and returning HTTP 200 OK
immediately.