# LAMS Integrations API

## Introduction

{% hint style="info" %}
**Recommendation!**

We strongly recommend using **IMS LTI 1.3** as your main integration method. While other integrations may work, standardising on LTI is the better approach, as it now includes robust extensions that improve functionality and compatibility.
{% endhint %}

LAMS provides the API described in this page to create rich and powerful interaction with any 3rd party system. The aim for this integration is to make LAMS appear into an LMS system like yet another native tool of the LMS.

LAMS has ***natively*** been integrated with:

* Blackboard
* Moodle | Check out the [LAMS-Moodle demo](https://moodle.lamsfoundation.org/moodle/)
* Sakai
* And any other that uses [IMS LTI](/lams/administration/system-administration/integrations.md#integrations-via-lti).

In this document, we present a technical overview on how these integrations are implemented. Although each 3rd party applications are different (even they are in different programming languages) the principles that we follow are essentially the same.

## LAMS Side

The following diagrams give the overview and the details of the LAMS and 3rd party app SingleSignOn implementation:

### Overview diagram

![Overview diagram LAMS LMS native integration](/files/-MUm6BJAfrwx8z_GPhpw)

### Single Sign-On Sequence Diagram

![SSO sequence diagram](/files/-MUm6IAdKahhE-ch71SC)

### **User Information** <a href="#lamsand3rdpartyappintegrationapis-userinformation" id="lamsand3rdpartyappintegrationapis-userinformation"></a>

Every time a LMS user attempts to access LAMS and there's no personal details passed, LAMS will check to see if the user exists in its database. If the user has not been created in LAMS, LAMS will make a call to the external application to retrieve user information and create the user on the fly. Therefore you will need to set up a user information servlet on the LMS side that will return user information to LAMS.

**Note** that the callback URL will only take place if the firstName, lastName parameters were **not** passed with the LoginRequest, LearningDesignRepository or LesssonManager (join method). See below.

If you are passing the user details as parameters in the requests, then there will be no call back to the LMS and the user will be created with the details passed.

**Request format**

The user information url is defined in the LAMS System Administration page and contains three parameters: username, timestamp and hash.

For example, the url for moodle is given by:

<http://localhost/moodle/mod/lamstwo/userinfo.php?ts=>%**timestamp**%\&un=%**username**%\&hs=%**hash**%

The hash value is generated using the SHA1 algorithm on the following (all in lower case)\
\[ timestamp + username +  serverID + serverKey ]

**Response Format**

The response from the external application is a comma separated list of 14 values

\<Title>,\<First name>,\<Last name>,\<Address>,\<City>,\<State>,\<Postcode>,\<Country>,\<Day time number>,\<Mobile number>,\<Fax number>,\<Email>,\<Locale language>,\<Locale country>&#x20;

### **Group Information** <a href="#lamsand3rdpartyappintegrationapis-groupinformation" id="lamsand3rdpartyappintegrationapis-groupinformation"></a>

In order to enable import and usage of the groups created on the integrated server (*Blackboard only*), one needs to go to the LAMS System Administration page and enter External groups URL property following the next format:

[https://\<BB\_SERVER>:8443/webapps/lams-lamscontent-BBLEARN/GroupData](https://bb9.lamsinternational.com:8443/webapps/lams-lamscontent-BBLEARN/GroupData)

After this one be able to select and use external groups at the monitoring page of the lesson created via that integrated server.

### **External calls to LAMS** <a href="#lamsand3rdpartyappintegrationapis-externalcallstolams" id="lamsand3rdpartyappintegrationapis-externalcallstolams"></a>

#### Login Requests <a href="#lamsand3rdpartyappintegrationapis-loginrequests" id="lamsand3rdpartyappintegrationapis-loginrequests"></a>

Request for author, learner and monitor are directed through the *LoginRequest* servlet.  For example:

[http://localhost/lams/LoginRequest?](http://localhost/lams/LoginRequest)....

The parameters are:

| Parameter           | Description                                                                                                                                                                                                                                               | Restriction/conditions                                                                                                       |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **uid**             | The username on the external system                                                                                                                                                                                                                       | Must be unique. Only alphanumeric characters and these symbols allowed "\_" "-")                                             |
| **ts**              | Number of milliseconds since January 1, 1970, 00:00:00 GMT (known as "the epoch") till the time when the call is made                                                                                                                                     | Required if according integrated server has "Enforce time limitation" setting ON. And if it's OFF it can be a random String. |
| **sid**             | serverID (see integration configuration)                                                                                                                                                                                                                  |                                                                                                                              |
| **method**          | Either author, monitor, learner or learnerStrictAuth; it sets permissions and redirects user to requested content                                                                                                                                         | Must match one of the methods' name                                                                                          |
| **hash**            | A SHA1 hash of \[ts + uid + method + serverID + serverKey] (Note: all lower case before hashing) If you are using the learnerStrictAuth, you must include the lsId in the hash (see below)                                                                |                                                                                                                              |
| mode                | Additional directive: "preview" for previewing lesson in learner, "gradebook" to access user gradebook after logging in                                                                                                                                   |                                                                                                                              |
| courseid            | the id of the course from the LMS                                                                                                                                                                                                                         | Must be unique for each LMS course                                                                                           |
| lsid                | Used for monitor, learner and gradebook to tell LAMS the lesson id you want to open                                                                                                                                                                       | Required if requesting access to monitor, learner or gradebook UIs                                                           |
| firstName           | Used if a new user is created                                                                                                                                                                                                                             | No numbers or special characters permitted                                                                                   |
| lastName            | Used if a new user is created                                                                                                                                                                                                                             | No numbers or special characters permitted. Only single quotes and spaces allowed ie: O'Harries or Garcia Marquez)           |
| email               | Used if a new user is created                                                                                                                                                                                                                             | Correctly validated email address required                                                                                   |
| country             | Country (must use 2 letter code as [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-2) for country)                                                                                                                                       |                                                                                                                              |
| lang                | Language code or locale code. In case of just passing language use "es" for Spanish or locale as "es\_ES" (see [list of available locales](/lams/administration/system-administration/integrations/lams-integrations-api.md#locale-list-and-ids) in LAMS) |                                                                                                                              |
| isUpdateUserDetails | "true" in case user details should get updated with new information, "false" (or no parameter) otherwise                                                                                                                                                  |                                                                                                                              |
| requestSrc          | String to identify who is making the call, this is only used in authoring to display on the close button.                                                                                                                                                 |                                                                                                                              |
| notifyCloseURL      | Callback URL to refresh the page after a sequences has been added.                                                                                                                                                                                        |                                                                                                                              |

You can use either http method POST or GET.

{% hint style="warning" %}
POST highly preferred!&#x20;
{% endhint %}

### **Mapping external roles to LAMS course roles**

[LAMS course roles](/lams/administration/course-management.md#course-based-roles) are learner, monitor and author.

Therefore passing a method with one of these roles will assign the user the following LAMS course roles

| Method            | Grants roles                |
| ----------------- | --------------------------- |
| Author            | learner, monitor and author |
| Monitor           | monitor                     |
| learner           | learner                     |
| learnerStrictAuth | learner                     |

{% hint style="info" %}
**The learnerStrictAuth method**\
\
Use the **learnerStrictAuth** method when launching students into lessons
{% endhint %}

While you can use the `method=learner` to launch learners into a LAMS lesson, it is strongly recommended that you use the `method=learnerStrictAuth` instead.

When you use **learnerStrictAuth**, you also include the lessonID (lsId) that the user is being launched to into the authentication hash. This prevents any tampering and ensures that the user always goes to the correct lesson.

The main difference within the LoginRequest as explained before is that you use the method `"learnerStrictAuth"` and include the lsId in the hash as follows:

hashText = ToLowerCase(\[ts + uid + method + lsId +serverID + serverKey])

Then use sha1 to hash the hashText.

### Getting LAMS server time and Time to live for LoginRequests

n order for LMS to provide correct timestamp when making a call to LoginRequest it can use this servlet to acquire current LAMS server time.

It can be achieved by making a request to the GetServerTime servlet on the LAMS side. For example:

[http://localhost/lams/services/getServerTime](http://localhost/lams/services/xml/LearningDesignRepository)

Servlet will return the number of milliseconds since January 1, 1970, 00:00:00 GMT [POSIX time](http://en.wikipedia.org/wiki/Unix_time). For example, 1417535668074 (which stand for Dec 02 11:24:28 VET 2014).

No parameters are expected.

You can use either http method POST or GET.

**Why do I need to know the LAMS server time?**

Good question, in LAMS 2.5+ we wanted to add another level of security in case a user attempts to hijack a LoginRequest URL. On LAMS 2.5+ there are two new options when creating an integrated server:

* Enforce time limitation for integration requests (checkbox) and
* Time to live for integration requests (in minutes)

If you enforce a time limitation, then the LoginRequest have a set number (say 5 mins) for this LoginRequest URL "to live". After that time, the URL will be rejected.

So you use getServerTime to find out the POSIX time that the LAMS app is using and then you can calculate the delta with yours. So next time you send a LoginRequest, if you have the `"Enforce time limitation"` checked, then you send the **ts** with the LAMS server time.

### Getting Learning Designs

You will need to get a List of existing learning designs so the LMS user can choose which ones they wish to start.\
You can get a list of learning designs by making a request to the LearningDesignRepository servlet on the LAMS side. For example:

[http://localhost/lams/services/xml/LearningDesignRepository?](http://localhost/lams/services/xml/LearningDesignRepository)

The parameters are:

### Starting, Stopping, Scheduling, Removing or Cloning a Lesson

To start, stop, schedule or clone a lesson in LAMS you need request another servlet:&#x20;

[http://localhost/lams/services/xml/LessonManager?](http://localhost/lams/services/xml/LessonManager)

The parameters are:

* username - the username of the current user
* serverId - the server id
* datetime - timestamp
* hashValue - SHA1 hash of \[timestamp + username + serverID + serverKey]  (Note: all lower case)
* courseId - the id of the course from the LMS *(excluding removeLesson)*
* country - Country (must use 2 letter code as [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-2) for country)
* lang - Language code or locale code. In case of just passing language use "es" for Spanish or locale as "es\_ES" (see [list of available locales](/lams/administration/system-administration/integrations/lams-integrations-api.md#locale-list-and-ids) in LAMS)
* method - "start", "stop", "schedule", "removeLesson"/"removeAllLessons" or "clone"
* ldId - the id of the learning design *(for start and schedule methods)*
* lsId - the id of the lesson *(for stop, removeLesson, clone)*
* title - the title of the lesson *(for start and schedule)*
* desc - the description of the lesson *(for start and schedule)*
* learnerEnableExport - enables exporting portfolio by learners. Optional, default value: false *(for start and schedule)*
* learnerSeeOnline - enables learner presence in the lesson. Optional, default value: false *(for preview, start and schedule)*
* learnerInstantMessaging - enables learner instant messaging in the lesson. Optional, default value: false *(for preview, start and schedule)*
* enableNotifications - enables "email notifications" link for the lesson. Optional, default value: false *(for start and schedule)*
* allowLearnerRestart - whether learners are allowed to restart the lesson. Optional, default value: according LAMS ExtServer's default setting \_(for start and schedule)

This servlet returns an xml response depending on the method ('start', 'schedule' or 'stop').

* Start - An xml node called "Lesson" with an attribute "lessonId" which contains the lesson id.
* Schedule - An xml node called "Lesson" with an attribute "lessonId" which contains the lesson id.
* Stop - An xml node called "Lesson" with an attribute "deleted" which informs you whether the lesson was successfully deleted in LAMS
* Clone - An xml node called "Lesson" with an attribute "lessonId" which contains the new lesson id.

You can use either http method POST or GET.

### Pre-adding students and monitors to a lesson

By default, the LoginRequest servlet will add students/monitors to an existing lesson automatically. But in some cases you might want/need to pre-add the students/monitors to the lesson

For this, you can use the LessonManager servlet and make only one call passing all usernames for all the students and monitors:

[http://localhost/lams/services/xml/LessonManager?](http://localhost/lams/services/xml/LessonManager)

The parameters are:

* &#x20;username - the username of the current user
* &#x20;serverId - the server id
* &#x20;datetime - timestamp
* &#x20;hashValue - SHA1 hash of \[timestamp + username + serverID + serverKey]  (Note: all lower case)
* &#x20;courseId - the id of the course from the LMS
* &#x20;country - Country (must use 2 letter code as [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-2) for country)
* &#x20;lang - Language code or locale code. In case of just passing language use "es" for Spanish or locale as "es\_ES" (see [list of available locales](/lams/administration/system-administration/integrations/lams-integrations-api.md#locale-list-and-ids) in LAMS)
* &#x20;lsId - the id of the lesson
* &#x20;method - "join"
* &#x20;learnerIds - a comma separated string with all the students' usernames (ie: johnd,ernieg,fei,sarah)
* &#x20;monitorIds - a comma separated string with all the monitors' usernames

You can use either http method POST or GET.

If the learners and monitors are to be created in LAMS, you must pass their user details following a few conventions:

* firstNames, lastNames, emails - these are comma separated parameters;
* if there is a need to create even only one user it is required to supply comma separated list of all users going to be joined to lesson (i.e.: if learnerIds=user1,user1). Then each of the new parameters should have 2 values, like firstNames=name1,name2.
* in case if you want to join monitors as well during one call - learner's parameters should go first, before monitor's ones
* if any of these 3 parameters(firstNames, lastNames, emails) is provided it is expected that all of them have the **same number of comma separated elements**

LAMS will **not** create the users if the number of usernames, firstnames and lastnames is not the same.

While you can use GET to post this,

### Removing users from a lesson

Removes user(s) completely from a lesson regardless of his/her role with it.&#x20;

Call LessonManager servlet: [http://localhost/lams/services/xml/LessonManager?](http://localhost/lams/services/xml/LessonManager)

The parameters are:

* &#x20;username - the username of the current user
* &#x20;serverId - the server id
* &#x20;datetime - timestamp
* &#x20;hashValue - SHA1 hash of \[timestamp + username + serverID + serverKey]  (Note: all lower case)
* &#x20;lsId - the id of the lesson
* &#x20;method - "removeUser" or "removeAllUsers"
* &#x20;userIds - a comma separated string with all the users' usernames (ie: johnd,ernieg,fei,sarah) *(for removeUser only)*

### Previewing a lesson

This is the same as starting a lesson. The only thing that changes here is that the title and the method is to be set to **preview**. Once you get the lessonId, just compose the LoginRequest as usual with mode = **preview**. That's all ![(smile)](https://wiki.lamsfoundation.org/s/en_US/8100/6512c1e2a41cdf14570641b46bd2fe3eaeb38d03/_/images/icons/emoticons/smile.svg)

#### Get Design Image <a href="#lamsand3rdpartyappintegrationapis-getdesignimage" id="lamsand3rdpartyappintegrationapis-getdesignimage"></a>

In LAMS version **2.3.5+** (that's the latest on the [lams2\_3\_release branch](https://wiki.lamsfoundation.org/display/lams/CVS+Repositories%2C+Branching+and+TAGS)), you are able to get a learning design image (the learning design activity drawing) from an integration.

[http://localhost/lams/services/LearningDesignSVG?](http://localhost/lams/services/LearningDesignSVG)\
The parameters are:

* &#x20;serverId - the server id
* &#x20;datetime - timestamp
* &#x20;hashValue - SHA1 hash of \[timestamp + username + serverID + serverKey]  (Note: all lower case)
* &#x20;username - the username of the current user
* &#x20;ldId - the id of the learning design (for starting or scheduling)
* &#x20;svgFormat - image format (svgFormat can be either 1 for SVG or 2 for PNG)

The response is the image content (bytes), so you can set it as "src" attribute of a \<img> tag.

You need to use http method GET.

### Get user progress for a lesson

To get a user progress for a lesson, you must also request the LessonManagerServlet. You can either get a specific progress for a user, or a list of progresses for an entire lesson.

The parameters are:

* username - the username of the current user
* serverId - the server id
* datetime - timestamp
* hash - SHA1 hash of \[timestamp + username + serverID + serverKey]  (Note: all lower case)
* method - singleStudentProgress or studentProgress for the list of progresses
* lsId - the lesson id
* courseId - the course id\
  There are 3 additional parameters for single user progress (`method=singleStudentProgress`)
* firstName - first name of the user who's progress you wish to retrieve
* lastName - last name of the user who's progress you wish to retrieve
* email - email of the user who's progress you wish to retrieve

You can use either http method POST or GET.

You will receive an xml response in the following form:

#### For single user progress

```markup
<LearnerProgress
    lessonComplete="true"
    activityCount="4"
    activitiesCompleted="4"
    attemptedActivities="4"
    studentId="304"
    courseId="MATH101"
    username="testUser"
    lessonId="13"
>
</LearnerProgress>
```

#### For multiple user progresses

```markup
<LessonProgress>
 
     <LearnerProgress
         lessonComplete="true"
         activityCount="4"
         activitiesCompleted="4"
         attemptedActivities="4"
         studentId="304"
         courseId="MATH101"
         username="testUser"
         lessonId="13"
     >
     </LearnerProgress>
      
     <LearnerProgress
         lessonComplete="false"
         activityCount="4"
         activitiesCompleted="2"
         attemptedActivities="3"
         studentId="114"
         courseId="MATH101"
         username="stephenh"
         lessonId="13"
     >
     </LearnerProgress>
 
  
</LessonProgress>
```

### Get lessons where an user has Monitor role

To get a list of lesson for which the given user has Monitor role you must request LessonManagerServlet.

The parameters are:

* username - the username of the current user
* serverId - the server id
* datetime - timestamp
* hash - SHA1 hash of \[timestamp + username + serverID + serverKey]  (Note: all lower case)
* method - use "listMonitor"
* courseId - the course id

You will receive an xml response in the following form:

```markup
<Lessons>
  <Lesson lessonId="5" name="myLesson1"       description="math lesson" state="3" />
  <Lesson lessonId="8" name="someOtherLesson" description="eng lesson"  state="5" />
</Lessons>
```

### Get tool outputs (marks) from a lesson

At times you might want to get the marks that the student(s) got in a LAMS activity -for instance the mark of a multiple choice.

For that you need to change the methods as follows:

1. method=toolOutputsAllUsers: This one gets all outputs for all activities and for all users, see toolOutputsAllUsers.xml
2. method=authoredToolOutputsAllUsers: This one gets the requested outputs (which were pre-defined in author in the learning design) for each activity and prints them out for each user. See authoredToolOutputsAllUsers.xml
3. method=toolOutputsUser: This one gets all the outputs for an activity, but only for the specified user, see toolOutputsUser.xml
4. method=authoredToolOutputsUser: This one gets the requested outputs (which were pre-defined in author in the learning design)for each activity, but just for the specified user, see authoredToolOutputsUser.xml

You can use either http method POST or GET.

Calling:\
http\://\<lams-server>:8080/lams//services/xml/LessonManager?\&serverId=xxx\&courseId=xxx\&username=test1\&datetime=xxx\&hashValue=xxx\&lang=en\&country=AU\&method=toolOutputsAllUsers\&lsId=1

you get: **toolOutputsAllUsers.xml**

```markup
<?xml version="1.0" encoding="UTF-8"?>
<ToolOutputs lessonId="1" name="mc">
    <LearnerOutput completedLesson="false" firstName="Mary" lamsUserId="4" lamsUserName="mmm" lastName="Morgan" userName="mmm">
        <Activity activityId="6" attempted="true" completed="true" title="MC1">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="true" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="1" type="long" />
        </Activity>
        <Activity activityId="5" attempted="true" completed="false" title="MC2" />
        <Activity activityId="7" attempted="false" completed="false" title="MC3" />
    </LearnerOutput>
    <LearnerOutput completedLesson="false" firstName="Two" lamsUserId="6" lamsUserName="test2" lastName="Test" userName="test2">
        <Activity activityId="6" attempted="true" completed="false" title="MC1" />
        <Activity activityId="5" attempted="false" completed="false" title="MC2" />
        <Activity activityId="7" attempted="false" completed="false" title="MC3" />
    </LearnerOutput>
    <LearnerOutput completedLesson="true" firstName="Four" lamsUserId="8" lamsUserName="test4" lastName="Test" userName="test4">
        <Activity activityId="6" attempted="true" completed="true" title="MC1">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="false" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
        <Activity activityId="5" attempted="true" completed="true" title="MC2">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="false" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
        <Activity activityId="7" attempted="true" completed="true" title="MC3">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="false" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
    </LearnerOutput>
    <LearnerOutput firstName="Jacky" lamsUserId="3" lamsUserName="lamskh01" lastName="Fang" userName="lamskh01">
        <Activity activityId="6" attempted="false" completed="false" title="MC1" />
        <Activity activityId="5" attempted="false" completed="false" title="MC2" />
        <Activity activityId="7" attempted="false" completed="false" title="MC3" />
    </LearnerOutput>
    <LearnerOutput completedLesson="true" firstName="One" lamsUserId="5" lamsUserName="test1" lastName="Test" userName="test1">
        <Activity activityId="6" attempted="true" completed="true" title="MC1">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="true" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="1" type="long" />
        </Activity>
        <Activity activityId="5" attempted="true" completed="true" title="MC2">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="false" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
        <Activity activityId="7" attempted="true" completed="true" title="MC3">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="false" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
    </LearnerOutput>
    <LearnerOutput firstName="Three" lamsUserId="7" lamsUserName="test3" lastName="Test" userName="test3">
        <Activity activityId="6" attempted="false" completed="false" title="MC1" />
        <Activity activityId="5" attempted="false" completed="false" title="MC2" />
        <Activity activityId="7" attempted="false" completed="false" title="MC3" />
    </LearnerOutput>
    <LearnerOutput firstName="Testing" lamsUserId="2" lamsUserName="test" lastName="LDAP" userName="test">
        <Activity activityId="6" attempted="false" completed="false" title="MC1" />
        <Activity activityId="5" attempted="false" completed="false" title="MC2" />
        <Activity activityId="7" attempted="false" completed="false" title="MC3" />
    </LearnerOutput>
</ToolOutputs>
```

Calling:\
http\://\<your-lams>:8080/lams//services/xml/LessonManager?\&serverId=xxx\&courseId=xxx\&username=test1\&datetime=xxx\&hashValue=xxx\&lang=en\&country=AU\&method=authoredToolOutputsAllUsers\&lsId=1\
You get:\
**authoredToolOutputsAllUsers.xml**

You can use either http method POST or GET.

Calling:\
http\://\<your-lams>:8080/lams//services/xml/LessonManager?\&serverId=xxx\&courseId=xxx\&username=test1\&datetime=xxx\&hashValue=xxx\&lang=en\&country=AU\&method=toolOutputsUser\&lsId=1\&outputsUser=testXYZ

You get:\
**toolOutputsUser.xml**

```markup
<?xml version="1.0" encoding="UTF-8"?>
<ToolOutputs lessonId="1" name="mc">
    <LearnerOutput completedLesson="true" firstName="One" lamsUserId="5" lamsUserName="test1" lastName="Test" userName="test1">
        <Activity activityId="6" attempted="true" completed="true" title="MC1">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="true" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="1" type="long" />
        </Activity>
        <Activity activityId="5" attempted="true" completed="true" title="MC2">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="false" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
        <Activity activityId="7" attempted="true" completed="true" title="MC3">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="false" type="boolean" />
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
    </LearnerOutput>
</ToolOutputs>
```

Calling:\
http\://\<your-lams>:8080/lams//services/xml/LessonManager?\&serverId=xxx\&courseId=xxx\&username=test1\&datetime=xxx\&hashValue=xxx\&lang=en\&country=AU\&method=authoredToolOutputsUser\&lsId=1\&outputsUser=testXYZ

You get:\
**authoredToolOutputsUser.xml**

```markup
<?xml version="1.0" encoding="UTF-8"?>
<ToolOutputs lessonId="1" name="mc">
    <LearnerOutput completedLesson="true" firstName="One" lamsUserId="5" lamsUserName="test1" lastName="Test" userName="test1">
        <Activity activityId="6" attempted="true" completed="true" title="MC1">
            <ToolOutput description="Are learner's answers all correct?" name="learner.all.correct" output="true" type="boolean" />
        </Activity>
        <Activity activityId="5" attempted="true" completed="true" title="MC2">
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
        <Activity activityId="7" attempted="true" completed="true" title="MC3">
            <ToolOutput description="Learner's total mark" name="learner.mark" output="0" type="long" />
        </Activity>
    </LearnerOutput>
</ToolOutputs>
```

### Get Gradebook for Lesson or Course

To get Gradebook for a particular lesson or a whole course you need to send a request Gradebook servlet:&#x20;

[http://localhost/lams/services/Gradebook?](http://localhost/lams/services/xml/LessonManager)

The parameters are:

* &#x20;uid - the username of the current user
* &#x20;method -  either author, monitor or learner; see description below
* &#x20;ts - timestamp
* &#x20;sid - the server id
* &#x20;hash - SHA1 hash of \[ts + uid + method + serverID + serverKey]  (Note: all lower case)
* &#x20;country - Country (must use 2 letter code as [ISO 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/ISO_3166-2) for country)
* &#x20;lang - Language code or locale code. In case of just passing language use "es" for Spanish or locale as "es\_ES" (see [list of available locales](/lams/administration/system-administration/integrations/lams-integrations-api.md#locale-list-and-ids) in LAMS)
* &#x20;courseid - the id of the course from the LMS
* &#x20;lsid - the id of the lesson
* courseName - the LMS's course name

You can use either http method POST or GET.

Gradebook content can be obtained two ways:

* if the user is already logged in, a direct call to Gradebook servlet will return the desired content; "method" parameter is still required for hash, but has no meaning in processing
* Gradebook content can be also delivered by calling LoginRequest servlet, which will log the user in first; in this case the request to LoginRequest servlet needs to have "method" and "courseid" parameters set (same as in a plain call to this servlet), plus "mode" parameter set to "gradebook"

If ID of an external course is provided (it must be in case of calling LoginRequest, but it is not required when calling Gradebook servlet directly), it is translated into internal LAMS organisation ID and user is redirected to Gradebook for this course. If lsId is provided, it has higher priority than courseid and user is redirected to Gradebook for this particular lesson.

### Get total user marks in a lesson

It's possible to get either a lesson total mark for one specified user, or lesson total marks for all users in a lesson, or lesson total marks for all users in all lessons in a course.

To get total user marks from LAMS you need to make a call to the following servlet:  [http://localhost/lams/services/xml/LessonManager?](http://localhost/lams/services/xml/LessonManager)\
The parameters are:

* username - the username of the current user
* serverId - the server id
* datetime - timestamp
* hashValue - SHA1 hash of \[timestamp + username + serverID + serverKey]  (Note: all lower case)
* method - gradebookMarksUser for lesson total mark for a specified user or gradebookMarksLesson for all users in a lesson or gradebookMarksCourse - for all users for all lessons in a course
* lsId - the lesson id *(only for method=gradebookMarksUser and method=gradebookMarksLesson)*
* courseId - the course id *(only for method=gradebookMarksCourse)*
* outputsUser - the username of the user who's progress you wish to retrieve *(only for method=gradebookMarksUser)*

You will receive an xml response in the following format:

For single user total mark:

```markup
<GradebookMarks>
    <Lesson
        lessonId="13"
        lessonName="Big lesson"
        lessonMaxPossibleMark="4">
        <Learner
            extUsername="alex"
            userTotalMark="3">
        </Learner>
    </Lesson>
</GradebookMarks>
```

In case of method=gradebookMarksLesson there will be multiple \<Learner> elements. And in case of method=gradebookMarksCourse there will be multiple \<Lesson> elements.

### Locale List and IDs

Use the locale\_id according to the language and country you want to choose for a user:

| locale\_id | language\_iso\_code | country\_iso\_code | language name        |
| ---------- | ------------------- | ------------------ | -------------------- |
| locale\_id | language\_iso\_code | country\_iso\_code | language name        |
| 1          | en                  | AU                 | English (Australia)  |
| 2          | es                  | ES                 | Espanol              |
| 3          | mi                  | NZ                 | Maori                |
| 4          | de                  | DE                 | Deutsch              |
| 5          | zh                  | CN                 | Chinese (China)      |
| 6          | fr                  | FR                 | French (France)      |
| 7          | it                  | IT                 | Italiano             |
| 8          | no                  | NO                 | Norsk                |
| 9          | sv                  | SE                 | Svenska              |
| 10         | ko                  | KR                 | Korean               |
| 11         | pl                  | PL                 | Polski               |
| 12         | pt                  | BR                 | Portugues (Brasil)   |
| 13         | hu                  | HU                 | Magyar               |
| 14         | bg                  | BG                 | Bulgarian            |
| 15         | cy                  | GB                 | Cymraeg (Cymru)      |
| 16         | th                  | TH                 | Thai                 |
| 17         | el                  | GR                 | Greek                |
| 18         | nl                  | BE                 | Nederlands (Belgium) |
| 19         | ar                  | JO                 | Arabic (Jordan)      |
| 20         | da                  | DK                 | Dansk                |
| 21         | ru                  | RU                 | Russian              |
| 22         | vi                  | VN                 | Vietnamese           |
| 23         | zh                  | TW                 | Chinese (Taiwan)     |
| 24         | ja                  | JP                 | Japanese             |
| 25         | ms                  | MY                 | Malay (Malaysia)     |
| 26         | tr                  | TR                 | Turkish              |
| 27         | ca                  | ES                 | Catalan              |

## Easy integration example

Check out Integration example to get a quick overview on how you can integration your LMS to LAMS.

This is a *manual* integration example that would hopefully help you to create an integration with LAMS quickly.

First, I created an integration server in LAMS (login as sysadmin and then go to the syadmin menu) with these settings:

![Integration example settings on LAMS side. ](/files/-MUmBciiwqA4heX-iToS)

Obviously, change the URLS according to yours.

### **Open author**

Creates a user, the course, adds the user as author into it and then redirects the user directly to the Author UI

**Prepare hash**: \[ts + uid + method + serverID + serverKey]\
sha1(1roger01authorlmslms) = 2694cbe4a627b9798824453e65d0f13f8dc1f5e3

**URL**: <http://lams-server/lams/LoginRequest?uid=roger01&ts=1&sid=lms&method=author&courseid=123&firstName=Roger&lastName=Moore&email=roger@gmail.com&country=AU&lang=en&hash=2694cbe4a627b9798824453e65d0f13f8dc1f5e3>

**Result:**\
open LAMS author, create a sequence called "Some sequence" and saved

### **Get learning designs for roger01**

**Prepare hash**: \[timestamp + username + serverID + serverKey]

sha1(1roger01lmslms) = a8c722c31ac21e719145d15febf6df246ea16d16

**URL:**

<http://lams-server/lams/services/xml/LearningDesignRepository?username=roger01&datetime=1&serverId=lms&courseId=123&courseName=lola&mode=2&firstName=Roger&lastName=Moore&email=roger@gmail.com&country=AU&lang=en&hashValue=a8c722c31ac21e719145d15febf6df246ea16d16>

**Result:**

Shows me all the lessons available for Roger to create lessons. You can see "Some sequence" within Roger Moore's personal folder.

```markup
<?xml version="1.0" encoding="UTF-8"?>
<Folder name="My Workspace">
   <Folder name="Roger Moore">
      <LearningDesign name="Some sequence" resourceId="2173" />
   </Folder>
   <Folder name="My Courses">
      <Folder name="lms_lola">
         <Folder name="lms_lola Run Sequences" />
      </Folder>
   </Folder>
   <Folder name="Public Folder">
      <LearningDesign name="11" resourceId="264" />
      <LearningDesign name="bbb" resourceId="318" />
      <LearningDesign name="map_sequence" resourceId="2169" />
      <LearningDesign name="map_sequence_2" resourceId="2170" />
      <LearningDesign name="map_sequence_3" resourceId="2171" />
      <LearningDesign name="multiple leaders" resourceId="2065" />
      <LearningDesign name="Sample Activity" resourceId="2151" />
      <LearningDesign name="Test1" resourceId="1482" />
      <LearningDesign name="Τηλεδιάσεκεψη" resourceId="324" />
      <Folder name="ABC">
         <LearningDesign name="123" resourceId="203" />
         <LearningDesign name="44" resourceId="205" />
      </Folder>
   </Folder>
</Folder>
```

### **Start a lesson**

**Prepare hash:** \[timestamp + username + serverID + serverKey]

sha1(1roger01lmslms) = a8c722c31ac21e719145d15febf6df246ea16d16

**URL:**

<http://lams-server/lams/services/xml/LessonManager?username=roger01&serverId=lms&datetime=1&courseId=123&ldId=2173&method=start&title=Lesson01&desc=somedesc&hashValue=a8c722c31ac21e719145d15febf6df246ea16d16>

**Returns:**

The lessonId ready to be used

```markup
<?xml version="1.0" encoding="UTF-8"?>
<Lesson lessonId="1537" />
```

### **Jump into monitor to this lesson**

**Prepare hash:**

sha1(1roger01monitorlmslms) = 81079e7430329662ba19050e6d5d80395a7fab53

**URL:**

<http://lams-server/lams/LoginRequest?uid=roger01&ts=1&sid=lms&method=monitor&courseid=123&firstName=Roger&lastName=Moore&email=roger@gmail.com&country=AU&lang=en&hash=81079e7430329662ba19050e6d5d80395a7fab53&lsid=1537>

**Result:**

Opens Monitor UI for that lesson

### **Jump into this lesson as learner (using learnerStrictAuth method)**

Roger goes into the lesson as learner. Note that learnerStrictAuth is only available for LAMS 2.5+

**Prepare hash:** \[ts + uid + method + lsId +serverID + serverKey]

sha1(1roger01learnerstrictauth1537lmslms) = 109cf9886c6fcb926a29a6d10d217de7c524016d

**URL:**

<http://lams-server/lams/LoginRequest?uid=roger01&ts=1&sid=lms&method=learnerStrictAuth&courseid=123&firstName=Roger&lastName=Moore&email=roger@gmail.com&country=AU&lang=en&hash=109cf9886c6fcb926a29a6d10d217de7c524016d&lsid=1537>

**Result:**

Open Learner UI

### **Jump into this lesson as a new learner (using learner method)**

This will create the user, added to the course and also the lesson as leaner. Note that this method works with 2.4 and 2.5+

**Prepare hash:** \[ts + uid + method +serverID + serverKey]

sha1(1daniel007learnerlmslms) = c86882105c7db67e438be44919e6113fa17b4596

**URL:**

<http://lams-server/lams/LoginRequest?uid=daniel007&ts=1&sid=lms&method=learnerStrictAuth&courseid=123&firstName=Daniel&lastName=Craig&email=daniel@gmail.com&country=AU&lang=en&hash=c86882105c7db67e438be44919e6113fa17b4596&lsid=1537>

**Result:**

Open Learner UI, creates the user, adds it to the course and lesson just as leaner.

### **Jump in this lesson as a new Monitor (just for kicks** :grinning:)

**Prepare hash:**

sha1(1sean007monitor1537lmslms) = bbbf4b5f8b63291ee10c32d7e9181024d2326fa7

**URL:**

<http://lams-server/lams/LoginRequest?uid=sean007&ts=1&sid=lms&method=monitor&courseid=123&firstName=Sean&lastName=Connery&email=sean@gmail.com&country=AU&lang=en&hash=bbbf4b5f8b63291ee10c32d7e9181024d2326fa7&lsid=1537>

**Result:**

Opens Monitor UI. You can see on the sequence tab that there's two students (Roger and Daniel)

I think by now you pretty much get the idea how the integration works and how to get all the other API calls to work.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.lamsfoundation.org/lams/administration/system-administration/integrations/lams-integrations-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
