Skip to content
xapi.ie

For developers

xAPI, the practical guide

Statements, verbs, the Learning Record Store API and how courses are launched, with examples you can run with curl. The Experience API (xAPI, also known as Tin Can) is an open standard; this page covers version 1.0.3, the one in everyday use.

By Learn Skills, makers of Learn Skills LRS · Updated

Statements

Everything in xAPI is a statement: an actor, a verb and an object, optionally with a result and context. A course sends statements to a Learning Record Store (LRS) over HTTPS as JSON.

{
  "actor": {
    "objectType": "Agent",
    "name": "Ann Murphy",
    "mbox": "mailto:ann@example.com"
  },
  "verb": {
    "id": "http://adlnet.gov/expapi/verbs/passed",
    "display": { "en-IE": "passed" }
  },
  "object": {
    "id": "https://example.com/courses/fire-safety",
    "definition": { "name": { "en-IE": "Fire Safety Basics" } }
  },
  "result": {
    "score": { "scaled": 0.85 },
    "success": true,
    "completion": true,
    "duration": "PT14M12S"
  },
  "context": {
    "registration": "6a1d8c2e-58b4-4f0b-9a63-2f1d9c0c4b7e"
  },
  "timestamp": "2026-10-13T09:30:00Z"
}
  • actor: who. Identified by exactly one of mbox (email), mbox_sha1sum, openid or account (a user name on a system, given as homePage + name). Can also be a Group.
  • verb: what happened, identified by an IRI. The display text is only for people.
  • object: usually an Activity (a course, module, slide, question), identified by an IRI. Question activities carry an interactionType (choice, fill-in, matching…) and the correct responses in their definition.
  • result: score (scaled from −1 to 1, or raw/min/max), success, completion, response and an ISO 8601 duration.
  • context: the registration UUID ties the statements of one attempt together; context activities give the parent course of a question, and more.
  • The LRS adds an id, stored time and authority. Statements are never changed; a mistake is undone with a voiding statement.

Common verbs

Any IRI can be a verb, but reports work best with the well-known ADL verbs, which authoring tools use:

VerbUsed for
launched / initializedthe course was opened, a session starts
experienceda slide, page or video was seen
answereda question was answered (with result.response and result.success)
completedthe learner finished the course or module
passed / failedthe course or test was passed or failed, usually with a score
suspended / resumedthe learner left and came back later
terminatedthe session ended
voideda statement is withdrawn (object: a StatementRef)

All under http://adlnet.gov/expapi/verbs/.

The LRS API

An LRS is a small REST API under one base address, the endpoint. Every request needs HTTP Basic authentication (a key and secret from the LRS) and the header X-Experience-API-Version: 1.0.3.

ResourceMethodsWhat for
statementsPOST, PUT, GETstore statements (one or a list); fetch one by id or query them
activities/statePUT, POST, GET, DELETEa course’s saved data per learner and registration: where to resume, bookmarks
activities/profilePUT, POST, GET, DELETEdocuments about an activity
agents/profilePUT, POST, GET, DELETEdocuments about a learner
activitiesGETthe full definition of an activity, as the LRS knows it
agentsGETa Person object with all known identifiers of an agent
aboutGETthe versions the LRS supports (no authentication)

Send a statement:

curl https://lrs.ie/xapi/statements \
  -u "$KEY:$SECRET" \
  -H "X-Experience-API-Version: 1.0.3" \
  -H "Content-Type: application/json" \
  -d '{"actor":{"mbox":"mailto:ann@example.com"},
       "verb":{"id":"http://adlnet.gov/expapi/verbs/completed"},
       "object":{"id":"https://example.com/courses/fire-safety"}}'

The LRS answers with the new statement id in a JSON list. Posting to the same id twice with different content is refused (409).

Querying

GET statements filters by query parameters and returns newest first:

curl -G https://lrs.ie/xapi/statements \
  -u "$KEY:$SECRET" -H "X-Experience-API-Version: 1.0.3" \
  --data-urlencode 'agent={"mbox":"mailto:ann@example.com"}' \
  --data-urlencode 'verb=http://adlnet.gov/expapi/verbs/passed' \
  --data-urlencode 'since=2026-10-01T00:00:00Z' \
  --data-urlencode 'limit=50'
  • agent, verb, activity, registration: exact matches; related_activities / related_agents widen them to context and sub-statements.
  • since, until (stored time), ascending, limit.
  • format: exact, ids or canonical (one language).
  • Results come in pages: follow the more URL until it is empty.
  • There is no free-text search or aggregation in the standard. Reports are built by reading statements into your own tables.

Launching a course

A published xAPI course needs to be told where its LRS is and who the learner is. Storyline, Rise, Captivate and iSpring read the convention Rustici Software introduced with Tin Can: query parameters on the course’s start page.

index_lms.html?endpoint=https%3A%2F%2Flrs.example%2Fxapi%2F
  &auth=Basic%20a2V5OnNlY3JldA%3D%3D
  &actor=%7B%22name%22%3A%22Ann%22%2C%22mbox%22%3A%22mailto%3Aann%40example.com%22%7D
  &registration=6a1d8c2e-58b4-4f0b-9a63-2f1d9c0c4b7e
  &activity_id=https%3A%2F%2Fexample.com%2Fcourses%2Ffire-safety

The credential is visible to the learner’s browser, so it should never be the LRS’s main key: issue a short-lived one that can only write that learner’s statements. Keep the registration the same on every launch, so the course can resume from its saved state.

No course yet, or no time to build one?

The Learn Skills team builds courses from your content, ready to upload here, and can supply ready-made ones.

Get help building a course Ready-made courses

cmi5 and versions

  • xAPI 1.0.3 (2016) is what authoring tools and LRSs use today. ADL publishes a conformance test suite for it.
  • IEEE 9274.1.1-2023, often called xAPI 2.0, is the version published as an IEEE standard. It is largely compatible; adoption is gradual.
  • cmi5 is a profile of xAPI for courses launched by an LMS: a standard launch handshake (no secrets in the URL), a fixed set of verbs and “moveOn” rules for when a course counts as done.

Questions

What is the difference between xAPI and Tin Can?

None: they are the same standard. Tin Can was the project name while Rustici Software developed it for ADL; version 1.0 was published in 2013 as the Experience API, xAPI for short.

What is an LRS endpoint?

The base address of a Learning Record Store’s REST API, such as https://lrs.ie/xapi/. The resources (statements, activities/state and the others) are paths under it. A course or system needs the endpoint plus a key and secret for HTTP Basic authentication.

Which header does every xAPI request need?

X-Experience-API-Version, set to the version the client speaks (1.0.3 today). An LRS refuses requests without it, except GET about.

How do I get statements out of an LRS?

GET the statements resource with filters such as agent, verb, activity, since and limit, and follow the “more” URL in each response until it is empty. The standard has no aggregation; reports are built from the statements you read.

Is cmi5 the same as xAPI?

cmi5 is built on xAPI: a profile that fixes how an LMS launches a course, which verbs it sends and when the course counts as complete. Every cmi5 statement is an xAPI statement.

Is xAPI 2.0 different from 1.0.3?

xAPI 2.0 is the version published as IEEE 9274.1.1-2023. It is largely compatible with 1.0.3, which is what authoring tools and LRSs use today.

Get an endpoint

Learn Skills LRS is a hosted xAPI 1.0.3 LRS, kept in Ireland. It passes all 1,365 tests of the ADL conformance suite, hosts and launches courses for you, and turns statements into reports. The free plan includes an endpoint and keys.

See Learn Skills LRS