SCORM API Architecture Overview
SCORM API Architecture Overview
Introduction
The AllureLMS SCORM API is a standalone, API-first service that provides SCORM 1.2 and SCORM 2004 package hosting, session management, and learning analytics. Built with Next.js 14 and Supabase, it serves as a backend service for any client system (TrainingOS, AllureLMS, or external applications) that needs SCORM functionality.
High-Level Architecture
System Components
┌─────────────────────────────────────────────────────────────┐
│ Client Applications │
│ (TrainingOS, AllureLMS, Custom LMS, WordPress, etc.) │
└────────────────────┬────────────────────────────────────────┘
│
│ HTTPS / REST API
│
┌────────────────────▼────────────────────────────────────────┐
│ SCORM API Service (Next.js 14) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ API Layer │ │ Auth Layer │ │ Player UI │ │
│ │ (REST API) │ │ (API Keys + │ │ (Browser) │ │
│ │ │ │ Clerk) │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Business │ │ Storage │ │ Webhooks │ │
│ │ Logic │ │ Manager │ │ Service │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────┬───────────────┬───────────────┬───────────────┘
│ │ │
┌────────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Supabase │ │ Cloudflare │ │ Upstash │
│ PostgreSQL │ │ R2 │ │ Redis │
│ (Database) │ │ (Storage) │ │ (Rate Limit)│
└───────────────┘ └─────────────┘ └───────────────┘
Core Architecture Principles
- API-First Design: All functionality exposed via RESTful API endpoints
- Multi-Tenancy: Complete data isolation per tenant using Row Level Security (RLS)
- Stateless Services: Serverless functions for horizontal scalability
- Separation of Concerns: Clear boundaries between API, business logic, and storage
- Security by Default: Authentication required, tenant isolation enforced, rate limiting enabled
Technology Stack
Runtime & Framework
- Next.js 14 (App Router): Serverless API routes and React UI
- TypeScript 5.x: Type-safe development
- Node.js 18+: Runtime environment
Backend Services
- Supabase PostgreSQL: Primary database with Row Level Security
- Supabase Storage: Default file storage (SCORM packages)
- Cloudflare R2: Optional S3-compatible storage (production recommended)
- Upstash Redis: Distributed rate limiting (optional)
Authentication & Authorization
- API Keys: Tenant-scoped keys with SHA-256 hashing
- Clerk: Web application authentication for admin dashboard
- JWT Tokens: Launch tokens and dispatch tokens for secure package access
Validation & Utilities
- Zod: Schema validation for API requests
- date-fns: Date manipulation utilities
Multi-Tenancy Architecture
Tenant Isolation Strategy
The SCORM API implements database-level multi-tenancy using PostgreSQL Row Level Security (RLS):
- Tenant ID in Every Table: All data tables include
tenant_idcolumn - RLS Policies: Database policies automatically filter queries by tenant
- API Key Scoping: API keys are bound to a specific tenant
- Automatic Filtering: All queries automatically include tenant context
Tenant Data Model
interface Tenant {
id: string; // UUID
name: string;
created_at: string;
// Quota limits
max_packages?: number;
max_storage_bytes?: number;
}
Data Isolation Flow
API Request
↓
Extract tenant_id from API Key or Clerk session
↓
Query Database with tenant_id filter
↓
RLS Policy enforces tenant isolation
↓
Return only tenant's data
API Architecture
API Route Organization
The API is organized into logical route groups:
-
/api/v1/*: Public API endpoints (API key authenticated)/api/v1/packages: Package management/api/v1/sessions: Session and CMI data/api/v1/webhooks: Webhook management/api/v1/dispatches: Dispatch package distribution/api/v1/xapi: xAPI telemetry endpoints
-
/api/customer/*: Customer-facing endpoints (Clerk authenticated)- Dashboard functionality
- Self-service API key management
- Usage reports
- Billing portal
-
/api/admin/*: System admin endpoints (Clerk + system admin role)- System health monitoring
- Tenant management
- SaaS metrics
- Churn detection
-
/api/learner/*: Learner-facing endpoints- Progress tracking
- Certificates
Request Flow
1. Client Request
↓
2. Authentication Middleware
- Validate API Key or Clerk session
- Extract tenant_id
↓
3. Authorization Check
- Verify scopes (read/write/admin)
- Check tenant access
↓
4. Business Logic
- Validate input (Zod schemas)
- Execute business rules
- Apply tenant isolation
↓
5. Database Operation
- RLS automatically filters by tenant_id
↓
6. Response
- Format JSON response
- Include rate limit headers
Storage Architecture
Storage Backends
The SCORM API supports two storage backends:
-
Supabase Storage (Default)
- Integrated with database
- Automatic RLS enforcement
- CDN support
-
Cloudflare R2 (Recommended for Production)
- S3-compatible API
- Lower egress costs
- Global CDN
- Automatic failover if configured
Storage Structure
scorm-packages/
├── {tenant_id}/
│ ├── scorm-extracted/
│ │ └── {package_id}/
│ │ ├── imsmanifest.xml
│ │ ├── index.html
│ │ └── assets/
│ └── uploads/
│ └── {temp_upload_id}.zip
Upload Flow
-
Direct Upload (Small files < 100MB)
- Client → API → Storage
- Immediate processing
-
Multipart Upload (Large files 10GB+)
- Initialize upload → Get presigned URLs
- Upload parts directly to storage
- Complete upload → Process package
-
Presigned URL Upload (Medium files)
- Request presigned URL
- Upload directly to storage
- Notify API for processing
Security Architecture
Authentication Methods
-
API Key Authentication
- SHA-256 hashed in database
- Tenant-scoped
- Scope-based permissions (read/write/admin)
- Expiration support
-
Clerk Authentication
- Web application users
- Session-based
- Tenant resolution via
user_tenantstable
-
Launch Tokens
- JWT tokens for secure package launches
- Short-lived (default 600 seconds)
- Signed with secret key
-
Dispatch Tokens
- JWT tokens for dispatch package distribution
- Configurable expiration
- Domain allowlisting support
Security Features
- Row Level Security (RLS): Database-level tenant isolation
- Rate Limiting: Per-tenant rate limits (local or distributed via Redis)
- Input Validation: Zod schemas for all API inputs
- HMAC Signatures: Webhook payload verification
- HTTPS Only: All connections encrypted
- CORS Protection: Configurable allowed origins
Scalability Architecture
Horizontal Scaling
- Stateless API: All API routes are stateless serverless functions
- Database Connection Pooling: Supabase handles connection pooling
- CDN Caching: Static assets cached at edge
- Distributed Rate Limiting: Optional Redis-based rate limiting
Performance Optimizations
- Database Indexes: Optimized indexes on
tenant_id,package_id,session_id - Query Optimization: Efficient queries with proper joins
- Caching Strategy: Response caching for read-heavy endpoints
- Lazy Loading: On-demand package processing
Resource Limits
- Tenant Quotas: Per-tenant package and storage limits
- Rate Limits: Per-tenant API rate limits
- Upload Limits: Configurable max upload size (default 10GB)
Integration Patterns
Client Integration
-
API Key Integration (Server-to-Server)
const response = await fetch('https://api.scorm.com/v1/packages', { headers: { 'X-API-Key': 'your-api-key', 'Content-Type': 'application/json' } }); -
Clerk Integration (Web Application)
- User authenticates via Clerk
- API automatically resolves tenant
- No API key needed for web UI
-
Launch Integration (SCORM Player)
- Request launch URL with user/session context
- Receive signed launch token
- Embed player in iframe
Webhook Integration
- Event-Driven: Webhooks for package processing, session completion
- Retry Logic: Exponential backoff with jitter
- HMAC Verification: Secure webhook payload verification
- Delivery Tracking: Persistent delivery status tracking
Deployment Architecture
Vercel Deployment (Recommended)
- Serverless Functions: Automatic scaling
- Edge Network: Global CDN
- Environment Variables: Secure secret management
- Preview Deployments: Per-branch preview URLs
Docker Deployment (Alternative)
- Multi-stage Build: Optimized production image
- Health Checks: Container health monitoring
- Volume Mounts: Optional local storage
Monitoring & Observability
Health Monitoring
- Health Endpoint:
/api/healthfor system status - Database Health: Connection and query performance
- Storage Health: R2 and Supabase storage accessibility
- Rate Limiting Status: Distributed vs local rate limiting
Metrics & Analytics
- SaaS Metrics: MRR, ARR, churn rate, subscription metrics
- Usage Analytics: Package uploads, storage usage, session activity
- Tenant Activity: Active tenants, churn indicators
- API Key Usage: Usage statistics per API key
Admin Dashboard
- System Health: Real-time system status
- Tenant Management: Tenant overview with churn detection
- API Key Management: Create, revoke, monitor API keys
- Usage Reports: Custom reports and exports
Data Flow Examples
Package Upload Flow
1. Client → POST /api/v1/packages
2. API validates request (Zod schema)
3. API extracts tenant_id from API key
4. API uploads file to storage (Supabase/R2)
5. API processes package (extract, parse manifest)
6. API creates package record in database
7. API triggers webhook (if configured)
8. API returns package metadata
Session Launch Flow
1. Client → POST /api/v1/packages/{id}/launch
2. API validates package access (tenant check)
3. API creates/retrieves session record
4. API generates signed launch token
5. API returns launch URL with token
6. Client embeds player in iframe
7. Player loads SCORM content
8. Player communicates via SCORM API Bridge
9. API updates session CMI data
CMI Data Update Flow
1. SCORM Player → API Bridge → PUT /api/v1/sessions/{id}
2. API validates session ownership (tenant check)
3. API implements optimistic locking (version check)
4. API merges CMI data updates
5. API updates session record
6. API logs event for audit trail
7. API converts to xAPI statement (if enabled)
8. API triggers webhook (if configured)
9. API returns updated session
Error Handling
Error Response Format
{
"error": {
"code": "PACKAGE_NOT_FOUND",
"message": "Package with ID xyz not found",
"details": {
"package_id": "xyz",
"tenant_id": "abc"
}
}
}
Error Categories
- 4xx Client Errors: Invalid requests, authentication failures
- 5xx Server Errors: Internal errors, database failures
- Rate Limit Errors: 429 Too Many Requests
- Validation Errors: 422 Unprocessable Entity
Future Architecture Considerations
Planned Enhancements
- GraphQL API: Alternative query interface
- WebSocket Support: Real-time session updates
- Advanced Analytics: Machine learning insights
- Multi-Region Deployment: Geographic distribution
- Event Sourcing: Complete audit trail
Last Updated: 2025-01-12
Version: 1.0
For detailed system design, see System Design Documentation.