Upload Your First SCORM Package
Upload Your First SCORM Package
Learn how to upload, validate, and manage SCORM packages with the AllureLMS SCORM API.
Table of Contents
- Overview
- Prerequisites
- Package Requirements
- Upload Methods
- Understanding the Response
- Package Management
- Common Scenarios
- Troubleshooting
Overview
The SCORM API supports uploading SCORM 1.2 and SCORM 2004 packages. Once uploaded, packages are:
- Validated for SCORM compliance
- Extracted and stored securely
- Made available for launching sessions
- Tracked with version history
Prerequisites
- API key with
writescope - A valid SCORM 1.2 or SCORM 2004 package (ZIP file)
- Your tenant ID
Package Requirements
Supported Formats
- SCORM 1.2 - Full support
- SCORM 2004 (1st-4th Edition) - Full support
- ZIP Archive - Must be a valid ZIP file
Package Structure
Your SCORM package must contain:
- imsmanifest.xml - SCORM manifest file (required)
- Content Files - HTML, JavaScript, media files, etc.
- Valid Structure - Files organized according to SCORM specification
File Size Limits
- Default: 100MB per package
- Large Packages: Use multipart upload for packages >100MB
- Maximum: 10GB (with multipart upload)
Validation
The API automatically validates:
- Manifest structure and syntax
- SCORM version compatibility
- Required files presence
- Package integrity
Upload Methods
Method 1: Simple Upload (Recommended for <100MB)
Use this for most packages:
curl -X POST https://scorm-api.allurelms.com/api/v1/packages \
-H "X-API-Key: your-api-key-here" \
-F "file=@course.zip" \
-F "tenant_id=550e8400-e29b-41d4-a716-446655440000" \
-F "uploaded_by=user-123"
Form Fields:
file(required) - The SCORM package ZIP filetenant_id(required) - Your tenant UUIDuploaded_by(required) - User identifier (any string up to 255 chars)package_id(optional) - Existing package UUID to upload a new version
Method 2: Multipart Upload (For Large Packages >100MB)
For large packages, use the multipart upload flow:
Step 1: Initialize Upload
curl -X POST https://scorm-api.allurelms.com/api/v1/packages/multipart/init \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"uploaded_by": "user-123",
"filename": "large-course.zip"
}'
Response:
{
"upload_id": "upload_abc123",
"storage_path": "tenant/uploads/tmp_123.zip",
"part_size": 5242880,
"total_parts": 20
}
Step 2: Get Presigned URLs for Each Part
curl -X POST https://scorm-api.allurelms.com/api/v1/packages/multipart/part-url \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"upload_id": "upload_abc123",
"part_number": 1
}'
Response:
{
"part_number": 1,
"url": "https://storage.example.com/upload?presigned=...",
"expires_in": 3600
}
Step 3: Upload Each Part
curl -X PUT "https://storage.example.com/upload?presigned=..." \
-H "Content-Type: application/zip" \
--data-binary @part1.zip
Save the ETag from the response header.
Step 4: Complete Upload
curl -X POST https://scorm-api.allurelms.com/api/v1/packages/multipart/complete \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"upload_id": "upload_abc123",
"parts": [
{ "part_number": 1, "etag": "\"etag1\"" },
{ "part_number": 2, "etag": "\"etag2\"" }
]
}'
Step 5: Process Package
curl -X POST https://scorm-api.allurelms.com/api/v1/packages/process \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"uploaded_by": "user-123",
"storage_path": "tenant/uploads/tmp_123.zip",
"original_filename": "large-course.zip"
}'
Method 3: Validation Only
Test package validity without processing:
curl -X POST https://scorm-api.allurelms.com/api/v1/packages/process \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"uploaded_by": "user-123",
"storage_path": "tenant/uploads/tmp_123.zip",
"original_filename": "course.zip",
"validate_only": true
}'
Response:
{
"validation_only": true,
"manifest": {
"title": "Intro Course",
"version": "1.2",
"launch_url": "index.html",
"sco_count": 5
},
"file_size_bytes": 1421132,
"storage_path": "tenant/uploads/tmp_123.zip"
}
Understanding the Response
Successful Upload Response
{
"id": "pkg_abc123",
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"title": "Introduction to Safety Training",
"version": "1.2",
"scorm_version": "1.2",
"launch_url": "index.html",
"manifest_url": "imsmanifest.xml",
"storage_path": "tenant-550e8400/packages/pkg_abc123",
"file_size_bytes": 5242880,
"metadata": {
"identifier": "com.example.course.001",
"schema": "ADL SCORM",
"schemaversion": "1.2",
"description": "Course description",
"sco_count": 5
},
"created_at": "2025-01-15T10:30:00.000Z",
"updated_at": "2025-01-15T10:30:00.000Z"
}
Key Fields Explained
- id: Unique package identifier (use for launching sessions)
- title: Extracted from manifest
- version: SCORM version (1.2 or 2004)
- launch_url: Entry point for the course
- storage_path: Internal storage location
- metadata: Additional package information
Package Management
List All Packages
curl -X GET "https://scorm-api.allurelms.com/api/v1/packages?tenant_id=550e8400-e29b-41d4-a716-446655440000" \
-H "X-API-Key: your-api-key-here"
Get Package Details
curl -X GET https://scorm-api.allurelms.com/api/v1/packages/pkg_abc123 \
-H "X-API-Key: your-api-key-here"
Update Package Metadata
curl -X PATCH https://scorm-api.allurelms.com/api/v1/packages/pkg_abc123 \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "550e8400-e29b-41d4-a716-446655440000",
"description": "Updated course description",
"duration": "45m",
"tags": ["onboarding", "2025"],
"custom_metadata": { "level": "advanced" }
}'
Upload New Version
To update a package while keeping the same ID:
curl -X POST https://scorm-api.allurelms.com/api/v1/packages \
-H "X-API-Key: your-api-key-here" \
-F "file=@updated-course.zip" \
-F "tenant_id=550e8400-e29b-41d4-a716-446655440000" \
-F "uploaded_by=user-123" \
-F "package_id=pkg_abc123"
The launch URL stays stable, but current_revision increments.
Get Version History
curl -X GET "https://scorm-api.allurelms.com/api/v1/packages/pkg_abc123/versions?tenant_id=550e8400-e29b-41d4-a716-446655440000" \
-H "X-API-Key: your-api-key-here"
Common Scenarios
Scenario 1: Upload and Launch Immediately
// 1. Upload package
const uploadResponse = await fetch('/api/v1/packages', {
method: 'POST',
headers: { 'X-API-Key': apiKey },
body: formData
});
const package = await uploadResponse.json();
// 2. Launch session
const launchResponse = await fetch(`/api/v1/packages/${package.id}/launch`, {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
user_id: 'user-123',
session_id: crypto.randomUUID()
})
});
const { player_url } = await launchResponse.json();
// 3. Embed in iframe
document.getElementById('player').src = player_url;
Scenario 2: Batch Upload Multiple Packages
const packages = ['course1.zip', 'course2.zip', 'course3.zip'];
for (const packageFile of packages) {
const formData = new FormData();
formData.append('file', packageFile);
formData.append('tenant_id', tenantId);
formData.append('uploaded_by', userId);
const response = await fetch('/api/v1/packages', {
method: 'POST',
headers: { 'X-API-Key': apiKey },
body: formData
});
if (response.ok) {
const pkg = await response.json();
console.log(`Uploaded: ${pkg.title} (${pkg.id})`);
}
}
Scenario 3: Validate Before Uploading
// 1. Upload to temporary storage first
const tempUpload = await uploadToTempStorage(file);
// 2. Validate without processing
const validateResponse = await fetch('/api/v1/packages/process', {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tenant_id: tenantId,
uploaded_by: userId,
storage_path: tempUpload.storage_path,
original_filename: file.name,
validate_only: true
})
});
const validation = await validateResponse.json();
// 3. If valid, process for real
if (validation.manifest) {
await fetch('/api/v1/packages/process', {
method: 'POST',
headers: {
'X-API-Key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({
tenant_id: tenantId,
uploaded_by: userId,
storage_path: tempUpload.storage_path,
original_filename: file.name,
validate_only: false
})
});
}
Troubleshooting
Error: "Invalid SCORM Package"
Causes:
- Missing
imsmanifest.xml - Invalid manifest structure
- Unsupported SCORM version
Solutions:
- Verify package contains valid SCORM manifest
- Check SCORM version compatibility
- Review Package Validation Guide
Error: "File Too Large"
Causes:
- Package exceeds size limits
- Quota exceeded
Solutions:
- Use multipart upload for large packages
- Check your storage quota
- Contact support to increase limits
Error: "Package Processing Failed"
Causes:
- Corrupted ZIP file
- Missing required files
- Storage issues
Solutions:
- Verify ZIP file integrity
- Re-export package from authoring tool
- Check storage backend status
- Review error logs for details
Error: "Quota Exceeded"
Causes:
- Package limit reached
- Storage limit reached
Solutions:
- Delete unused packages
- Upgrade subscription plan
- Contact support for quota increase
Best Practices
- Validate Before Processing: Use
validate_only: trueto check packages before committing - Use Versioning: Upload new versions to existing packages to maintain stable IDs
- Monitor Quotas: Track your package and storage usage
- Handle Errors: Implement retry logic for transient failures
- Use Webhooks: Subscribe to
package.processing.completedevents for async workflows
Next Steps
- Launch Your First Session - Create and launch a learning session
- Package Validation Guide - Learn about SCORM requirements
- Webhook Setup - Get notified when packages are processed
- API Guide - Complete endpoint documentation (API Reference coming soon)
Last Updated: 2025-01-15
Related Documentation: