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.MTLSClient() Returns a MTLS Client, that needs to be configured with cert & key. Please be aware that both certificate and key need to be in the PEM-Format. The Toolbelt.MTLSClient() can yield an error if the certificate is malformed, so please make sure to catch it. Further the MTLS Client 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 @ https://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.

  // Importing the FaaS Toolbelt
  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
  httpClient("https://github.com/", {
    method: "GET", // HTTP VERB
    headers: {}, // Your Headers
    simple: false, // IF true => Status Code != 2xx & 3xx will throw
    resolveWithFullResponse: true //IF true => Includes Status Code, Headers etc.
  })
.then(response => {
	...
})
.catch(err => {
  ...
})
  • Please beware of the following restrictions:
  • If the domain is not whitelisted the proxy will close the connection yielding a `Socket is closed`-Error.
  • Max. 20 requests/sec (all beyond that are rejected with 429 - Too Many Requests.)

MTLS Client

  // Importing the FaaS Toolbelt
  const { Toolbelt } = require("lp-faas-toolbelt");
  // Configure MTLSClient with cert & key bundle in PEM format. 
  // Optional you can provide CA-Cert (PEM-Format) in case upstream cert is self-signed 
  // Also a soft format check is performed, which will throw an error if failing. Make sure to catch it.
  const mtlsClient = Toolbelt.MTLSClient({cert: 'cert-string', key: 'key-string'});
  mtlsClient.post('https://your-mtls-endpoint.com', { header: 'test'}, null, {
    json: true, // If true will attempt to parse response body to JSON
    timeout: 10000, // Deadline for request to finish by in MS
    allowSelfSigned: false, // Allow the upstream cert to be self-signed
    })
  .then(response => {
    ...
  })
  .catch(err => {
    ...
  })
  • Please beware of the following restrictions:
  • If the domain is not whitelisted the proxy will close the connection yielding a `Socket is closed`-Error.
  • Max. 20 req/sec (all beyond that are rejected with 429 - Too Many Requests).
  • The expiration date of cert is not tracked, that is something you are responsible for.
  • Both key and cert need to be in PEM-Format.
  • The provided cert and key is checked for its format and will raise an error if malformed.

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:

  1. 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
    }
    
  2. 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 will replace all files in a conversation permanently! Contact your Account Manager to get access.

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