Using the API

Introduction

This documentation is for the newly created API for the CU Wireless product LiveSurvey. The first phase of the API rollout is focused on providing subscribers with the ability to programmatically access LiveSurvey data leveraging the reporting capability.

Endpoint types

All endpoints are POST endpoints.

Available endpoints

Identity Login

Purpose:

With the Identity Login endpoint, LiveSurvey login credentials are passed in and the SSO token is returned. This is the first step in the authentication process. The sign in email and password used here are those for an Admin-role Remote Access User. LiveSurvey recommends setting up a dedicated email (for instance, livesurveyapi@creditunion.com) for use with the API and storing the credentials securely. Any user with an Admin role can access all survey data.

URL:

https://login.livecusurvey.com

Route:

POST api/login

Post:

{
    "Email": "EMAIL",
    "Password": "PASSWORD"
}

Example:

{
    "Email": "john.doe@bigcreditunion.com",
    "Password": "abc123!321CBA"
}

Return:

Success = 200 (OK) - The response from LiveSurvey will return a LiveSurvey SSO token.

{
    "ssoToken": "SSO_TOKEN"
}

Error = 401 - Login credentials are not valid.

Portal Login

Purpose:

The Portal Login endpoint is used to pass the SSO token returned from the Identity Login endpoint. This endpoint will return a JWT token.

Note: The JWT token expiration time is 20 minutes.

Access:

This endpoint is only available to Admin level (or higher) LiveSurvey users.

URL:

https://SUBDOMAIN.livecusurvey.com

Route:

POST api/v2/jwt/login

Post:

{
    "ssoToken": "SSO_TOKEN"
}

Return:

Success = 200 (OK) - The response from LiveSurvey will return a JWT token.

{
    "token": "JWT_TOKEN"
}

Error = 401 - SSO token is not supplied or not valid.

Error = 404 - URI subdomain is incorrect. No client is not found at the provided subdomain.

Generate Report

Purpose:

The Generate Report endpoint submits a request to LiveSurvey to run (generate) the specified report.

Note about date ranges: The report results will be inclusive of data from the specified end date.

Route:

POST api/v2/jwt/report

Post:

{
    "token": "JWT_TOKEN",
    "type": "REPORT_TYPE", // (Export, Summary, Departments, Employees, Comments, Transaction, NetPromoter)
    "surveyId": SURVEY_ID,
    "start": "yyyy-MM-dd", // Report Start Date
    "end": "yyyy-MM-dd" // Report End Date
}

Example:

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiI5NiIsIlVzZXJuYW1lIjoic3VwZXIyIiwiTmFtZSI6IiIsIkVtYWlsIjoiIiwiVGl0bGUiOiIiLCJEZXBhcnRtZW50S2V5IjoiIiwiRW1wbG95ZWVLZXkiOiJzdXBlcjIiLCJDbGllbnRHcm91cElkIjoiIiwiQ2xpZW50R3JvdXBOYW1lIjoiIiwiQ2xpZW50SWQiOiIzIiwiQ2xpZW50TmFtZSI6IiIsIkNsaWVudFRhZ3NFbmFibGVkIjoiVHJ1ZSIsIlJvbGUiOiJTdXBlciIsIlN1YmRvbWFpbiI6InN0YWdpbmciLCJUaW1lWm9uZUlkIjoiUGFjaWZpYyBTdGFuZGFyZCBUaW1lIiwibmJmIjoxNjMwNDQyMzM2LCJleHAiOjE2MzA0NDM1MzYsImlhdCI6MTYzMDQ0MjMzNn0.BH4jRU9h1-yKlZsyqMnsKcnZFWY1sO-duzByocfxqB8",
    "type": "Transaction",
    "surveyId": 3,
    "start": "2021-07-01",
    "end": "2021-07-31"
}

Return:

Success = 201 - A 201 response from LiveSurvey confirms that the requested report was submitted successfully to the Report Job queue to be created.

Error = 400 - Report Type, Survey ID, Start Date or End Date is not valid.

Error = 401 - The token is not valid.

Report List

Purpose:

The Report List endpoint will return an array of the previously generated reports associated with the user’s ClientID. The reports will be sorted by date, starting with the most recently generated.

Route:

POST api/v2/jwt/report/list

Post:

{
    "token": "JWT_TOKEN",
    "max": NUMBER_OF_REPORTS // default is 1
}

Example:

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiI5NiIsIlVzZXJuYW1lIjoic3VwZXIyIiwiTmFtZSI6IiIsIkVtYWlsIjoiIiwiVGl0bGUiOiIiLCJEZXBhcnRtZW50S2V5IjoiIiwiRW1wbG95ZWVLZXkiOiJzdXBlcjIiLCJDbGllbnRHcm91cElkIjoiIiwiQ2xpZW50R3JvdXBOYW1lIjoiIiwiQ2xpZW50SWQiOiIzIiwiQ2xpZW50TmFtZSI6IiIsIkNsaWVudFRhZ3NFbmFibGVkIjoiVHJ1ZSIsIlJvbGUiOiJTdXBlciIsIlN1YmRvbWFpbiI6InN0YWdpbmciLCJUaW1lWm9uZUlkIjoiUGFjaWZpYyBTdGFuZGFyZCBUaW1lIiwibmJmIjoxNjMwNDQyMzM2LCJleHAiOjE2MzA0NDM1MzYsImlhdCI6MTYzMDQ0MjMzNn0.BH4jRU9h1-yKlZsyqMnsKcnZFWY1sO-duzByocfxqB8",
    "max": 1
}

Return:

Success = 200 (OK) - The response from LiveSurvey will be an array of available reports.

{
    "reports": [
        {
            "ReportId": REPORT_ID,
            "Type": "REPORT_TYPE", // (Export, Summary, Departments, Employees, Comments, Transaction, NetPromoter)
            "SurveyId": SURVEY_ID,
            "Start": "yyyy-MM-dd", // Report Start Date
            "End": "yyyy-MM-dd", // Report End Date
            "Timestamp": "CREATED_ON_DATE_TIME"
        }
    ]
}

Error = 400 - There is an issue with the report service.

Error = 401 - The token is not valid.

Report Download

Purpose:

The Report Download endpoint will return the requested report file as an XLSX file.

Route:

POST api/v2/jwt/report/download

Post:

{
    "token": "JWT_TOKEN",
    "ReportId": REPORT_ID
}

Example:

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiI5NiIsIlVzZXJuYW1lIjoic3VwZXIyIiwiTmFtZSI6IiIsIkVtYWlsIjoiIiwiVGl0bGUiOiIiLCJEZXBhcnRtZW50S2V5IjoiIiwiRW1wbG95ZWVLZXkiOiJzdXBlcjIiLCJDbGllbnRHcm91cElkIjoiIiwiQ2xpZW50R3JvdXBOYW1lIjoiIiwiQ2xpZW50SWQiOiIzIiwiQ2xpZW50TmFtZSI6IiIsIkNsaWVudFRhZ3NFbmFibGVkIjoiVHJ1ZSIsIlJvbGUiOiJTdXBlciIsIlN1YmRvbWFpbiI6InN0YWdpbmciLCJUaW1lWm9uZUlkIjoiUGFjaWZpYyBTdGFuZGFyZCBUaW1lIiwibmJmIjoxNjMwNDQyMzM2LCJleHAiOjE2MzA0NDM1MzYsImlhdCI6MTYzMDQ0MjMzNn0.BH4jRU9h1-yKlZsyqMnsKcnZFWY1sO-duzByocfxqB8",
    "ReportId": 11
}

Return:

Success = 200 (OK) - The response from LiveSurvey will return the specified report (XLSX) file.

Error = 400 - The Report ID is empty.

Error = 401 - The token is not valid.

Error = 404 - The report service cannot find the specified report.

Code Example

The following code example is written in Python and was tested using Python 3.9.2.

This Python script demonstrates the entire flow:

  1. Logs in using your Identity credentials to retrieve an SSO token
  2. Uses the SSO token to retrieve a JWT login
  3. Submits a report to be generated
  4. Waits 30s for the report to be generated
  5. Gets a list of the last 3 reports created
  6. Downloads the most recent report

Copy and paste the code into a new Python file. Update the creds and settings at the top to match your account and report info. Once everything is updated correctly, running the Python script should download the report file into the same folder as the script file. The report file will be named using the report info.

'''LiveSurvey Report API example'''

import requests
import time

# creds, settings
API_HOST = 'https://SUBDOMAIN.livecusurvey.com' # update with your subdomain
EMAIL = 'LOGIN_EMAIL' # update with your admin login email
PASSWORD = 'LOGIN_PASSWORD' # update with your admin login password

REPORT_TYPE = 'Export' # update with your report type
REPORT_SURVEY_ID = 1 # update with your report survey id
REPORT_START = '2021-08-01' # update with your report start date
REPORT_END = '2021-08-31' # update with your report end date

WAIT_TIME = 30 # wait time in seconds for report to generate
REPORT_LIST_MAX  = 3 # maximum reports returned


#########################################
# Identity login
#########################################

def get_sso_token(email, password):
    '''Returns an SSO token after authenticating login credentials.'''

    url = 'https://login.livecusurvey.com/api/login'
    payload = {
        'Email': email,
        'Password': password
    }

    response = requests.post(url=url, json=payload)

    sso_token = response.json().get('ssoToken')

    print('- ...received SSO token: %s' % sso_token)

    return sso_token


#########################################
# Portal login
#########################################

def get_jwt_token(ssoToken):
    '''Returns a JWT token after authenticating SSO token credentials.'''

    url = '%s/api/v2/jwt/login' % API_HOST
    payload = {
        "ssoToken": ssoToken
    }

    response = requests.post(url=url, json=payload)

    jwt_token = response.json().get('token')

    print('- ...received JWT token %s' % jwt_token)

    return jwt_token


#########################################
# Generate report
#########################################

def api_generate_report(token, type_, survey_id, start, end):
    '''Submits a report to be generated.'''

    url = '%s/api/v2/jwt/report' % API_HOST
    payload = {
        'token':     token,
        'type':      type_,
        'surveyId':  survey_id,
        'start':     start,
        'end':       end,
    }

    response = requests.post(url=url, json=payload, stream=True)

    return response


#########################################
# Report list
#########################################

def api_report_list(token, max):
    '''Returns a list of the latest available reports.'''

    url = "%s/api/v2/jwt/report/list" % API_HOST
    payload = {
        "token": token,
        "max":   max # defaults to 1 if absent
    }

    response = requests.post(url=url, json=payload)

    return response.json().get('reports')


#########################################
# Report download
#########################################

def api_report_file(token, report_id):
    '''Downloads the specified report.'''

    url = "%s/api/v2/jwt/report/download" % API_HOST
    payload = {
        "token":    token,
        "ReportId": report_id
    }

    response = requests.post(url=url, json=payload, stream=True)

    return response


#########################################
# Get the login tokens
#########################################

print('- Getting SSO token...')
sso_token = get_sso_token(EMAIL, PASSWORD)

print('- Getting JWT token...')
jwt_token = get_jwt_token(sso_token)


#########################################
# Submit a report
#########################################

print('- Requesting report generation...')
report_response = api_generate_report(jwt_token, REPORT_TYPE, REPORT_SURVEY_ID, REPORT_START, REPORT_END)

if (report_response.status_code == 201):
    print("- ...success.")
    print('- Report submitted.')
else:
    print("! Failed: (%d) %s" % (report_response.status_code, report_response.text))


#########################################
# Wait for submitted report to generate
# This wait time may need to be adjusted depending on the size of the reports
#########################################

print("- ...waiting %d seconds for report to be generated." % WAIT_TIME)
time.sleep(WAIT_TIME)

#########################################
# Retrieve the report list
#########################################

print("- Getting report list:")
reports = api_report_list(jwt_token, REPORT_LIST_MAX)

for r in reports:
    print("- ------")
    print("  id:\t\t%s\n  survey_id:\t%s\n  type:\t\t%s" % (r['ReportId'], r['SurveyId'], r['Type']))
    print("  start:\t%s\n  end:\t\t%s" % (r['Start'], r['End']))
    print("  timestamp:\t%s" % (r['Timestamp']))

print("\n- Returned %d reports; done." % len(reports))

print("\n- Latest Report ID is %d" % reports[0]['ReportId'])


#########################################
# Download the latest report
# This report should be the one submitted above
#########################################

print("- Getting report file...")
report = api_report_file(jwt_token, reports[0]['ReportId'])

filename = "report%s_survey%s_%s_%s_%s.xlsx" % (reports[0]['ReportId'], reports[0]['SurveyId'], reports[0]['Type'], reports[0]['Start'], reports[0]['End'])
print("- Writing `%s`..." % filename)

c = 0
with open(filename, "wb") as fd:
    for chunk in report.iter_content():
        fd.write(chunk)
        c += 1

print("- Wrote %d bytes; done." % c)