Statements
/xapi/statementsThe Statements resource is the core of the xAPI spec. All learning events are stored here as immutable records. Statements can be submitted one at a time or in batches, and queried by any combination of actor, verb, activity, and time range.
POST Submit Statement(s)
Submit one statement (object) or multiple statements (array). Returns an array of assigned or confirmed statement IDs. Statements whose id is already stored are skipped and their ID still appears in the response — resubmitting a batch never conflicts, so retry loops are guaranteed to drain. Max 250 statements per request; 120 requests per minute per credential.
POST /xapi/statements
Authorization: Basic <base64(key:secret)>
Content-Type: application/json
X-Experience-API-Version: 1.0.3
// Single:
{
"actor": { "objectType": "Agent", "mbox": "mailto:student@school.edu" },
"verb": { "id": "http://adlnet.gov/expapi/verbs/completed", "display": { "en-US": "completed" } },
"object": { "objectType": "Activity", "id": "https://your-game.com/level-1" }
}
// Batch (array):
[{ ... }, { ... }]// 200 OK — statement(s) accepted
["550e8400-e29b-41d4-a716-446655440000"]
// 400 Bad Request — body: { "message": "actor is required" }
// 401 Unauthorized
// 413 Payload Too Large — more than 250 statements in one request
// 429 Too Many Requests — rate limit (120 requests/min per credential)GET Query Statements
Retrieve statements matching the given filters. Returns a StatementResult object with a more URL for pagination.
| Parameter | Type | Description |
|---|---|---|
| statementId | UUID | Fetch a single statement by ID. Cannot be combined with other filters. |
| agent | JSON | Filter by actor. E.g. {"mbox":"mailto:x@y.com","objectType":"Agent"} |
| activity | IRI | Filter by object activity ID. |
| verb | IRI | Filter by verb ID. |
| since | ISO 8601 | Stored timestamp after this datetime (exclusive). |
| until | ISO 8601 | Stored timestamp before or at this datetime (inclusive). |
| limit | integer | Max statements to return. Default 50, max 500. |
| ascending | boolean | true = oldest first. Default false (newest first). |
GET /xapi/statements?agent={"mbox":"mailto:student@school.edu","objectType":"Agent"}&activity=https://your-game.com&limit=20
Authorization: Basic <base64(key:secret)>
X-Experience-API-Version: 1.0.3
// 200 OK:
{
"statements": [ ...xAPI statement objects... ],
"more": "/xapi/statements?agent=...&offset=20&limit=20"
}PUT Submit Statement by ID
Submit a single statement with a specific UUID. The ID is taken from the query string, not the body. Idempotent — if the ID is already stored, the request returns 204 and the stored statement is left unchanged.
PUT /xapi/statements?statementId=550e8400-e29b-41d4-a716-446655440000
Authorization: Basic <base64(key:secret)>
Content-Type: application/json
X-Experience-API-Version: 1.0.3
{
"actor": { "objectType": "Agent", "mbox": "mailto:student@school.edu" },
"verb": { "id": "http://adlnet.gov/expapi/verbs/passed", "display": { "en-US": "passed" } },
"object": { "objectType": "Activity", "id": "https://your-game.com/quiz-1" },
"result": { "score": { "raw": 90, "min": 0, "max": 100, "scaled": 0.9 }, "success": true }
}
// 204 No Content — accepted (or ID already stored; existing statement unchanged)
// 429 Too Many Requests — rate limit (120 requests/min per credential)Statement Object Reference
| Field | Required | Description |
|---|---|---|
| id | No | UUID. Assigned by LRS if omitted. Include for idempotency. |
| actor | Yes | Agent or Group who performed the action. |
| verb | Yes | IRI + display name of the action performed. |
| object | Yes | Activity, Agent, StatementRef, or SubStatement. |
| result | No | Score, success, completion, duration, response. |
| context | No | Registration UUID, instructor, team, parent activities, extensions. |
| timestamp | No | ISO 8601 datetime the experience occurred. LRS records stored time separately. |
| authority | No | Set by LRS to the credential used. Not accepted from clients. |