Launch Your First SCORM Session
Launch Your First SCORM Session
Learn how to create learning sessions, launch SCORM players, and track learner progress.
Table of Contents
- Overview
- Prerequisites
- Creating a Session
- Launching the Player
- Tracking Progress
- Updating Session Data
- Common Scenarios
- Troubleshooting
Overview
A SCORM session represents a learner's interaction with a SCORM package. Sessions track:
- CMI Data: Progress, scores, completion status
- Time Spent: Total learning time
- Attempts: Number of times the course was accessed
- State: Current learning state (incomplete, completed, passed, failed)
Prerequisites
- API key with
writescope - A successfully uploaded SCORM package
- A user ID (your system's learner identifier)
Creating a Session
Method 1: Launch Endpoint (Recommended)
The launch endpoint creates a session and returns a player URL in one call:
curl -X POST https://scorm-api.allurelms.com/api/v1/packages/pkg_abc123/launch \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user-123",
"session_id": "session-456"
}'
Response:
{
"player_url": "https://scorm-api.allurelms.com/player/session-456",
"session_id": "session-456",
"package_id": "pkg_abc123",
"user_id": "user-123",
"expires_at": "2025-01-15T22:30:00.000Z"
}
Method 2: External Session (For External Systems)
If you're integrating from an external system (like TrainingOS), use the external session endpoint:
curl -X POST https://scorm-api.allurelms.com/api/v1/sessions/external \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"token": "<external-jwt-token>",
"package_id": "pkg_abc123",
"launch_token_ttl_seconds": 600
}'
Response:
{
"session_id": "session-456",
"launch_url": "https://scorm-api.allurelms.com/player/session-456?token=...",
"launch_token": "eyJhbGciOiJIUzI1NiIs..."
}
Launching the Player
Option 1: Embed in iframe (Recommended)
<iframe
src="https://scorm-api.allurelms.com/player/session-456"
width="100%"
height="800px"
frameborder="0"
allow="fullscreen"
title="SCORM Player"
></iframe>
Option 2: Redirect to Player
window.location.href = 'https://scorm-api.allurelms.com/player/session-456';
Option 3: Open in New Window
window.open(
'https://scorm-api.allurelms.com/player/session-456',
'SCORM Player',
'width=1200,height=800'
);
Tracking Progress
Get Session Data
Retrieve current session state and CMI data:
curl -X GET https://scorm-api.allurelms.com/api/v1/sessions/session-456 \
-H "X-API-Key: your-api-key-here"
Response:
{
"id": "session-456",
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"user_id": "user-123",
"package_id": "pkg_abc123",
"cmi_data": {
"cmi.core.lesson_status": "incomplete",
"cmi.core.score.raw": "75",
"cmi.core.score.max": "100",
"cmi.core.session_time": "PT15M30S"
},
"completion_status": "incomplete",
"success_status": "unknown",
"score": {
"scaled": 0.75,
"raw": 75,
"max": 100,
"min": 0
},
"time_spent_seconds": 930,
"version": 3,
"created_at": "2025-01-15T10:00:00.000Z",
"updated_at": "2025-01-15T10:15:30.000Z"
}
Polling for Updates
Check session progress periodically:
async function pollSessionProgress(sessionId: string) {
const interval = setInterval(async () => {
const response = await fetch(`/api/v1/sessions/${sessionId}`, {
headers: { 'X-API-Key': apiKey }
});
const session = await response.json();
console.log(`Progress: ${session.completion_status}`);
console.log(`Score: ${session.score?.scaled || 0}`);
if (session.completion_status === 'completed') {
clearInterval(interval);
console.log('Course completed!');
}
}, 5000); // Poll every 5 seconds
}
Updating Session Data
Update CMI Data
The SCORM player automatically updates session data, but you can also update it programmatically:
curl -X PUT https://scorm-api.allurelms.com/api/v1/sessions/session-456 \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"version": 3,
"cmi_data": {
"cmi.core.lesson_status": "completed",
"cmi.core.score.raw": "85",
"cmi.core.score.max": "100",
"cmi.core.session_time": "PT20M45S"
},
"completion_status": "completed",
"success_status": "passed",
"score": {
"scaled": 0.85,
"raw": 85,
"max": 100,
"min": 0
},
"session_time": "PT20M45S"
}'
Important: Always include the version field for optimistic locking. If you get a 409 Conflict error, fetch the latest session data and retry.
Handling Version Conflicts
async function updateSessionWithRetry(
sessionId: string,
updates: any,
maxRetries = 3
) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
// 1. Get current session
const session = await fetch(`/api/v1/sessions/${sessionId}`, {
headers: { 'X-API-Key': apiKey }
}).then(r => r.json());
// 2. Merge updates
const payload = {
version: session.version,
cmi_data: {
...session.cmi_data,
...updates.cmi_data
},
...updates
};
// 3. Attempt update
const response = await fetch(`/api/v1/sessions/${sessionId}`, {
method: 'PUT',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (response.ok) {
return await response.json();
}
if (response.status === 409 && attempt < maxRetries - 1) {
console.log(`Version conflict, retrying... (${attempt + 1}/${maxRetries})`);
continue;
}
throw new Error(`Update failed: ${response.status}`);
}
}
Common Scenarios
Scenario 1: Launch and Track Completion
// 1. Launch session
const launchResponse = await fetch(`/api/v1/packages/${packageId}/launch`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: userId,
session_id: sessionId
})
});
const { player_url, session_id } = await launchResponse.json();
// 2. Embed player
const iframe = document.createElement('iframe');
iframe.src = player_url;
iframe.width = '100%';
iframe.height = '800px';
document.body.appendChild(iframe);
// 3. Poll for completion
const checkCompletion = setInterval(async () => {
const session = await fetch(`/api/v1/sessions/${session_id}`, {
headers: { 'X-API-Key': apiKey }
}).then(r => r.json());
if (session.completion_status === 'completed') {
clearInterval(checkCompletion);
showCompletionMessage(session);
}
}, 5000);
Scenario 2: Resume Previous Session
// 1. Find existing session
const sessionsResponse = await fetch(
`/api/v1/sessions?package_id=${packageId}&user_id=${userId}`,
{ headers: { 'X-API-Key': apiKey } }
);
const { sessions } = await sessionsResponse.json();
// 2. Find incomplete session
const incompleteSession = sessions.find(
s => s.completion_status === 'incomplete'
);
if (incompleteSession) {
// Resume existing session
const playerUrl = `https://scorm-api.allurelms.com/player/${incompleteSession.id}`;
window.location.href = playerUrl;
} else {
// Create new session
const launchResponse = await fetch(`/api/v1/packages/${packageId}/launch`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: userId,
session_id: crypto.randomUUID()
})
});
const { player_url } = await launchResponse.json();
window.location.href = player_url;
}
Scenario 3: Track Multiple Users
async function launchForMultipleUsers(packageId: string, userIds: string[]) {
const sessions = [];
for (const userId of userIds) {
const response = await fetch(`/api/v1/packages/${packageId}/launch`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: userId,
session_id: crypto.randomUUID()
})
});
if (response.ok) {
const session = await response.json();
sessions.push(session);
}
}
return sessions;
}
Troubleshooting
Error: "Session Not Found"
Causes:
- Invalid session ID
- Session expired
- Session belongs to different tenant
Solutions:
- Verify session ID is correct
- Check session expiration time
- Ensure API key matches tenant
Error: "Version Conflict" (409)
Causes:
- Concurrent updates to same session
- Using outdated version number
Solutions:
- Fetch latest session data
- Merge your changes with latest data
- Retry with updated version number
- See Handling Version Conflicts
Error: "Package Not Found"
Causes:
- Invalid package ID
- Package deleted
- Package belongs to different tenant
Solutions:
- Verify package ID
- Check package exists
- Ensure API key matches tenant
Player Not Loading
Causes:
- CORS issues
- Invalid session token
- Network connectivity
Solutions:
- Check browser console for errors
- Verify CORS configuration
- Check network connectivity
- Ensure session hasn't expired
Best Practices
- Use Unique Session IDs: Generate UUIDs for session IDs to avoid conflicts
- Handle Version Conflicts: Always implement retry logic for session updates
- Poll for Progress: Check session status periodically for real-time updates
- Resume Sessions: Check for existing incomplete sessions before creating new ones
- Monitor Expiration: Track session expiration times and refresh if needed
- Error Handling: Implement comprehensive error handling for all API calls
Next Steps
- Generate Your First Report - View learner progress and analytics
- CMI Data Guide - Understand SCORM CMI data structure
- Session Management - Complete session API reference (API Reference coming soon)
- Webhook Setup - Get notified of session events
Last Updated: 2025-01-15
Related Documentation: