Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents

API Interface Documentation

All available API endpoints incl. parameters and response data structures (except the login endpoint) can be found on your LMS url + /help (no login is required). 

...

This document only contains a selection of endpoints with detailed information on how to use them.

API Connection Protocol

Please note that all connections to the API are required to use the security protocol TLS v1.2.

Example in C#

Code Block
System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol | System.Net.SecurityProtocolType.Tls12;

Logon (Post)

POST https://[fill-in-your-lms-domain]/services/api/oauth2/token

Body Parameters

grant_type: ‘password’
username:  org login Id or LMS user name
password: login password as clear text
scope: path to the organization like /Root/MyOrg (mandatory if org login Id is used for username)

...

Headers

Content-Type: application/x-www-form-urlencoded

...

Response

access_token is used to call into the API endpoints for authentication
refresh_token is used to refresh the access_token and extend the expiry of the token
expires_in in seconds until the access_token and refresh_token is invalid

...

Refresh Token

POST https://[fill-in-your-lms-domain]/services/api/oauth2/token

Body Parameters

grant_type: refresh_token
refresh_token: Use the refresh_token from the response during login

...

Headers

Content-Type: application/x-www-form-urlencoded

...

Response

access_token is used to call into the API endpoints for authentication
refresh_token is used to refresh the access_token and extend the expiry of the token
expires_in in seconds until the access_token and refresh_token is invalid

...

JSON Result Property Mapping

Some JSON result properties have integer values with a specific meaning. This section lists all mappings.

  • RegistrationStatus 

    • 0 = Pending

    • 1 = Active

    • 2 = Completed

  • RegistrationCreationType 

    • 0 = Unknown

    • 1 = Historical

    • 2 = Auto

    • 3 = Imported

    • 4 = Self

    • 5 = Manual

  • StudentResultAuditType 

    • 0 = ExamInstance

    • 1 = EvaluationInstance

    • 2 = ExternalGradeInstance

GetActiveRegistrationData

POST https://[fill-in-your-lms-domain]/Services/api/ExternalRegistration/GetActiveRegistrationData

URL Parameters

orgPath={orgPath}
fromDate={from date and time of format ISO 8601 in UTC (i.e. yyyy-mm-ddThh:mmZ)}
suppressCourseCodeFiltering={suppressCourseCodeFiltering}

...

  • The fromDate is the fence post date and time to return registrations with modification date > fromDate

  • suppressCourseCodeFiltering is optional and is set to ‘false’ by default. ‘false’ retains the existing behaviour.

...

Headers

Content-Type: application/json
Authorization: Bearer [access_token from the login]
Accept: application/json

Notes:
Alternative values for Content-Type and Accept: application/xml 

...

Body

Optional but recommended paging via JSON object 

...

Response

The response has a structure with the following fields:

  • Items: array of registrations. Empty [ ], if no registrations were found. Max. PageSize registrations are returned for one request. All registrations are returned if no page size has been passed in the request (not recommended)

  • TotalItems: count of all registrations found according to the request parameters

  • PageSize: page size passed in the request. 0 if no page size has been requested

  • FirstIndexOfNextPage: use this value as StartIndex to retrieve the next page. If FirstIndexOfNextPage >= TotalItems you have reached the last page. Continue to get the next page as long as FirstIndexOfNextPage < TotalItems.
    Always 0 if no pageInfo or PageSize was set for the request.

Response Data

Code Block
{
	"Items": [
		{
			"CourseCode": "9973469",
			"FirstName": "Pat327",
			"LastName": "Learner",
			"OrganizationLoginId": "PatLearner327",
			"UniqueLoginId": "PatLearner327",
			"EmailAddress": "PatLearner327@marinels.com",
			"ContactEmail": "PatLearner327@marinels.com",
			"CourseName": "OSHA 1",
			"CourseId": "2806f1bb-2eb5-11e7-80c0-0cc47a6f32d1",
			"OfferingShortId": "OSHA1",
			"RegistrationDate": "2017-07-07T22:13:49.3670000Z",
			"RegistrationId": "bb06f1bb-2eb5-11e7-80c0-0cc47a6f32cb",
			"RegistrationStatus": 1,
			"OrgProfileFieldValues": [
				{
					"Name": "Rank",
					"Value": "none"
				},
				{
					"Name": "Vessel",
					"Value": "My Vessel 1"
				}
			]
		},
		{
			"CourseCode": "9973469",
			"FirstName": "Pat326",
			"LastName": "Learner",
			"OrganizationLoginId": "PatLearner326",
			"UniqueLoginId": "PatLearner326",
			"EmailAddress": "PatLearner326@marinels.com",
			"ContactEmail": "PatLearner326@marinels.com",
			"CourseName": "OSHA 1",
			"CourseId": "2806f1bb-2eb5-11e7-80c0-0cc47a6f32d1",
			"OfferingShortId": "OSHA1",
			"RegistrationDate": "2017-07-07T22:13:49.5370000Z",
			"RegistrationId": "c806f1bb-2eb5-11e7-80c0-0cc47a6f32ff",
			"RegistrationStatus": 1,
			"OrgProfileFieldValues": [
				{
					"Name": "Rank",
					"Value": "none"
				},
				{
					"Name": "Vessel",
					"Value": "My Vessel 2"
				}
			]
		}
	],
	"TotalItems": 7502,
	"PageSize": 2,
	"FirstIndexOfNextPage": 2
}

GetCompletedRegistrationData

POST https://[fill-in-your-lms-domain]/Services/api/ExternalRegistration/GetCompletedRegistrationData

URL Parameters

orgPath={orgPath}
fromDate={from date and time of format ISO 8601 in UTC (i.e. yyyy-mm-ddThh:mmZ)}
suppressCourseCodeFiltering={suppressCourseCodeFiltering}

...

  • The fromDate is the fence post date and time to return registrations with modification date > fromDate

  • ‘suppressCourseCodeFiltering’ is optional and is set to ‘false’ by default. ‘false’ retains the existing behaviour.

...

Headers

Content-Type: application/json
Authorization: Bearer [access_token from the login]
Accept: application/json

Notes:
Alternative values for Content-Type and Accept: application/xml 

...

Body

Optional but recommended paging via JSON object 

...

Response

The response has a structure with the following fields:

  • Items: array of registrations. Empty [ ], if no registrations were found. Max. PageSize registrations are returned for one request. All registrations are returned if no page size has been passed in the request (not recommended)

  • TotalItems: count of all registrations found according to the request parameters

  • PageSize: page size passed in the request. 0 if no page size has been requested

  • FirstIndexOfNextPage: use this value as StartIndex to retrieve the next page. If FirstIndexOfNextPage >= TotalItems you have reached the last page. Continue to get the next page as long as FirstIndexOfNextPage < TotalItems.
    Always 0 if no pageInfo or PageSize was set for the request.

Response Data

Code Block
{
	"Items": [
		{
			"CourseCode": "TEST",
			"FirstName": "Pat222",
			"LastName": "Learner",
			"OrganizationLoginId": "PatLearner222",
			"UniqueLoginId": "PatLearner222",
			"EmailAddress": "PatLearner222@marinels.com",
			"ContactEmail": "PatLearner222@marinels.com",
			"CourseName": "Initiation A",
			"CourseId": "a5d2a4aa-19f1-11e7-80bf-0cc47a6f32d0",
			"OfferingShortId": "InitA",
			"CompletionDate": "2017-04-07T23:14:48.9370000Z",
			"RegistrationDate": "2017-04-05T18:18:28.7070000Z",
			"RegistrationId": "aa06f1bb-2eb5-11e7-80c0-0cc47a6f32c8",
			"RegistrationStatus": 2,
			"OrgProfileFieldValues": [
				{
					"Name": "Rank",
					"Value": "none"
				},
				{
					"Name": "Vessel",
					"Value": "My Vessel 1"
				}
			]
		},
		{
			"CourseCode": "TEST",
			"FirstName": "Pat143",
			"LastName": "Learner",
			"OrganizationLoginId": "PatLearner143",
			"UniqueLoginId": "PatLearner143",
			"EmailAddress": "PatLearner143@marinels.com",
			"ContactEmail": "PatLearner143@marinels.com",
			"CourseName": "Initiation A",
			"CourseId": "a5d2a4aa-19f1-11e7-80bf-0cc47a6f32d0",
			"OfferingShortId": "InitA",
			"CompletionDate": "2017-07-02T09:48:56.3370000Z",
			"RegistrationDate": "2017-04-06T21:07:45.1530000Z",
			"RegistrationId": "ee06f1bb-2eb5-11e7-80c0-0cc47a6f32c1",
			"RegistrationStatus": 2,
			"OrgProfileFieldValues": [
				{
					"Name": "Rank",
					"Value": "none"
				},
				{
					"Name": "Vessel",
					"Value": "My Vessel 1"
				}
			]
		}
	],
	"TotalItems": 98,
	"PageSize": 2,
	"FirstIndexOfNextPage": 2
}

Which Registrations are Included in the Response?

The registration completion date and fromDate parameter usually correlate with each other. However, if the data is coming from a vessel via sync the completion date and the time when it would show up in a GetCompletedRegistrationData call does not correlate with the passed in fromDate. The completion date of a registration is the time an exam/evaluation was completed to reflect the completion as accurately as possible (e.g. on a vessel). However, the synchronization of data from Vessel to Main and registration completion rules may take a bit of time (depending on sync interval and connectivity of the vessel and when registration processing happens on Main). If the API were only checking for completion date >= fromDate it would miss completed registrations which were synced after the fromDate but had completion dates before the fromDate - due to the sync/processing delay the completion date would be in the past. Therefore, the fromDate checks the ModifiedDate of the registration to determine whether it should get exported. That is to ensure you don't miss completed registrations which have been completed in the past but synced at a later date because the vessel was not able to sync the data in time.

...

Using a fromDate 2022-07-14T23:03:10.000Z would include the registration record: fromDate = 2022-07-14T23:03:10.000Z minus 5 min. = 2022-07-14T22:58:10.000. The DateModified of the record is 2022-07-14 22:58:21.073 and therefore AFTER the fromDate. That is why it would include the record using a fromDate = 2022-07-14T23:03:10.000Z.

A side note to be aware of for selecting the next fromDate

Calculating the fromDate for the next interval should be the date and time just before you issue the first GetCompletedRegistrationData call. This ensures that you don't miss out any registration records due to the time the API calls and processing of the retrieved data takes.

  1. currentFromDate = retrieve stored date and time from last time

  2. nextFromDate = Now()

  3. call GetCompletedRegistrationData(currentFromDate,...) and data processing

  4. On success: store nextFromDate to load next time as currentFromDate

Paging API Calls

Most API endpoints support paging if the expected response can be large. The paging info is passed as request body (also see details for API endpoints) and is always recommended if available.

Request Body

Code Block
{"PageSize":60000, "StartIndex":0}

Response Object Properties

  • Items: array of registrations. Empty [ ], if no registrations were found. Max. PageSize registrations are returned for one request. All registrations are returned if no PageSize has been passed in the request (not recommended)

  • TotalItems: count of all registrations found according to the request parameters

  • PageSize: page size passed in the request. 0 if no PageSize has been requested (not recommended)

  • FirstIndexOfNextPage: use this value as StartIndex in your request to retrieve the next page. If FirstIndexOfNextPage >= TotalItems you have reached the last page. In other words, continue to get the next page as long as FirstIndexOfNextPage < TotalItems.

Note: FirstIndexOfNextPage would always be 0 if no pageInfo or PageSize was set for the request (not recommended).

Attention on changing TotalItems

The API calls are operating in a dynamic and busy environment across multiple transactions. That is, parallel processes may modify data you may request. Therefore, the result count returned may change while paging through the result set via multiple API calls. That means, more or less items are returned than the first TotalItems may have expressed - keeping the TotalItems close to the actual state of the system. Having said that, using the fromDate guarantees that you get all required items (i.e. completed registrations). That is, no registrations are omitted due to the changing environment. If you don’t get the registration for this round of API calls you will get them the next time.

...