Contact Us Get Email Updates
 
 

Thanks! Someone will be in touch with you shortly.

Rather just email us? Email us here.
Rather speak with someone in person?
Call any time with Tin Can questions:

866.497.2676

Building a Learning Record Store

 
Developing an LRS from scratch is not a trivial undertaking. The first step is to get an in-depth understanding of the complete Tin Can specification itself. Unlike an activity provider, which can just use the very basic parts of the specification, an LRS is responsible for implementing the entire specification along with other specifications that are required to be used alongside the Tin Can spec.

To build an LRS, you first have to decide if the LRS will be a component of an LMS or a standalone, enterprise LRS. If you decide to build your LRS as part of an LMS, there’s a guide that handles how Tin Can content should be imported, launched and how to deal with private access to content. That LMS/LRS guide lives alongside the Tin Can specification and is agreed upon by the community as the best practice for implementing an LRS in an LMS, you can find it here.

This is the bare minimum functionality you will need to implement, no matter which type of LRS you decide to build.
 

 

The APIs

The Tin Can API is really a collection of four RESTful APIs. In talking about Tin Can, many focus on statements and transferring them between LRSs, this is the job of the statement API. The Document APIs: State, Activity, and Agent don’t deal with statements, they allow for richer information to be stored (a string, an image, a Word document, a video, etc — the document APIs are about these other pieces of data that don’t belong in a statement.) To build an LRS, you have to implement all four APIs.

  Statement API
The statement API is the way to put statements into an LRS and to get statements from an LRS. You can get and put a single statement or multiple statements with this API. This is the API you would use to pull down statements from an LRS to fuel reporting and visualizations.

Statements range in size. Today we often see fairly small statements, but there is potential for very large statements. Adding attachments in 1.0 increases the likelihood of seeing larger statements regularly. An LRS needs to determine how large is too large for a statement, this needs to be carefully decided so it doesn’t limit common use cases for the users. The LRS needs to effectively balance storing and working with large statements while efficiently handling smaller statements.

 
 
  State API
The state API is generally used by activity providers as a scratch space to support learning activities while they’re in progress. Saving state in this way allows resumption of an activity across sessions and across devices.

Example:
An example for using this API could be a person editing an image as part of a learning activity, that image could be saved (as an image) in the LRS with the state API. The different states of the image could be pulled back by the application at the end to put together a collection that shows the changes in the work over time.

 
 
  Activity Profile API
The Activity API stores data about activities in the LRS. There should be a full description of each activity in the LRS that can be referenced through this API. The LRS bears the responsibility for determining the best definition for each unique activity it has received. Part of the LRS’s responsibility for determining an activity’s definition is to attempt to access the activity’s metadata – care should be taken to avoid blocking requests when doing this. It’s likely activities will be duplicated in an LRS for various reasons (different IDs for the same activities, etc). The LRS needs to identify duplicates and treat them all as the same activity.

Example:
For team simulations, an activity could store it’s state under it’s own profile instead of with the State API. The state API is specific to Agent, the Activity API is not agent specific. Screenshots or pictures of real life training could be stored with this API. It’s a way to store documents that represent people showing their work with the activity.

Another example, in our Tetris prototype you will see a call to store high scores across the users in the LRS as a document for the activity with the Activity API. This populates a leaderboard much more quickly than by deriving high scores across all of the statements for the Tetris activity each time the user requests to see the leaderboard.

 
 
  Agent Profile API
The Agent API is similar to the State and Activity APIs, but it’s focused on adding additional data about agents to the LRS. The Agent API is a way to connect the different ways a person has been identified across an LRS by adding the different IDs and credentials to the Agent.

Example:
An avatar that represents the person could be added to their profile in the LRS through the Agent API. An avatar image is not something that would be sent with a statement. When other permissed systems queried the LRS for the profile, they could pull in this image file to populate for the person in their system.

 
 
 
 

Security and Authentication: Permissions and OAuth

An LRS has to support authentication, and the most common two authentication mechanisms are HTTP basic authentication and oAuth. If an LRS is going to support oAuth, then it has to implement the various requirements listed below. oAuth is a commonly used specification for authentication on the web. This image is an example of a music site and Facebook connecting with oAuth. In most of the Tin Can API world, the consumer would be an application and the provider would be the LRS. LRSs can also connect to each other. Once connected they can use the Statement API to share statements.

There are five scenarios:

In the authorization process, the Tin Can API spec has specific ways that tokens, authorizations, and temporary credentials need to work with endpoints.

If an oAuth connection is made, the scope of the data that can be shared through the statement API is defined. An LRS has to follow oAuth 2.0’s scope parameter, which is here. The scope allows the statement API to work with the data in the LRS on the users behalf.

The LRS is responsible for populating (or validating) the authority portion of the statement, based on the credentials used to send the statement. There are specific requirements for constructing an authority based on each type of authentication.
 

 

Statement Transfer: Retrieval

Retrieving a collection of statements from an LRS and storing them locally to support reports or visualizations is the best way to work with the data. Constantly querying the LRS is less effective because it’s a big load. Pulling down the data also allows you to do more in-depth queries of the data because the statement API doesn’t query on all statement parameters (extensions, for example, can not be queried with the statement API).

An LRS will need to carefully index data because efficiently serving the queries can be complex. One challenge is efficiently handling relationships between statements. An example of this would be if a search for certain conditions that match statement C must return statement A. Then if A targets B which targets C, all three must be returned, as described in filter conditions for statement refs. Statement references are ways to point to another statement as important to the referencing statement.

When a query for statements is made to the LRS, it returns a number of statement results and generates a URL, which has to remain active for 24 hours to allow for more statements to be pulled down. There are also guidelines about the length of URLs and storage of query data, that’s all in the spec too.
 

 

Data Quality

  Voided statement handling
The LRS has specific responsibilities when it comes to voided statements. This is because Tin Can statements are immutable. They cannot be deleted. A false or inaccurate statement can only be voided. The burden is on the LRS to make sure that the original flawed statement is dealt with appropriately so it doesn’t mire reports and other ways that the data may be used.

The LRS needs to store all ‘voiding’ statements, and when returning statement results the LRS must filter out any statements which have been voided. The LRS should check to see if that statement made any changes to the activity or agent definitions and roll the changes that the statement made back. Read more about handling voided statements here.

 
 
  Statement Data Constraints and Validation
The LRS checks for syntax. It has to validate all of the pieces of a statement to make sure that data is formatted properly, required fields are present, and that the JSON values match the requirements of the spec. The semantics of a statement and meaning of the data within the statement is the responsibility of the activity provider.

Read more about Statement Data Constraints and Validation.

 
 
  Data Concurrency Controls
Considering the volume of data that is flowing in and out of an LRS, concurrency is a major concern. The specification has many rules and checks that an LRS must do to make sure that the data in the LRS is not being degraded by putting old data into the LRS.

Read more about Data Concurrency Controls.

 
 
  Signed Statement Validation
Signed statements have a special case in the LRS. They can be validated by the authority signing the statement without trusting the system that the statement originated in. In order for an LRS to validate signed statements, the LRS must check specific algorithms and properties in the JSON Web Signature (JWS) format. The implementor of the LRS needs to understand specification for JWS as well as the specific rules outlined in the Tin Can specification.

Learn more about Signed Statement Validation here.

 
 
  HTTP Head
An LRS returns only meta information only to HTTP headers, not the full documents in the LRS. A request can be made to find out if there is a newer version of a document without downloading the full document. This is a less load intensive way of checking to see if documents need to be downloaded from the LRS to support an application or report.

Learn more about HTTP Head here.

 
 
 
 

Future Proofing: API versioning and resource requests

Version headers are required in every response from an LRS to make it clear what versions of the Tin Can specification the LRS supports. The version headers use semantic versioning. An LRS needs to provide an ‘about’ resource that returns JSON that identifies the versions of the specification that the LRS supports.
 

 

Handling the Past

There are three versions of the Tin Can API specification that are in use by different activity providers currently. The specification doesn’t require that an LRS support all of the versions, but it should. Supporting limited versions is a headache for the LRS administrators and users. An LRS needs to be able to receive and store statements that are 0.9, 0.95, and 1.0.0. The LRS also needs to up-convert older versions to the most recent version of the specification so that they are able to be understood by all clients. This means that the older statements must be preserved in their original state and an updated version should be stored according to this appendix to the spec, appendix F.
 

 

Credential Management

An LRS is not required by the specification to do user management and permission management, but in order to be usable it should. This includes building ways for applications to register as OAuth consumers, managing user credentials, and managing basic authorization combos. Managing who can talk with the LRS is one part, the next step is to give controls for how much they can access which comes with a much more complicated set of decisions to be made about security and permissions.
 

 

Dealing with IE: Cross Origin Requests

The specification enables cross domain tracking, but the method for doing this does not allow HTTP headers to be set. This is a problem in using IE8 and IE9. There is a specific workaround for this in the specification that LRSs must support.
 

 

Beyond the basic, spec required LRS functionality:

Now, all of that said, if you want to build an LRS that is a standalone enterprise system it will need a lot more functionality. These are some of the things the LRS should do:

  • Permissions management
  • Push-pull statement synchronization with other lrs
  • Data extraction, viewing and analysis
  • Authentication management
  • Actor merging, supported by the Agent API
  • Activity de-duplification, supported by the Activity API

 

Tin Can API Email Updates

* indicates required

Tin Can API Email Updates

Thanks for signing up for the Tin Can API newsletter!

Make sure to follow us on Twitter @ProjectTinCan,
and tweet this page to let others know about the Tin Can API.

Close