Answers Integration - Lumapps

As Moveworks builds and integration with Lumapps, This document highlights the capabilities that can be built in this integration and the end user experience while fetching knowledge articles.

Moveworks utilizes Lumapps APIs to discover Lumapps’ response structure and how to integrate those responses into the Moveworks knowledge ingestion engine.

Lumapps Knowledge Structure

How to authenticate with Lumapps?

To authenticate with Lumapps we use the service account created within the customer’s instance:

Create and authorize credentials

In APIs & Services > Credentials click create credentials > Service account and follow the steps. During the last step, generate a key and get the client ID inside it.

Lastly, send an email to [email protected], specify:

  • you want to use LumApps delegation.
  • the clientID (xxxxxxxxxxxxxxxxxxxxx) to be granted access.
  • the customer ID on which to grant access.
  • the environment.

This will allow the service account to generate token for the your Lumapps instance and fetch knowledge contents.

To generate a bearer token with this account we need to run a python script which takes inputs from the service_account.json file.

The fields which are empty need input in the service_account.json file.

Service account details

  "type": "service_account",
  "project_id": "",
  "private_key_id": "",
  "private_key": "",
  "client_email": "",
  "client_id": "",
  "auth_uri": "",
  "token_uri": "",
  "auth_provider_x509_cert_url": "",
  "client_x509_cert_url": "{client_email value}"

Token generation script

import requests
import datetime
import json
import jwt

LUMAPPS_API_BASE_URL = f"{MY_LUMAPPS_ENV}/_ah/api/lumsites/v1"

def call_lumapps_apis_with_service_account_raw():
    #  1 - Construct a jwt with your service account
    with open("service _account.json", "r") as f:
        service_account = json.load(f)

    sa_email = service_account["client_email"]
    sa_private_key = service_account["private_key"]
    current_timestamp =
    exp_time = current_timestamp + 30 
    data = {
        'aud': '',
        'iss': sa_email,
        'iat': current_timestamp,
        'exp': exp_time,           # expiry time is 30 seconds from time of creation
        'scope': ''
    constructed_jwt = jwt.encode(data, sa_private_key, algorithm='RS256')

    # 2 - Get a google token from your jwt
    google_token_url = ""
    body = {
        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "assertion": constructed_jwt
    response =, data=body)
    response_json = response.json()
    google_token = response_json["access_token"]

    #  3 - Call LumApps api "user/getToken" endpoint with your google token
    # to get a LumApps jwt token authenticated as a user.
    url = f"{LUMAPPS_API_BASE_URL}/user/getToken"
    headers = {"Authorization": f"Bearer {google_token}"}
    customer_id = ""              # Your customer id
    user_to_authenticate_as = ""  # The email of the user you want to authenticate as
    params = {
        "customerId": customer_id,
        "email": user_to_authenticate_as

    response = requests.get(url, params=params, headers=headers)
    response_json = response.json()
    lumapps_token = response_json["accessToken"]

    # 4 - Call a lumapps endpoints using the access token you just retrieved

    # Here we call user/get to get the user associated to the token
    # See for more informations about other endpoints

    url = f"{LUMAPPS_API_BASE_URL}/user/get" # user/get endpoint
    headers = {"Authorization": f"Bearer {lumapps_token}"}
    response = requests.get(url, headers=headers)
    user = response.json()
    print(f"User: {user}")

How Moveworks ingests knowledge articles?

Moveworks' knowledge engine makes relevant snippets from the knowledge articles in your knowledge base, using Moveworks' NLU and similarity scoring.

The snippetized articles are then stored in the enterprise cache, and can be served to users in-chat based on the user queries.

Ingestion scope

Lumapps hosts knowledge under different pages and sub-pages, these act as containers that hold different widgets. Moveworks only ingests the Intro widget and the HTML widget.



Whenever a user requests for an inquiry there are potentially two cases which can be served

Case 1: Bot finds a relevant knowledge article

Case 2: Bot doesn't find any relevant knowledge articles