Back to TOC

User Manual

Veracity Learning Basics

Veracity Learning is an easy to use, cloud or self hosted Learning Record Store (LRS). The most essential feature of an LRS is that it receives and processes eXperience API (XAPI) data transactions. XAPI is a new standard for moving around performance data from informal learning, LMSs, courseware or mobile apps. It transcends many of the limitations of the older SCORM specification's Run Time Environment (RTE). It does not, however, replace SCORM completely.

Veracity Learning fully implements all 1,200 requirements of the xAPI specification, including digital signatures, binary attachments, access keys, concurrency control and document state storage. We also include some useful extensions to the xAPI like activity definition POST and advanced queries. Veracity Learning makes an effort to work in a wide variety of scenarios. We automatically correct many common xAPI mistakes, so you have maximum flexibility in what data you send.

This document covers the basics of getting set up with an account and creating your first LRS.

Table of Contents

Creating an Account

Veracity Learning is available as a SaaS solution at https://lrs.io. If you're looking for information on managing user accounts on your self hosted Enterprise install, please check the Enterprise version docs.

Anyone can sign up for a free account on lrs.io, and generate up to 3 LRSs for free! We do limit you to 100 MB of data storage, but for many purposes this should be enough. Generally, you should be able to store around 100,000 xAPI statements in each free LRS. To sign up for an account, browse to https://lrs.io/ and click the big "Create Account" button.


Here, you'll see a very simple form. Just fill in your email address and a password, and click "Create Account". We're not in the business of collecting your information, so this form requires the absolute minimum information necessary.


You'll receive an email with a link in it. This is necessary for us to confirm that your email address is valid. The email will looks something like this:

You're receiving this email because you signed up for an account on the Veracity Learning. You'll need to verify the account's email address before you can start using the system.

Here's the link to verify [Your user name]'s email:

Verify your account

If your email program cannot display links, you can also enter the code manually. Open the address below.


And when prompted, enter the code


From here, you can either click on "Verify your account", or copy the code provided and browse to https://lrs.io/ui/users/validateEmail/. Once you're email address is validated, just accept the terms of service, and you'll be logged in.

Creating LRSs

Users can create up to a certain number of separate LRSs depending on their account tier. Each LRS in our system is completely independent. They don't share keys, analytics, or even the same database. This allows you to completely separate different uses of the LRS. One common scenario is to use one LRS as a testing environment, and a different one to host your production data. A few of our customers have their own learning tools, and choose to manage a fleet of LRSs for their own clients. However you use them, it's important to understand that there is absolutely no data of any sort shared between your LRSs (or indeed anyone else's). They are completely separate systems.

We create a sample LRS for users when they first sign up. This does eat into your storage allocation, so feel free to delete the sample LRS if you need to. This sample LRS will be populated with sample data, so you can get a feel for how the system works.

When you log in, you'll see something like this:


This page gives you a quick overview if your existing LRSs. You can see what data is allocated, the traffic and errors rate over time, and the amount of storage used. If you haven't created all your allowed LRSs, you'll see a button near the top of the page.


If you're allowed to, click this button to begin setting up a new LRS. Once you click the button, you'll be presented with a form to fill out.


This form sets up the new LRS. You can change these options later, but with some drawbacks.

  • LRS Name - choose a name for the LRS. This name will become part of the URL for your xAPI endpoint. If you change it in the future, you might have to update the connection string in any learning record providers. You'll be notified if the name you choose is not available. These names must be globally unique on LRS.io, and unique to your domain if you have a self hosted version.
  • Strict API Mode - This controls how tightly your LRS requires the exact behavior from the xAPI spec. There are a lot of legacy content authoring tools out there that don't properly support the spec. We recommend leaving this unchecked in order to support the widest possible range of learning record providers.
  • Verbose Logs - Whether or not we keep detailed logs of the traffic to the LRS. Leave this on unless you're sure you won't need to troubleshoot any content. We allow you to disable this because the logs can eat into your storage allocation. You can also manually clear the logs and any time to free up space.

Once you click "Create", you'll see the management page for your new LRS!

xAPI Access Keys

xAPI requires you to use HTTP Basic Authentication when sending data or querying the LRS. Don't use your LRS.IO name and password - these credentials will not connect to an LRS. You'll need to allocate "Access Keys" to create a username/password pair to connect to the LRS. You can create multiple keys - don't feel like you must have just one. A common pattern is to create keys for each different learning record provider that might send data to your LRS. You can also allocate keys for each learner, or organization.... it's really up to you how you use them. Still, you must have at least one.


Click the big red button. Since you can't use the LRS without any keys, it's highlighted for you. On the following page, you'll see listed all existing keys (if you have any) and a green button like this:


Click this button to create a key. We'll suggest a username and password for you. You'll see a form like the one below. Again, you can change the setting for the key at any time, but read the bullets below!


  • Key Name - A name for the key. This is used to display it in the user interface, but also to set the Authority field of the xAPI statements sent with this key. Changing this value can change the name in the authority field, which might not be what you expect! Exercise care when changing this value.
  • Read xAPI Permission - This key can be used to read xAPI data. It can issue GET requests to the document endpoints, and query for xAPI statements.
  • Write xAPI Permission - This key can write xAPI statements, and send PUT and POST requests to the document endpoints. This permission is currently required to use the Aggregation query feature, since it issues a POST with the query body. We'll fix this in the future.
  • Limited Read - When querying the statement endpoint, only return values that were created by this key. Note that this cannot be enforced for the document endpoints, because they don't store Authority data. This value is also incompatible with "Advanced Queries" below.
  • Advanced Queries - Allow this key to be used on the advanced query extensions to the xAPI. Allows access to /statements/search and /aggregate.
  • JWT - Allow this key to sign JSON Web Tokens

Accessing the API with JWT

Using JWT-based access controls greatly simplifies the task of generating short lived credentials. Instead of using a REST API to tell the LRS to create a Basic Auth credential, then revoke it at the end of a session, you can send a payload in the Authentication header that describes what rules are enforced. Why can't the client fake this? Because it's digitally signed with a key that you got from the LRS. Since it's signed, we know the rules (like read, write, or timeout) are what you intended, and because the user sees only the token, not the secret, we know that they can't forge their own. Finally, since a JWT is stateless, we never have to store it in a database, and neither do you. You just generate one on demand, hand it to your client's browser, and forget about it. When it expires, we will reject it - all this without any API call or database logic. It's a fantastic way to authorize clients to your LRS.


When you set up a JWT key, that key cannot be used for regular HTTP Basic Authentication. Never share the password for this key! It can be used to generate access tokens to your server. Should you accidentally loose control of this value, you can disable or delete the key in the LRS, and no tokens signed by it will be valid. The above configuration is the only one that will allow JWT access - you must uncheck all 4 permissions.

You cannot modify an existing key to sign JWTs. This is a security precaution.


Veracity Learning includes a tool for you to use a key to generate a valid JWT, and to see the expected payload. Not that you do not need to use the Veracity Learning software to generate this token - we provide this functionality for testing purposes. We expect that your LMS or server side application can generate these tokens. In fact - that the primary benefit. Your application can issue limited access tokens against the LRS without interacting with it. Click Generate a JWT from the context menu to see the options.


The above form allows you to set some options. Most importantly, you can set a time after which the token will expire. You should also allocate some unique ID to the Token ID field. The choice of this value is important, but depends on your applications needs. When using the "Limited Read" permission, xAPI queries are only allowed to fetch information that was generated by the "authority" that issues the query. Because a token can expire, the token itself cannot be used to scope this query. Data posted with a given token ID will use that token ID as the authority, thus allowing you to issues additional JWTs that can read the same, limited pool of data, after one expired. For many use cases, you can leave this blank or full in a random string.

    "jti": "Some Unique Value",
    "exp": 1570579200000,
    "sub": "",
    "read": false,
    "write": true,
    "advancedQueries": false,
    "limitedRead": false,
    "aud": "local.veracity.it:3005",
    "iss": "TheTokenIdentifier"

The payload of the JWT is above. Note that the iss claim has the username of the credential that generated the token. Since sub is blank, this token can be used to post xAPI statements about any actor. If we had populated sub, then statements that are POSTed must contain that exact actor. You'll also see that the aud claim is the domain of the server on which this token should be used.

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJTb21lIFVuaXF1ZSBWYWx1ZSIsImV4cCI6MTU3MDU3OTIwMDAwMCwic3ViIjoiIiwicmVhZCI6ZmFsc2UsIndyaXRlIjp0cnVlLCJhZHZhbmNlZFF1ZXJpZXMiOmZhbHNlLCJsaW1pdGVkUmVhZCI6ZmFsc2UsImF1ZCI6ImxvY2FsLnZlcmFjaXR5Lml0OjMwMDUiLCJpc3MiOiJUaGVUb2tlbklkZW50aWZpZXIiLCJpYXQiOjE1Njk5NTI5Njd9.BAvB4rYGb_wLVV9g0lzgzCI_cjISRa4uhZHqXSuz29U

This data should be signed with the associated password/secret, and encoded using a standard JWT library. The resulting token should be send in the Authorization header using the Bearer method.

Viewing xAPI Data

Veracity Learning gives you lots of tools to review your xAPI data. At the most basic level, you can use our Statement Viewer to see your statements. We also have viewers for the document stores, binary attachments, and access logs. We also have a beautiful sets of graphs and charts you can access from the "Analytics" page. Most basic data view features are on the left side menu, under "xAPI Data". You can also find them from the "View Data" page under "All Management Tools"


Viewing xAPI Statements

Statements are the backbone of xAPI. Each one represents an experience, event, or learning activity that a learner takes on some content. Our statement viewer enables you explore the statements in the LRS by filtering, sorting, and searching on a variety of fields. The default configuration of the Statement Viewer looks like this.


Here, you can see a few dozen xAPI statements presented in an easy to read chart. We pull out the proper display name for Agents and Activities wherever possible. The grid can be configured with a few options. These options will persist when you refresh the page, or when you flip pages through the database of statements, but will be lost if you click on the link to load the viewer again.Click "Configure" to see the viewer options. You can toggle them on or off with the slider buttons. At the bottom, you can also change pages, jump to a specific page, or change the number of rows on each page.


Most of the toggles here allow you to show or hide additional columns. Each of these is a field from the xAPI statement data model. When you show these columns, you can sort or filter on them. There are a few toggles that control other aspects of the viewer.

  • Format Dates - present the timestamp and stored fields in an easy to read format. Disable this to see the raw timestamp.
  • Raw IDs - instead of picking a pretty display name out of the statement, display the Actor and Activity IDs directly.
  • Property Icons - These icons show you additional information about what sorts of data the statement contains
  • Full Text Search - This controls how the search boxes at the top of the viewer work. In full text mode, you can search within the field for words or phrases. When disabled, you search within the raw data for the field, rather than the pretty display values.

You can search for statements by placing a value in the column header search box. Note the relationship to "Full Text Search" above.


You can clear the search box by clicking the "X" icon on the left. Some columns can be used to sort the results. Click on the column header to sort. A border will appear at the top or bottom of the column title to indicate that the results are sorted in ascending or descending order on that field.


This shows us that the results are sorted by Stored date, with the newest first. Some search boxes present choices to you, for fields where the spec defines a vocabulary.

There are a variety of icons on the viewer. Here's a description of their function.

  • - This statement has a result value
  • - This statement has a context value
  • - This statement has extensions
  • - This statement has a platform value
  • - this statement has attachments
  • - Search for all statement where this column has this value
  • - graph this object or actor in the Analytics tool
  • - refresh this page, retrieving new statements that match the current filters
  • - refresh this page, retrieving new statements that match the current filters every few seconds
  • - export this chart as a CSV file. Note that this includes ALL pages, not just the current page

Viewing xAPI Document Stores

The xAPI has a few places where Learning Record Providers can store data to be associated with an Agent or Activity. Veracity Learning provides viewers for the Activity State, Activity Profile and Agent Profile data stores. Each works basically the same way.


Here, we can see an Activity State. In this case, the posted data is a JSON document. The LRS will attempt to render the data in a meaningful way whenever possible, but it may not be possible to preview all data. The top 4 fields show the "context" for this document, and are required to retrieve this data from the xAPI.


The attachment viewer will show you the binary data associated with xAPI statements. You can click the "Download" icon to export the attachment.

The Analytics Page

The LRS includes a large set of graphing and visualization tools to help you get actionable insights out of your raw data. You can access this page from the "Analytics" option on the left side menu. This section will describe how the tools work, but won't list every possible visualization. You can also read about customizing the dashboards here.


The dashboard system presents a set of widgets, each of which shows a chart, graph, table, or other rendering of some analysis over your data. These widgets are dynamically placed, so your view might not match these screenshots exactly. The system attempts to fit the available widgets into the space available, making them larger or smaller depending on the screen layout and the amount of data they need to display. Also, the content of each dashboard is dynamic. The system will attempt to hide charts that are meaningless for your data - for instance, a chart of the distribution of scores would be hidden if the data set for the dashboard did not include any xAPI statements that included score information.


The Analytics page also replaces the values on the left side menu. Instead, it shows you a list of available dashboards. The dashboards available to you depend on the "Scope" that the analytics package is attached to. Most users will deal only with the "LRS" scope, which shows information about all the data in the LRS. Other scopes include "Admin", which shows system status and logs information for the entire server installation, or the "Learner" scope, which restricts the data to only the logged in learner. Additional scopes are planned in the future.

Click "Back to LRS" to return to the LRS management page. The default dashboard in the LRS scope is LRS Overview dashboard, shown above.


Each dashboard has a set of options that scope what data is displayed. Expand the down arrow below the dashboard title to show the parameters.


All dashboards include a global time range filter. Click this teal box to choose a time range for the dashboard.


Each parameter type will present you with a search box. We strive to minimize the amount of URLs and IRIs you have to remember, and present intelligent autocomplete text wherever possible. The autocomplete text boxes display the human readable title of activities and agents. You can also paste in the exact activity ID or agent IFI if you know it.


Sometimes, you might find that the dashboard requires that you choose a value. In this case, the choices will be expanded automatically, and you'll see a warning that some value must be selected.


You can hover your mouse over pie slices, bars, and lines to show a tooltip with more information. When the pie slice or bar represents an Actor or Activity, you can click on it to focus the appropriate dashboard for that actor or activity. For instance, below is a section of the Learner dashboard for a certain Actor. In their pie chart showing what Activities the learner has recently used, we can click the pie chart slice to move to the Activity dashboard. The parameters for the Activity dashboard will be set to show the "Forward Button" Activity, since this is the slice we clicked.


When a graph shows a legend, you can remove results from the display by clicking on the legend box. The graph will automatically update to best illustrate the remaining data.


Graph results can be expensive to compute. Each value is cached for a predetermined amount of time. To ignore this cache and reload the graph, click the icon in the upper right of each widget.

Exporting Widget Data

Veracity Learning gives you a few tools to export the information from a widget. Many can simply be downloaded as a rendered image in JPG, PNG, or SVG formats. You can also export that raw data that went into the chart as JSON, CSV, or Excel.

Each of these features is accessed by moving the mouse over the "..." icon on the upper right.


You can also embed a live copy of a widget in a blog, forum or website. Click the icon in the upper right of widget. This will open a confirmation dialog.


Clicking on "Get Link" will create a unique link to this chart that you can paste into any system that accepts HTML. Heed the warning: this is intended to make the chart data public. Anyone with the link can view the chart.


Copy and paste the HTML fragment into your blog, website or forum.


You can also embed a full dashboard with a similar interface. Click the "Link" icon in the upper right of a given dashboard. The current parameter values will be recorded. Unless you check the "Allow Parameter Modification" box, the dashboard parameter will be set and unchangeable. Checking the box will allow the embedded dashboard to change the value, like selecting another Actor or changing the time range.