{"id":21959720,"url":"https://github.com/rusticisoftware/scormcloud-api-v2-client-javascript","last_synced_at":"2025-04-23T18:04:09.955Z","repository":{"id":46188083,"uuid":"177436268","full_name":"RusticiSoftware/scormcloud-api-v2-client-javascript","owner":"RusticiSoftware","description":"Swagger Generated Java Script Client for SCORM Cloud API v2","archived":false,"fork":false,"pushed_at":"2024-02-09T22:22:57.000Z","size":410,"stargazers_count":11,"open_issues_count":1,"forks_count":4,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-11-19T12:15:43.986Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RusticiSoftware.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2019-03-24T15:55:21.000Z","updated_at":"2024-11-05T11:36:06.000Z","dependencies_parsed_at":"2023-12-08T21:36:08.401Z","dependency_job_id":null,"html_url":"https://github.com/RusticiSoftware/scormcloud-api-v2-client-javascript","commit_stats":{"total_commits":12,"total_committers":3,"mean_commits":4.0,"dds":0.5833333333333333,"last_synced_commit":"30d474a8aa3ab8c41a5b023b1373a3a7357bae8c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RusticiSoftware%2Fscormcloud-api-v2-client-javascript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RusticiSoftware%2Fscormcloud-api-v2-client-javascript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RusticiSoftware%2Fscormcloud-api-v2-client-javascript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RusticiSoftware%2Fscormcloud-api-v2-client-javascript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RusticiSoftware","download_url":"https://codeload.github.com/RusticiSoftware/scormcloud-api-v2-client-javascript/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227089763,"owners_count":17729546,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T09:32:06.417Z","updated_at":"2024-11-29T09:32:07.023Z","avatar_url":"https://github.com/RusticiSoftware.png","language":"JavaScript","readme":"# @rusticisoftware/scormcloud-api-v2-client-javascript\n\nJavaScript client for @rusticisoftware/scormcloud-api-v2-client-javascript\n    REST API used for SCORM Cloud integrations.\nThis SDK is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project:\n\n- API version: 2.0\n- Package version: 4.0.0\n- Build package: io.swagger.codegen.languages.JavascriptClientCodegen\n\n## Installation\n### npm\n[@rusticisoftware/scormcloud-api-v2-client-javascript](https://www.npmjs.com/package/@rusticisoftware/scormcloud-api-v2-client-javascript)\n\n```shell\nnpm install @rusticisoftware/scormcloud-api-v2-client-javascript --save\n```\n\n### GitHub\n[RusticiSoftware/scormcloud-api-v2-client-javascript](https://github.com/RusticiSoftware/scormcloud-api-v2-client-javascript)\n\n```shell\nnpm install RusticiSoftware/scormcloud-api-v2-client-javascript --save\n```\n\n### Local\nTo use the library locally without pulling from the npm registry, first install the dependencies by changing\ninto the directory containing `package.json` (and this README). Let's call this `JAVASCRIPT_CLIENT_DIR`. Then run:\n\n```shell\nnpm install\n```\n\nNext, [link](https://docs.npmjs.com/cli/link) it globally in npm with the following, also from `JAVASCRIPT_CLIENT_DIR`:\n\n```shell\nnpm link\n```\n\nFinally, switch to the directory you want to use your @rusticisoftware/scormcloud-api-v2-client-javascript from, and run:\n\n```shell\nnpm link /path/to/\u003cJAVASCRIPT_CLIENT_DIR\u003e\n```\n\nYou should now be able to `require('@rusticisoftware/scormcloud-api-v2-client-javascript')` in javascript files from the directory you ran the last\ncommand above from.\n\n### For browser\n\nThe library also works in the browser environment via npm and [browserify](http://browserify.org/). After following\nthe above steps and installing browserify with `npm install -g browserify`,\nperform the following (assuming *main.js* is your entry file, that's to say your javascript file where you actually\nuse this library):\n\n```shell\nbrowserify main.js \u003e bundle.js\n```\n\nThen include *bundle.js* in the HTML pages.\n\n### Webpack Configuration\n\nUsing Webpack you may encounter the following error: \"Module not found: Error:\nCannot resolve module\", most certainly you should disable AMD loader. Add/merge\nthe following section to your webpack config:\n\n```javascript\nmodule: {\n    rules: [\n        {\n            parser: {\n                amd: false\n            }\n        }\n    ]\n}\n```\n\n## Tips and Tricks\nWorking with headers will require passing a response parameter of the callback function. This allows for grabbing the header directly from the response object:\n```javascript\n// Note: This code is specifically designed to not modify any existing data\nconst dispatchApi = new ScormCloud.DispatchApi();\ndispatchApi.updateDispatches(new ScormCloud.UpdateDispatchSchema(), { \"since\": new Date().toISOString() }, function(err, data, response) {\n    console.log(response.headers[\"x-total-count\"]);\n});\n```\n\n## Changelog:\n### Release 2.0.X:\n- The return type for endpoints which used to return a File have changed to instead return a Blob object. This change\nallows both Node and the browser to download the files appropriately.\n\nCheck the [changelog](https://cloud.scorm.com/docs/v2/reference/changelog/) for further details of what has changed.\n\n## Sample Code\nThere are additional dependencies required to get the sample code running.\n```\nnpm install browser-or-node prompt-sync\n```\n\n```javascript\nconst ScormCloud = require('@rusticisoftware/scormcloud-api-v2-client-javascript');\nconst fs = require('fs');\n\nlet prompt;\nvar jsEnv = require(\"browser-or-node\");\nif (jsEnv.isBrowser) {\n    prompt = window.prompt;\n}\nif (jsEnv.isNode) {\n    prompt = require('prompt-sync')({sigint: true});\n}\n\n\n// ScormCloud API credentials\n// Note: These are not the same credentials used to log in to ScormCloud\nconst APP_ID = \"APP_ID\";\nconst SECRET_KEY = \"SECRET_KEY\";\n\n// Sample values for data\nconst COURSE_PATH = \"/PATH/TO/COURSE/RunTimeAdvancedCalls_SCORM20043rdEdition.zip\";\nlet COURSE_FILE;\n\nconst COURSE_ID = \"JS_SAMPLE_COURSE\";\nconst LEARNER_ID = \"JS_SAMPLE_COURSE_LEARNER\";\nconst REGISTRATION_ID = \"JS_SAMPLE_COURSE_REGISTRATION\";\n\n// String used for output formatting\nconst OUTPUT_BORDER = \"---------------------------------------------------------\\n\";\n\n\n/**\n * This sample will consist of:\n * 1. Creating a course.\n * 2. Registering a learner for the course.\n * 3. Building a link for the learner to take the course.\n * 4. Getting the learner's progress after having taken the course.\n * 5. Viewing all courses and registrations.\n * 6. Deleting all of the data created via this sample.\n *\n * All input variables used in this sample are defined up above.\n */\nfunction main() {\n    // Configure HTTP basic authorization: APP_NORMAL\n    const APP_NORMAL = ScormCloud.ApiClient.instance.authentications['APP_NORMAL'];\n    APP_NORMAL.username = APP_ID;\n    APP_NORMAL.password = SECRET_KEY;\n\n    // Create a course\n    createCourse(COURSE_ID, COURSE_FILE, function(courseDetails) {\n        // Show details of the newly imported course\n        console.log(\"Newly Imported Course Details: \");\n        console.log(courseDetails);\n\n        // Create a registration for the course\n        createRegistration(COURSE_ID, LEARNER_ID, REGISTRATION_ID, function() {\n            // Create the registration launch link\n            buildLaunchLink(REGISTRATION_ID, function(launchLink) {\n                // Show the launch link\n                console.log(OUTPUT_BORDER);\n                console.log(`Launck Link: ${launchLink}`);\n                console.log(\"Navigate to the url above to take the course. \" +\n                    (jsEnv.isNode ? \"Hit enter once complete.\" : \"Click OK on the in-browser prompt once complete.\"));\n                prompt();\n\n                // Get the results for the registration\n                getResultForRegistration(REGISTRATION_ID, function(registrationProgress) {\n                    // Show details of the registration progress\n                    console.log(OUTPUT_BORDER);\n                    console.log(\"Registration Progress: \");\n                    console.log(registrationProgress);\n\n                    // Get information about all the courses in ScormCloud\n                    getAllCourses(function(courseList) {\n                        // Show details of the courses\n                        console.log(OUTPUT_BORDER);\n                        console.log(\"Course List: \");\n                        courseList.forEach((course) =\u003e {\n                            console.log(course);\n                        });\n\n                        // Get information about all the registrations in ScormCloud\n                        getAllRegistrations(function(registrationList) {\n                            // Show details of the registrations\n                            console.log(OUTPUT_BORDER);\n                            console.log(\"Registration List: \");\n                            registrationList.forEach((registration) =\u003e {\n                                console.log(registration);\n                            });\n\n                            // Delete all the data created by this sample\n                            cleanUp(COURSE_ID, REGISTRATION_ID);\n                        });\n                    });\n                });\n            });\n        });\n    });\n}\n\nfunction logErrorAndCleanUp(error) {\n    console.error(error)\n\n    // Delete all the data created by this sample\n    cleanUp(COURSE_ID, REGISTRATION_ID);\n}\n\n/**\n * Sets the default OAuth token passed with all calls to the API.\n *\n * If a token is created with limited scope (i.e. read:registration),\n * calls that require a different permission set will error. Either a\n * new token needs to be generated with the correct scope, or the\n * default access token can be reset to None. This would cause the\n * request to be made with basic auth credentials (appId/ secret key)\n * instead.\n *\n * Additionally, you could create a new configuration object and set\n * the token on that object instead of the default access token. This\n * configuration would then be passed into the Api object:\n *\n * apiClient = new ScormCloud.ApiClient();\n * tokenRequest = {\n *     permissions: { scopes: [ \"write:course\", \"read:course\" ] },\n *     expiry: new Date((new Date()).getTime() + 2 * 60 * 1000).toISOString()\n * };\n * appManagementApi.createToken(tokenRequest, function (error, data) {\n *     if (error) {\n *         return logErrorAndCleanUp(error.response.text);\n *     }\n *     apiClient.authentications['OAUTH'].accessToken = data.result;\n *     courseApi = new ScormCloud.CourseApi(apiClient);\n *\n *     // Logic would go here\n * });\n *\n * Any calls that would use this CourseApi instance would then have the\n * write:course and read:course permissions passed automatically, but\n * other instances would be unaffected and continue to use other means\n * of authorization.\n *\n * @param {Array\u003cString\u003e} scopes List of permissions for calls made with the token.\n */\nfunction configureOAuth(scopes, callback) {\n    const appManagementApi = new ScormCloud.ApplicationManagementApi();\n\n    // Set permissions and expiry time of the token\n    // The expiry expected for token request must be in ISO-8601 format\n    const expiry = new Date((new Date()).getTime() + 2 * 60 * 1000).toISOString();\n    const permissions = { scopes: scopes };\n\n    // Make the request to get the OAuth token\n    tokenRequest = { permissions: permissions, expiry: expiry };\n    appManagementApi.createToken(tokenRequest, function (error, data) {\n        if (error) {\n            return logErrorAndCleanUp(error.response.text);\n        }\n\n        // Set the default access token used with further API requests.\n        // To remove the token, reset\n        // ScormCloud.ApiClient.instance.authentications['OAUTH'].accessToken\n        // back to null before the next call.\n        const OAUTH = ScormCloud.ApiClient.instance.authentications['OAUTH'];\n        OAUTH.accessToken = data.result;\n\n        callback();\n    });\n}\n\n/**\n * Creates a course by uploading the course from your local machine.\n * Courses are a package of content for a learner to consume.\n *\n * Other methods for importing a course exist. Check the documentation\n * for additional ways of importing a course.\n *\n * @param {String} courseId Id that will be used to identify the course.\n * @param {File} courseFile The File object containing the course contents.\n * @returns {CourseSchema} Detailed information about the newly uploaded course.\n */\nfunction createCourse(courseId, courseFile, callback) {\n    function createCourseLogic() {\n        const courseApi = new ScormCloud.CourseApi();\n        let jobId;\n\n        // This call will use OAuth with the \"write:course\" scope\n        // if configured.  Otherwise the basic auth credentials will be used\n        courseApi.createUploadAndImportCourseJob(courseId, { file: courseFile }, function(error, data) {\n            if (error) {\n                return logErrorAndCleanUp(error.response.text);\n            }\n\n            jobId = data.result;\n\n            function getUploadStatus(jobId) {\n                // This call will use OAuth with the \"read:course\" scope\n                // if configured.  Otherwise the basic auth credentials will be used\n                let interval = setInterval(function () {\n                    courseApi.getImportJobStatus(jobId, function(error, data) {\n                        if (error) {\n                            clearInterval(interval);\n                            return logErrorAndCleanUp(error.response.text);\n                        }\n\n                        if (data.status == ScormCloud.ImportJobResultSchema.StatusEnum.RUNNING) {\n                            return;\n                        }\n\n                        // If importing has finished (failure or success)\n                        clearInterval(interval);\n\n                        if (data.status == ScormCloud.ImportJobResultSchema.StatusEnum.ERROR) {\n                            return logErrorAndCleanUp(\"Course is not properly formatted: \" + data.message);\n                        }\n\n                        callback(data.importResult.course);\n                    });\n                }, 1000);\n            }\n            getUploadStatus(jobId);\n        });\n    }\n\n    // (Optional) Further authenticate via OAuth token access\n    // First line is with OAuth, second is without\n    // configureOAuth([ \"write:course\", \"read:course\" ], createCourseLogic);\n    createCourseLogic();\n}\n\n/**\n * Creates a registration allowing the learner to consume the course\n * content. A registration is the link between a learner and a single\n * course.\n *\n * @param {String} courseId Id of the course to register the learner for.\n * @param {String} learnerId Id that will be used to identify the learner.\n * @param {string} registrationId Id that will be used to identify the registration.\n */\nfunction createRegistration(courseId, learnerId, registrationId, callback) {\n    function createRegistrationLogic() {\n        const registrationApi = new ScormCloud.RegistrationApi();\n        const learner = { id: learnerId };\n        const registration = { courseId: courseId, learner: learner, registrationId: registrationId };\n        registrationApi.createRegistration(registration, {}, function(error) {\n            if (error) {\n                return logErrorAndCleanUp(error.response.text);\n            }\n\n            callback();\n        });\n    }\n\n    // (Optional) Further authenticate via OAuth token access\n    // First line is with OAuth, second is without\n    // configureOAuth([ \"write:registration\" ], createRegistrationLogic);\n    createRegistrationLogic();\n}\n\n/**\n * Builds a url allowing the learner to access the course.\n *\n * This sample will build the launch link and print it out. It will then\n * pause and wait for user input, allowing you to navigate to the course\n * to generate sample learner progress. Once this step has been reached,\n * hitting the enter key will continue program execution.\n *\n * @param {String} registrationId Id of the registration the link is being built for.\n * @returns {String} Link for the learner to launch the course.\n */\nfunction buildLaunchLink(registrationId, callback) {\n    function buildLaunchLinkLogic() {\n        const registrationApi = new ScormCloud.RegistrationApi();\n        const settings = { redirectOnExitUrl: \"Message\" };\n        registrationApi.buildRegistrationLaunchLink(registrationId, settings, function(error, data) {\n            if (error) {\n                return logErrorAndCleanUp(error.response.text);\n            }\n\n            callback(data.launchLink);\n        });\n    }\n\n    // (Optional) Further authenticate via OAuth token access\n    // First line is with OAuth, second is without\n    // configureOAuth([ \"read:registration\" ], buildLaunchLinkLogic);\n    buildLaunchLinkLogic();\n}\n\n/**\n * Gets information about the progress of the registration.\n *\n * For the most up-to-date results, you should implement our postback\n * mechanism. The basic premise is that any update to the registration\n * would cause us to send the updated results to your system.\n *\n * More details can be found in the documentation:\n * https://cloud.scorm.com/docs/v2/guides/postback/\n *\n * @param {String} registrationId Id of the registration to get results for.\n * @returns {RegistrationSchema} Detailed information about the registration's progress.\n */\nfunction getResultForRegistration(registrationId, callback) {\n    function getResultForRegistrationLogic() {\n        const registrationApi = new ScormCloud.RegistrationApi();\n        registrationApi.getRegistrationProgress(registrationId, {}, function(error, data) {\n            if (error) {\n                return logErrorAndCleanUp(error.response.text);\n            }\n\n            callback(data);\n        });\n    }\n\n    // (Optional) Further authenticate via OAuth token access\n    // First line is with OAuth, second is without\n    // configureOAuth([ \"read:registration\" ], getResultForRegistrationLogic);\n    getResultForRegistrationLogic();\n}\n\n/**\n * Gets information about all courses. The result received from the API\n * call is a paginated list, meaning that additional calls are required\n * to retrieve all the information from the API. This has already been\n * accounted for in the sample.\n *\n * @returns {Array\u003cCourseSchema\u003e} List of detailed information about all of the courses.\n */\nfunction getAllCourses(callback) {\n    function getAllCoursesLogic() {\n        const courseApi = new ScormCloud.CourseApi();\n        const courseList = [];\n\n        function getPaginatedCourses(more) {\n            // This call is paginated, with a token provided if more results exist.\n            // Additional filters can be provided to this call to get a subset\n            // of all courses.\n            courseApi.getCourses({ more: more },  function(error, data) {\n                if (error) {\n                    return logErrorAndCleanUp(error.response.text);\n                }\n\n                courseList.push(...data.courses);\n\n                if (data.more) {\n                    return getPaginatedCourses(data.more);\n                }\n\n                callback(courseList);\n            });\n        }\n        getPaginatedCourses(null);\n    }\n\n    // (Optional) Further authenticate via OAuth token access\n    // First line is with OAuth, second is without\n    // configureOAuth([ \"read:course\" ], getAllCoursesLogic);\n    getAllCoursesLogic();\n}\n\n/**\n * Gets information about the registration progress for all\n * registrations. The result received from the API call is a paginated\n * list, meaning that additional calls are required to retrieve all the\n * information from the API. This has already been accounted for in the\n * sample.\n *\n * This call can be quite time-consuming and tedious with lots of\n * registrations. If you find yourself making lots of calls to this\n * endpoint, it might be worthwhile to look into registration postbacks.\n *\n * More details can be found in the documentation:\n * https://cloud.scorm.com/docs/v2/guides/postback/\n *\n * @returns {Array\u003cRegistrationSchema\u003e} List of detailed information about all of the registrations.\n */\nfunction getAllRegistrations(callback) {\n    function getAllRegistrationsLogic() {\n        const registrationApi = new ScormCloud.RegistrationApi();\n        const registrationList = [];\n\n        function getPaginatedRegistrations(more) {\n            // This call is paginated, with a token provided if more results exist.\n            // Additional filters can be provided to this call to get a subset\n            // of all registrations.\n            registrationApi.getRegistrations({ more: more },  function(error, data) {\n                if (error) {\n                    return logErrorAndCleanUp(error.response.text);\n                }\n\n                registrationList.push(...data.registrations);\n\n                if (data.more) {\n                    return getPaginatedRegistrations(data.more);\n                }\n\n                callback(registrationList);\n            });\n        }\n        getPaginatedRegistrations(null);\n    }\n\n    // (Optional) Further authenticate via OAuth token access\n    // First line is with OAuth, second is without\n    // configureOAuth([ \"read:registration\" ], getAllRegistrationsLogic);\n    getAllRegistrationsLogic();\n}\n\n/**\n * Deletes all of the data generated by this sample.\n * This code is run even if the program has errored out, providing a\n * \"clean slate\" for every run of this sample.\n *\n * It is not necessary to delete registrations if the course\n * they belong to has been deleted. Deleting the course will\n * automatically queue deletion of all registrations associated with\n * the course. There will be a delay between when the course is deleted\n * and when the registrations for the course have been removed. The\n * registration deletion has been handled here to prevent scenarios\n * where the registration hasn't been deleted yet by the time the\n * sample has been rerun.\n *\n * @param {String} courseId Id of the course to delete.\n * @param {String} registrationId Id of the registration to delete.\n */\nfunction cleanUp(courseId, registrationId) {\n    function cleanUpLogic() {\n        // This call will use OAuth with the \"delete:course\" scope\n        // if configured.  Otherwise the basic auth credentials will be used\n        const courseApi = new ScormCloud.CourseApi();\n        courseApi.deleteCourse(courseId, function(error) {\n            if (error) {\n                throw error;\n            }\n        });\n\n        // The code below is to prevent race conditions if the\n        // sample is run in quick successions.\n\n        // This call will use OAuth with the \"delete:registration\" scope\n        // if configured.  Otherwise the basic auth credentials will be used\n        const registrationApi = new ScormCloud.RegistrationApi();\n        registrationApi.deleteRegistration(registrationId, function(error) {\n            if (error) {\n                throw error;\n            }\n        });\n    }\n\n    // (Optional) Further authenticate via OAuth token access\n    // First line is with OAuth, second is without\n    // configureOAuth([ \"delete:course\", \"delete:registration\" ], cleanUpLogic);\n    cleanUpLogic();\n}\n\n// If running through the browser, call browserFileUpload instead:\n\n// \u003c!DOCTYPE html\u003e\n// \u003chtml\u003e\n//     \u003cbody\u003e\n//         \u003cp\u003e\n//             When running the sample in the browser, a File object is required to be passed to the sample code.\n//             Input a file using the input below and then run the sample code.\n//         \u003c/p\u003e\n//         \u003cinput id=\"fileButton\" type=file /\u003e\n//     \u003c/br\u003e\n//         \u003cbutton onclick=\"runSample()\"\u003eClick here to run sample code in the console.\u003c/button\u003e\n//         \u003cp id=\"runLog\"\u003e\u003c/p\u003e\n//     \u003c/body\u003e\n// \u003c/html\u003e\n// \u003cscript src=\"bundle.js\"\u003e\u003c/script\u003e\n// \u003cscript\u003e\n//     function runSample() {\n//         const file = document.getElementById('fileButton').files[0];\n//         browserFileUpload(file);\n//\n//         document.getElementById(\"runLog\").innerHTML += \"Sample is running, please see console for output. The process may take a few seconds. \u003cbr\u003e\";\n//     }\n// \u003c/script\u003e\n\nif (jsEnv.isNode) {\n    COURSE_FILE = fs.createReadStream(COURSE_PATH);\n    main();\n} else {\n    window.browserFileUpload = (file) =\u003e {\n        COURSE_FILE = file;\n        main();\n    };\n}\n\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frusticisoftware%2Fscormcloud-api-v2-client-javascript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frusticisoftware%2Fscormcloud-api-v2-client-javascript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frusticisoftware%2Fscormcloud-api-v2-client-javascript/lists"}