Skip to content

xAPI data types

The parts of a statement, as plain serializable types. An xAPI statement is "actor verb object", with optional result and context — these are those pieces.

File What it is
XApiStatement The whole thing: actor, verb, object, result, context, id, timestamp
XApiActor Who did it — an agent, identified by mbox, account, or openid
XApiVerb What they did — an IRI plus a display name
XApiActivity What they did it to — an IRI plus name and description
XApiResult How it went — score, success, completion, response, duration
XApiContext Registration, and the activity hierarchy the statement sits in

Everything optional is nullable, and that is load-bearing

XApiResult.success and completion are bool?; every field on XApiScore is float?. Omitting one says nothing, rather than saying no.

This matters more in xAPI than in SCORM. A statement about answering a question carries a response and a success and usually no score at all, and a statement that reported score: 0, completion: false because those are the defaults for their types says something false about the learner.

XApiScore.Raw, and the rejection it avoids

Use XApiScore.Raw(raw, min, max) rather than setting the fields by hand. It derives scaled from the range and clamps it to -1..1, which the specification requires.

It also clamps raw into min..max, which the specification equally requires and which is the less obvious half: an LRS is obliged to reject the entire statement when raw sits outside the stated range. So Passed(105) against the default 0–100 range used to lose the pass completely — the statement was refused, and the queue then correctly discarded it as permanently rejected.

A clamped score is a reporting inaccuracy. A rejected statement is a lost pass. The clamp is the better trade, and it logs a warning naming the real value so the range can be fixed.