Provision or select an LRS that conforms to the xAPI specification (1.0.3 is the current stable version); note the LRS's statements endpoint URL (typically https://lrs.example.com/xAPI/statements) and authentication credentials.
Construct a valid xAPI statement as a JSON object with at minimum an actor (with objectType, name, and mbox or account), a verb (with id URI and display map), and an object (with objectType and id); add result, context, and timestamp fields as required by your use case.
Send the statement to the LRS via HTTP POST to /xAPI/statements with Authorization: Basic base64(key:secret) (or Bearer token if the LRS supports OAuth), Content-Type: application/json, and X-Experience-API-Version: 1.0.3 header.
For single idempotent statement submission, use HTTP PUT to /xAPI/statements?statementId={uuid} with the same headers; the LRS returns 204 on success and 409 Conflict if a statement with that UUID already exists with different content.
Batch multiple statements by sending a JSON array in the POST body to /xAPI/statements; the LRS returns an array of the newly assigned statement IDs in the same order.
Query stored statements via GET /xAPI/statements with filter parameters such as agent, verb, activity, since, and until to verify ingestion and support analytics; the LRS returns a StatementResult envelope with statements array and more URL for pagination.
Known gotchas
The X-Experience-API-Version header is mandatory on every request; omitting it causes spec-compliant LRS implementations to return a 400 Bad Request, which may look like an authentication or connectivity error.
xAPI actor identity relies on a consistent identifier (mbox, mbox_sha1sum, openid, or account); inconsistent actor identifiers across statements from different systems prevent the LRS from aggregating a single learner's full activity record.
Statement voiding (declaring a previous statement invalid) uses a specific verb id of http://adlnet.gov/expapi/verbs/voided and a StatementRef object type — the original statement is not deleted but is excluded from most query results once voided.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp