As mentioned in the Getting Started document, we offer you access to our lp-faas-toolbelt
Node.js module, which is a language-specific utility library for lambdas.
Currently, the Toolbelt offers the following methods:
Method | Description |
---|---|
Toolbelt.SFClient() | Returns a Salesforce Client, that is configured to work with the FaaS Proxy. |
Toolbelt.HTTPClient() | Returns a HTTP Client, that is configured to work with the FaaS Proxy. |
Toolbelt.LpClient() | Returns the LivePerson (LP) Client. This is a wrapper for the HTTP Client. It simplifies the usage of LivePerson APIs by providing automatic service discovery as well as taking care of the authorization. |
Toolbelt.SecretClient() | Returns an Secret Storage Client, that is configured to work with the FaaS Secret Storage. |
Toolbelt.ConversationUtil() | Returns a Conversation Util instance. |
Toolbelt.GDPRUtil() | Returns a GDPR Util instance. Provides GDPR related functionality, such as replacing files of a conversation. |
Toolbelt.SDEUtil() | Returns a SDE Util instance. Provides SDE related functionality, such as setting/ updating SDEs for an Engagement. |
Toolbelt.ContextServiceClient() | Returns a Context Service Client instance. Provides functionality to interact with the Context Session Store. |
Here are usage example, which are taken out of the official templates:
Salesforce Client
Salesforce Client that is based on jsforce for connecting LivePerson Functions to any Salesforce system.
const { Toolbelt } = require("lp-faas-toolbelt");
const sfClient = Toolbelt.SFClient(); // for API docs look @ hhtps://jsforce.github.io/
//This will establish a connection with SF. And leverage Access Token / Refresh Token to login
const con = sfClient.connectToSalesforce({
loginUrl: "https://test.salesforce.com",
accessToken: "PROVIDE_YOUR_ACCESS_TOKEN", //Obtain it from Secret Store
refreshToken: "PROVIDE_YOUR_REFRESH_TOKEN" // Obtain it from Secret Store
});
con.query(query, function(err, queryResult) {});
HTTP Client
HTTP Client that is based on request-promise for opening external HTTP connections.
const { Toolbelt } = require("lp-faas-toolbelt");
//Obtain an HTTPClient instance from the Toolbelt
const httpClient = Toolbelt.HTTPClient(); // For API Docs look @ https:/www.npmjs.com/package/request-promise
const URL = "https://www.liveperson.com/";
httpClient(URL, {
method: "GET", //HTTP VERB
headers: {}, //Your headers
simple: false, //IF true => Status Code != 2xx & 3xx will throw
json: true, // Automatically parses the JSON string in the response
resolveWithFullResponse: false //IF true => Includes Status Code, Headers etc.
})
.then(response ==> {
...
})
- Please beware of the following restrictions:
- Error code
403 - You do not have access to the page or resource you are trying to reach
means that the url is not whitelisted! - mTLS is not support!
- Max. 20 requests/sec (all beyond that are rejected with
429 - Too Many Requests
)
LivePerson Client
The LivePerson (LP) Client is a wrapper for the HTTP Client. It simplifies the usage of LivePerson APIs by providing automatic service discovery as well as taking care of the authorization.
Every LivePerson API has a service name. This is documented in the respective page on developers.liveperson.com. The Messaging Interactions API for instance has the service name msgHist
. The LP Client expects the LpService name as the first argument. This can be done by using our LpServices
enum or by manually providing the service name as a string. Each of the API-domains related to the LpServices
enum is whitelisted in LivePerson Functions by default. (s. Whitelisted Domains for more information)
Additionally, most of the LivePerson API calls need authorization. The LP Client takes care of that by automatically creating the respective HTTP headers. In order to perform this authorization, the LP Client uses credentials from an API-key. Each account using Liveperson Functions has an API-key called lp-faas-default
by default, which is visible in Live Engage. This API-key is able to authenticate to the following APIs:
API | Read/ Write access? |
---|---|
Data Access API | Yes |
Messaging Interactions API | Yes |
Operational Realtime API | Yes |
Personal Data Deletion API | Read only |
Users API | Read only |
Skills API | Read only |
Agent Groups API | Read only |
Profiles API | Read only |
LOBs API | Read only |
Workdays API | Read only |
Visit Information API | Yes |
Engagement Attributes API | Yes |
Validate Engagement API | Yes |
IVR Engagement API | Yes |
Predefined Content API | Read only |
Automatic Messages API | Read only |
Predefined Categories API | Read only |
Unified Automatic Messages API | Read only |
Agent Status Reason API | Read only |
Currently, only APIs that use API Key authorization are supported.
Using APIs not covered in default API-key/Whitelisting
If you need to access an API which is not covered by the default API-key/Whitelisting, you need to perform the following steps:
- Create and maintain the API Key credentials
- Create an API Key as described here. (the Messaging Interactions API for instance needs the permission
Data -> Engagement History / Messaging Interactions
) - Create a new secret of the type JSON to save the API Key credentials. The JSON has to have the structure as displayed below. Provide the name of the created secret when using the LP Client (see Sample Usage below for an example).
{ "consumerKey": "...", // App Key "consumerSecret": "...", // Secret "token": "...", // Access token "tokenSecret": "...", // Access token secret }
- Create an API Key as described here. (the Messaging Interactions API for instance needs the permission
- Whitelist the API you want to use
- Retrieve the domain for the service you want to use as described here.
- Go to
Settings -> Domain Whitelist
- Add the domain
Sample Usage
const { Toolbelt, LpServices } = require("lp-faas-toolbelt");
// Obtain an LpClient instance from the Toolbelt
const lpClient = Toolbelt.LpClient();
/**
* Same options as the HTTPClient
* For possible options look @ https://github.com/request/request#requestoptions-callback
*/
const options = {
method: "POST",
body: {
conversationId
},
json: true,
/** insert the name of your custom authentication secret here - Use only
* if you want to bypass the default API-key and understand the ramifications.
*/
appKeySecretName: 'my-custom-secret-name'
}
lpClient(
LpServices.MSG_HIST, // LP service name
`/messaging_history/api/account/${process.env.BRAND_ID}/conversations/conversation/search`, // endpoint of the service
options // options
)
.then(response => {
...
})
Secret Storage Client
Storage Client that is able to read & update secret values. The following methods exist:
SecretClient.readSecret
Searches the secret that belongs to the provided key. Will raise an error if there is no secret for the provided key.
Parameter | Description |
---|---|
key | Name of the secret |
Returns | Description |
---|---|
secretEntry | Object with properties key & value
|
SecretClient.updateSecret
Updates the secret with the provided update entry.
Parameter | Description |
---|---|
secretEntry | Object with properties key & value
|
Returns | Description |
---|---|
secretEntry | Created entry |
Sample Usage
// import FaaS Toolbelt
const { Toolbelt } = require("lp-faas-toolbelt");
// obtain SecretClient from Toolbelt
const secretClient = Toolbelt.SecretClient();
// this is how you can access your stored secret
secretClient
.readSecret("my_Secret-Key")
.then(mySecret => {
// Fetching the secret value
const value = mySecret.value;
// you can also update your secret e.g. if you received a new OAuth2 token
mySecret.value = "nEw.oaUtH2-tOKeN!!11!";
return secretClient.updateSecret(mySecret);
})
.then(_ => {
callback(null, { message: "Successfully updated secret" });
})
.catch(err => {
console.error(`Failed during secret operation with ${err.message}`);
callback(err, null);
});
Conversation Util
The Conversation Util allows conversation related methods to be performed, which are listed below.
Get Conversation By ID
This method retrieves a conversation from the Messaging Interactions API. It requires a conversation ID and accepts an optional Array to define which contents should be retrieved. It returns a Promise
that resolves to a conversation object.
Parameter | Required? | Description | Type/Value |
---|---|---|---|
conversationId | yes | The ID of the conversation that should be retrieved | string |
contentToRetrieve | no | An array which can be used to define the content that should be retrieved. Use the ConversationContentTypes for an overview of which content types can be retrieved (s. Sample Usage below) | array |
Sample Usage
// import FaaS Toolbelt
const { Toolbelt, ConversationContentTypes } = require("lp-faas-toolbelt");
// Create instance
const conversationUtil = Toolbelt.ConversationUtil();
// Define Parameters
const conversationId = "c911f008-4761-4f43-95445-6948017eace5"
const contentToRetrieve = [
ConversationContentTypes.SDES,
ConversationContentTypes.UNAUTH_SDES
]
// Get conversation
conversationUtil.getConversationById(conversationId, contentToRetrieve)
.then(conversation => {}) //TODO: react to the response
.catch(err => {}); //TODO: React to error
Scan Conversation For Keywords
This method scans a conversation that has been retrieved with getConversationById()
(see method above) for messages containing certain keywords. Those keywords can be freely determined and are case insensitive.
Sample Usage
// import FaaS Toolbelt
const { Toolbelt } = require("lp-faas-toolbelt");
// Create instance
const conversationUtil = Toolbelt.ConversationUtil();
// Get conversation
const conversation = await conversationUtil.getConversationById(conversationId);
// Determine Keywords
const keywords = ["Keyword", "awesome"];
// Scan Conversation for Keywords
const scannerResult = conversationUtil.scanConversationForKeywords(
conversation,
keywords
);
Sample Result
The method collects every message which contains a keyword in an array. It retrieves a timestamp, information on who sent the message and adds a tag detailing the keyword for which the message has been selected. If one message contains more than one keyword it will appear as often in the array. (see example underneath)
Attribute | Description | Type/Value |
---|---|---|
message | The whole message which is containing at least one keyword | string |
sentTimestamp | Timestamp (Current Unix epoch time in milliseconds) when the message was sent | number |
sentBy | Who the conversation was sent by | string |
[
{
message: "Will we use Keywords in this conversation?",
sentTimestamp: 1560764690328,
sentBy: "Consumer",
tag: "keywordRef:Keyword"
},
{
message: "We definitely will, because keywords are awesome!",
sentTimestamp: 1560764734592,
sentBy: "Agent",
tag: "keywordRef:Keyword"
},
{
message: "We definitely will, because keywords are awesome!",
sentTimestamp: 1560764734592,
sentBy: "Agent",
tag: "keywordRef:awesome"
}
];
GDPR Util
This method provides GDPR related functionality, such as replacing files in a conversation. This Util works for Messaging-Use Cases only!
Replace files of a conversation
This method replaces all files of a conversation from LivePerson's file storage. It expects a conversation, the credentials for the file storage, a callback for filtering files and replacement image.
Sample Usage
// import FaaS Toolbelt
const { Toolbelt } = require("lp-faas-toolbelt");
// set file storage credentials (get from Account Manager)
const fileStorageCredentials = {
username: '...',
password: '...'
}
// Create instance
const conversationUtil = Toolbelt.ConversationUtil();
// Create GDPR Util instance
const gdprUtil = Toolbelt.GDPRUtil();
const shouldReplace = (filePath) => ... // filter here by returning boolean
const replacementFile = {
body: Buffer.from('...', 'base64'), // create file from base64
contentType: 'image/png',
};
// Get conversation and replace files
conversationUtil.getConversationById(conversationId)
.then(conversation => gdprUtil.replaceConversationFiles(
conversation,
fileStorageCredentials,
shouldReplace, //(optional) defaults to (path) => true
replacementFile, //(optional) defaults to a black 1px*1px png
))
.then(replacedFiles => //TODO: react on the response)
.catch(err => //TODO: React to error);
SDE Util
The SDE Util allows SDE related methods to be performed, which are listed below.
Add SDEs
This method adds/ updates SDEs to an Engagement via the Engagement Attributes API. It requires the session ID and the visitor ID where the SDEs should be added and the SDEs themselves. It returns a Promise
that resolves when the SDEs have been successfuly set/ updated.
Parameters
Parameter | Required? | Description | Type/Value |
---|---|---|---|
sdes | yes | Array of SDEs which should be added to an engagement. For more information about the available Engagement Attributes, refer to the Engagement Attributes Overview. Also use the SDETypes for suggestions for which types of engagement attributes can be added. (s. sample usage below) | array |
visitorId | yes | The ID of the Visitor you want to add the SDEs to. (Sometimes is included in the faas-event payload, if not use the conversation ID with the Conversation Util to retrieve) | string |
sessionId | yes | The ID of the Session you want to add the SDEs to. (Sometimes is included in the faas-event payload, if not use e.g. the conversation ID with the Conversation Util to retrieve) | string |
Sample Usage
// import FaaS Toolbelt
const { Toolbelt, SDETypes } = require("lp-faas-toolbelt");
// Create instance
const sdeUtil = Toolbelt.SDEUtil();
// Define parameters
const visitorId = "YyY2RlZGY3NzZjYoJhZGQx";
const sessionId = "bjfYkPt-SYCqqZWDHNwSKQ";
const sdes = [
{
type: SDETypes.PERSONAL_INFO,
personal: {
contacts: [
{
email: "john.doe@example.com"
}
]
}
}
];
// Add SDEs
sdeUtil.addSDEs(sdes, visitorId, sessionId)
.then(response => {}) //TODO: react to the response
.catch(err => {}); //TODO: React to error
Get SDEs from Conversation
The method extracts the SDEs from a conversation that has been retrieved fromt the Messaging Interactions API. (e.g via the ConversationUtil) Before returning them, it sorts the contained SDE-Events in ascending order.
Sample Usage
// import FaaS Toolbelt
const { Toolbelt, ConversationContentTypes } = require("lp-faas-toolbelt");
// Create SDE/Conversation-Util instance
const conversationUtil = Toolbelt.ConversationUtil()
const sdeUtil = Toolbelt.SDEUtil();
// Define parameters
const conversationId = "c944f008-4761-4f43-9536-6948017eace5";
const contentToRetrieve = [
ConversationContentTypes.SDES,
ConversationContentTypes.UNAUTH_SDES
]
// Get Conversation and extract SDEs
conversationUtil.getConversationById(conversationId, contentToRetrieve)
.then(conversation => {
// TODO: define how to procede with the SDEs
const sdes = sdeUtil.getSDEsFromConv(conversation);
})
.catch(err => {}); //TODO: React to error
Sample Result
If there were no errors, the result is an object which allways contains an array of SDE-Events for authenticated SDEs (sdes
) and an array for unauthanticated SDEs. (unAuthSdes
) Those arrays are sorted in ascending order, meaning the last event is the most current one.
{
sdes: {
events: [
{
customerInfo: {
...
},
serverTimeStamp: 1569572377158,
sdeType: 'CUSTOMER_INFO',
},
{
personalInfo: {
...
},
serverTimeStamp: 1569572377270,
sdeType: 'PERSONAL_INFO',
},
],
},
unAuthSdes: {
events: [
{
customerInfo: {
...
},
serverTimeStamp: 1569574433640,
sdeType: 'CUSTOMER_INFO',
},
{
customerInfo: {
...
},
serverTimeStamp: 1569574433640,
sdeType: 'CUSTOMER_INFO',
},
{
personalInfo: {
...
},
serverTimeStamp: 1569574433865,
sdeType: 'PERSONAL_INFO',
},
],
},
}
Context Service Client
The Context Service Client can be used to easily interact with the Context Session Store. This is especially useful for storing data between function calls.
After all prerequisites for using the context session store have been set up successfully, the client can be instantiated as follows.
const { Toolbelt } = require('lp-faas-toolbelt');
// creating a secretClient instance
const secretClient = Toolbelt.SecretClient();
try {
// retrieving your developer key from the secret storage
const { value: apiKey } = await secretClient.readSecret('YOUR_DEVELOPER_KEY_SECRET_NAME');
// retrieving your account ID via e.g. env variable
const accountId = process.env.BRAND_ID
const config = {accountId, apiKey}
// using the config to instantiate the contextServiceClient
const contextClient = Toolbelt.ContextServiceClient(config);
} catch(error) {
// Handle error based on your integration by providing a legit fallback operation.
console.error(`received following error message: ${error.message}`);
}
Methods
ContextServiceClient.createNamespace
Creates a custom namespace with the specified name for the provided account. Given the namespace exists it will not recreate it or throw an error.
Parameter | Required? | Description | Example |
---|---|---|---|
namespace | Yes | Name of the namespace | - |
options | No | options that should be applied to the namespace. For example Time to Live in seconds. If not provided/defined TTL will be permanent. | { ttl: 120 } |
ContextServiceClient.deleteNamespace
Deletes a custom namespace with the specified name. Given the namespace was already deleted it will not throw an error.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |
ContextServiceClient.getListOfNamespaces
Returns a list containing all custom namespaces for the account the client was initialised for. Please be aware that built-in namespaces won't show up with exception to the default namespace.
Parameter | Required? | Description |
---|---|---|
- | - | function has no parameters |
ContextServiceClient.setPropertiesInNamespace (Code Snippet)
Will set properties on the specified session in the defined namespace. Given no session was provided it will fallback to the default session of the namespace. All values will be stored in their JSON serialized version. Given a property/properties does exist they will be updated.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |
properties | Yes | object containing the properties that should be set |
sessionId | No | if not provided will use default session |
ContextServiceClient.updatePropertiesInNamespace (Code Snippet)
Will update properties on the specified session in the defined namespace. Given no session was provided it will fallback to the default session of the namespace. All values will be stored in their JSON serialized version. Given a property/properties does not exist they will be created.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |
properties | Yes | object containing the properties that should be updated |
sessionId | No | if not provided will use default session |
ContextServiceClient.getAllPropertiesInSession
Returns the specified session containing all of it's properties. Given no session was provided it will fallback to the default session of the namespace.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |
sessionId | No | if not provided will use default session |
ContextServiceClient.getSelectedPropertiesInSession
Returns the specified session containing all of the defined properties. Given a property does not exist it will be ignored. Given no session was provided it will fallback to default session of the namespace.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |
propertyNames | Yes | names of the desired properties in a string array |
sessionId | No | if not provided will use default session |
ContextServiceClient.getPropertyInSession (Code Snippet)
Get the value of the specified property on the defined session. Given no session was provided it will fallback to default session of the namespace.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |
propertyName | Yes | name of the desired property |
sessionId | No | if not provided will use default session |
ContextServiceClient.deletePropertyInSession (Code Snippet)
Deletes the specified property on the defined session. Given no session was provided it will fallback to default session of the namespace. Given the property was already deleted it will not throw an error.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |
propertyName | Yes | name of the property that should be deleted |
sessionId | No | if not provided will use default session |
ContextServiceClient.deleteSession
Deletes the specified session in the defined namespace. Given no session was provided it will fallback to default session of the namespace. Given the session was already deleted it will not throw an error.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |
sessionId | Yes | ID of the session that should be deleted |
ContextServiceClient.getListOfSessions
Returns a list containing all session in the specified namespaces.
Parameter | Required? | Description |
---|---|---|
namespace | Yes | Name of the namespace |