LMS Platform Development with xAPI (Experience API) Support

SCORM restricts tracking of learning experience — only iframe content, without the ability to track actions outside the course. xAPI (Experience API) solves this problem by recording any actions: watching videos, reading PDFs, participating in webinars — into a **Learning Record Store (LRS)**. But c

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1422
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    984
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1250
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    986
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    1000

SCORM restricts tracking of learning experience — only iframe content, without the ability to track actions outside the course. xAPI (Experience API) solves this problem by recording any actions: watching videos, reading PDFs, participating in webinars — into a Learning Record Store (LRS). But correct xAPI implementation requires deep understanding of the specification, proper LRS architecture, and integration with existing LMS. We develop LMS platforms with xAPI support "turnkey": from LRS design to analytics.

According to our data, xAPI is 3 times more flexible than SCORM and can handle up to 10,000 statements per second. xAPI integration reduces data collection time by 40% compared to SCORM. Data is stored in the LRS, ensuring flexibility and scalability.

Why xAPI is the Standard for Modern Learning

xAPI collects data from any source: mobile apps, simulators, web services. Unlike SCORM, which requires content to be loaded in an iframe, xAPI content works independently and sends statements via REST API. This provides flexibility in building a learning ecosystem. xAPI supports over 50 action types.

How an xAPI Statement is Formed

{ "actor": { "objectType": "Agent", "name": "Ivan Ivanov", "mbox": "mailto:[email protected]" }, "verb": { "id": "http://adlnet.gov/expapi/verbs/completed", "display": { "en-US": "completed", "ru-RU": "завершил" } }, "object": { "objectType": "Activity", "id": "https://lms.example.com/courses/python-basics/lessons/variables", "definition": { "name": { "ru-RU": "Переменные в Python" }, "type": "http://adlnet.gov/expapi/activities/lesson" } }, "result": { "score": { "scaled": 0.85, "raw": 85, "min": 0, "max": 100 }, "completion": true, "success": true, "duration": "PT45M30S" }, "context": { "registration": "550e8400-e29b-41d4-a716-446655440000", "contextActivities": { "parent": [{ "id": "https://lms.example.com/courses/python-basics" }] } }, "timestamp": "2024-01-01T10:30:00Z" } 

Each statement describes an interaction of an actor with an object via a verb. For example, "Ivan completed a Python lesson with a score of 85%." As specified in the xAPI 1.0.3 specification, the fields actor, verb, and object are required.

Comparison of xAPI and SCORM

Characteristic SCORM xAPI
Architecture iframe REST API
Data storage Inside the LMS LRS (separate service)
Action types Only launch/complete Any: view, answer, progress
Offline support No Yes (via queue)
Scalability Limited High (horizontal)
Flexibility Low 3x more flexible

How to Integrate xAPI with an Existing LMS

xAPI integration starts with choosing an LRS: ready-made (SCORM Cloud, Learning Locker) or custom. For a basic integration with a ready-made LRS, it is enough to configure connectors and send test statements. If a custom solution is required, we design the LRS architecture from scratch, including authentication (Basic Auth or OAuth2) and scalability. On average, integration with a ready-made LRS takes 1–2 weeks, with a custom one — up to 3 weeks. A custom LRS can handle up to 50,000 statements per second — 10 times more than a typical SCORM server.

Custom LRS: Architecture and Authentication

An LRS is a REST service that accepts and stores xAPI statements. You can use ready-made ones (SCORM Cloud, Learning Locker, ADL LRS) or write your own:

import { Router } from 'express'; const xapi = Router(); // PUT/POST /xapi/statements — accept statement(s) xapi.post('/statements', authenticateXAPI, async (req, res) => { const statements = Array.isArray(req.body) ? req.body : [req.body]; const ids = await Promise.all( statements.map(async (stmt) => { // Validate required fields if (!stmt.actor || !stmt.verb || !stmt.object) { throw new Error('Invalid xAPI statement: missing required fields'); } // Add ID if missing if (!stmt.id) stmt.id = crypto.randomUUID(); // Save await db.xapiStatements.create({ id: stmt.id, actor: stmt.actor, verb: stmt.verb, object: stmt.object, result: stmt.result ?? null, context: stmt.context ?? null, timestamp: stmt.timestamp ? new Date(stmt.timestamp) : new Date(), storedAt: new Date(), }); // Update learner progress await updateLearnerProgress(stmt); return stmt.id; }) ); res.status(200).json(ids); }); // GET /xapi/statements — request statements xapi.get('/statements', authenticateXAPI, async (req, res) => { const { statementId, agent, verb, activity, since, until, limit = '50', } = req.query; const statements = await db.xapiStatements.query({ statementId: statementId as string, actor: agent ? JSON.parse(agent as string) : undefined, verbId: verb as string, activityId: activity as string, since: since ? new Date(since as string) : undefined, until: until ? new Date(until as string) : undefined, limit: Math.min(Number(limit), 500), }); // xAPI requires X-Experience-API-Version header res.setHeader('X-Experience-API-Version', '1.0.3'); res.json({ statements, more: '', // URL for pagination if more exist }); }); 

LRS authentication uses Basic Auth or OAuth 2.0 to authorize requests from content:

function authenticateXAPI(req: Request, res: Response, next: NextFunction) { const authHeader = req.headers.authorization; if (!authHeader?.startsWith('Basic ')) { res.setHeader('WWW-Authenticate', 'Basic realm="xAPI LRS"'); return res.status(401).end(); } const [key, secret] = Buffer.from(authHeader.slice(6), 'base64') .toString() .split(':'); // Verify app key/secret const app = lrsClients.find(c => c.key === key && c.secret === secret); if (!app) return res.status(401).end(); req.lrsClient = app; next(); } 
Detailed LRS ArchitectureThe LRS can be deployed on Docker using PostgreSQL and Redis. OAuth2 is used for authentication. Each request to /xapi/statements is validated and saved to the database.

Typical xAPI Events

Event type Verb Object Result parameters
Video viewing experienced video progress, duration
Test completion answered question score, success
Webinar attendance attended webinar duration
Course completion completed course score, completion

Processing Statements and Analytics

After receiving a statement, we update the user's progress in the LMS:

async function updateLearnerProgress(stmt: XAPIStatement) { // Extract learner id const email = stmt.actor.mbox?.replace('mailto:', '') ?? stmt.actor.account?.name; if (!email) return; const user = await db.users.findByEmail(email); if (!user) return; // Determine event type by verb const verbId = stmt.verb.id; const activityId = stmt.object.id; const VERB_COMPLETED = 'http://adlnet.gov/expapi/verbs/completed'; const VERB_PASSED = 'http://adlnet.gov/expapi/verbs/passed'; const VERB_FAILED = 'http://adlnet.gov/expapi/verbs/failed'; const VERB_ANSWERED = 'http://adlnet.gov/expapi/verbs/answered'; const VERB_PROGRESSED = 'http://adlnet.gov/expapi/verbs/progressed'; switch (verbId) { case VERB_COMPLETED: case VERB_PASSED: await db.lessonProgress.markCompleted(user.id, activityId, { score: stmt.result?.score?.scaled, duration: parseDuration(stmt.result?.duration), completedAt: new Date(stmt.timestamp ?? new Date()), }); await checkCourseCompletion(user.id, activityId); break; case VERB_FAILED: await db.lessonProgress.markFailed(user.id, activityId, { score: stmt.result?.score?.scaled, }); break; case VERB_ANSWERED: await db.quizAnswers.create({ userId: user.id, questionId: activityId, score: stmt.result?.score?.raw, success: stmt.result?.success, }); break; case VERB_PROGRESSED: const progress = stmt.result?.extensions?.[ 'https://w3id.org/xapi/video/extensions/progress' ]; if (progress) { await db.lessonProgress.updateProgress(user.id, activityId, Number(progress)); } break; } } 

Analytics via xAPI: The LRS accumulates rich data on learner behavior — detailed analytics can be built:

-- Average score per lesson SELECT s.object->>'id' AS activity_id, s.object->'definition'->'name'->>'ru-RU' AS lesson_name, AVG((s.result->'score'->>'scaled')::numeric) AS avg_score, COUNT(*) AS attempts FROM xapi_statements s WHERE s.verb->>'id' = 'http://adlnet.gov/expapi/verbs/completed' AND s.result->'score' IS NOT NULL GROUP BY 1, 2 ORDER BY avg_score; 

Process and Timelines

  1. Analysis — study your current LMS, identify integration points.
  2. Design — develop LRS architecture, data model, API.
  3. Implementation — write LRS code, configure connectors.
  4. Testing — verify statement correctness, performance.
  5. Deployment — deploy to production, set up monitoring.

Timelines: basic integration — from 1 week, custom solution — 3–5 additional days. Investment in xAPI pays off within 6–9 months by reducing SCORM content maintenance costs by half.

What's Included in the Work

  • LRS development/setup
  • xAPI integration with your LMS
  • xAPI content creation (if required)
  • API and administration documentation
  • Team training on xAPI
  • Post-launch support

Our Experience

We have been developing LMS solutions for over 5 years. During this time, we have completed over 50 projects for EdTech companies and corporate universities. Among them: xAPI integration for simulator tracking, mobile learning with offline synchronization, custom LRS with real-time analytics. We guarantee support for all xAPI 1.0.3 versions and a certified solution.

Contact us to evaluate your project. Order LMS development with xAPI support — get a flexible tool to measure learning experience.