Skip to main content

University Block

University Block

The University Block provides a complete Learning Management System (LMS) API for building educational platforms, corporate training systems, and e-learning applications. Create courses, track progress, assess learners, and issue certificates - all through a simple REST API.

Features

  • Course Management - Create structured courses with modules, lessons, and rich content
  • Progress Tracking - Monitor learner advancement in real-time
  • Quizzes & Assessments - Multiple question types with automatic grading
  • Certificates - Issue verifiable certificates on completion
  • Learning Paths - Define prerequisites and guided curricula
  • Enrollment Management - Control access and manage cohorts
  • Analytics & Reporting - Measure learning outcomes and engagement
  • Multi-tenant Support - Isolated data per organization

API Endpoint

ServiceURL
Universityhttps://university.api.us.23blocks.com

Environment Routing: Use the same URL for all environments. Your API key determines the environment:

  • pk_test_* / sk_test_* → Routes to Staging
  • pk_live_* / sk_live_* → Routes to Production

Quick Start

npm install @23blocks/sdk
import { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { university: 'https://university.api.us.23blocks.com' },
apiKey: 'your-api-key', // Use pk_test_* for staging, pk_live_* for production
});

// Create a course
const course = await client.university.createCourse({
title: 'Introduction to JavaScript',
description: 'Learn the fundamentals of JavaScript programming',
status: 'published'
});

// Enroll a user
await client.university.enroll({
userId: 'user-123',
courseId: course.id
});

// Track lesson completion
await client.university.completeLesson({
userId: 'user-123',
lessonId: 'lesson-abc',
timeSpent: 1800
});

Authentication

All API requests require authentication via API key headers:

curl -X GET "https://api.23blocks.com/v1/university/courses" \
-H "Content-Type: application/json" \
-H "X-App-Id: your-app-id" \
-H "X-Api-Key: your-api-key"

Courses API

List Courses

Retrieve all courses with optional filtering.

GET /v1/university/courses

Query Parameters:

ParameterTypeDescription
statusstringFilter by status: draft, published, archived
categorystringFilter by category ID
instructor_idstringFilter by instructor
pageintegerPage number (default: 1)
per_pageintegerItems per page (default: 20, max: 100)

Response:

{
"data": [
{
"id": "course-abc123",
"type": "course",
"attributes": {
"title": "Introduction to JavaScript",
"description": "Learn the fundamentals of JavaScript programming",
"slug": "intro-to-javascript",
"status": "published",
"thumbnail_url": "https://cdn.23blocks.com/courses/js-thumb.png",
"duration_minutes": 480,
"module_count": 8,
"lesson_count": 24,
"enrollment_count": 1250,
"rating": 4.8,
"settings": {
"self_enrollment": true,
"certificate_enabled": true,
"discussion_enabled": true,
"drip_content": false
},
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-03-20T14:30:00Z"
},
"relationships": {
"instructor": {
"data": { "type": "user", "id": "user-456" }
},
"category": {
"data": { "type": "category", "id": "cat-dev" }
}
}
}
],
"meta": {
"total": 45,
"page": 1,
"per_page": 20
}
}

Create Course

Create a new course.

POST /v1/university/courses

Request Body:

{
"data": {
"type": "course",
"attributes": {
"title": "Advanced React Patterns",
"description": "Master advanced React patterns and best practices",
"category_id": "cat-frontend",
"instructor_id": "user-instructor",
"status": "draft",
"settings": {
"self_enrollment": true,
"certificate_enabled": true,
"passing_score": 80,
"max_attempts": 3
}
}
}
}

Get Course

Retrieve a specific course with its structure.

GET /v1/university/courses/{course_id}

Query Parameters:

ParameterTypeDescription
includestringInclude related resources: modules, lessons, instructor

Update Course

Update course details.

PATCH /v1/university/courses/{course_id}

Delete Course

Delete a course (soft delete).

DELETE /v1/university/courses/{course_id}

Modules API

Modules organize lessons within a course.

List Modules

GET /v1/university/courses/{course_id}/modules

Response:

{
"data": [
{
"id": "module-001",
"type": "module",
"attributes": {
"title": "Getting Started",
"description": "Introduction and environment setup",
"position": 1,
"lesson_count": 4,
"duration_minutes": 45,
"unlock_at": null
}
},
{
"id": "module-002",
"type": "module",
"attributes": {
"title": "Core Concepts",
"description": "Fundamental patterns and techniques",
"position": 2,
"lesson_count": 6,
"duration_minutes": 90,
"unlock_at": "2025-02-01T00:00:00Z"
}
}
]
}

Create Module

POST /v1/university/courses/{course_id}/modules

Request Body:

{
"data": {
"type": "module",
"attributes": {
"title": "Advanced Hooks",
"description": "Deep dive into React hooks",
"position": 3,
"unlock_at": null
}
}
}

Reorder Modules

POST /v1/university/courses/{course_id}/modules/reorder

Request Body:

{
"module_ids": ["module-002", "module-001", "module-003"]
}

Lessons API

List Lessons

GET /v1/university/modules/{module_id}/lessons

Response:

{
"data": [
{
"id": "lesson-001",
"type": "lesson",
"attributes": {
"title": "Introduction to Hooks",
"description": "Understanding the motivation behind hooks",
"position": 1,
"content_type": "video",
"content": {
"video_url": "https://cdn.23blocks.com/videos/hooks-intro.mp4",
"duration_seconds": 720,
"transcript_url": "https://cdn.23blocks.com/transcripts/hooks-intro.vtt"
},
"free_preview": true,
"created_at": "2025-01-15T10:00:00Z"
}
},
{
"id": "lesson-002",
"type": "lesson",
"attributes": {
"title": "useState Deep Dive",
"description": "Mastering the useState hook",
"position": 2,
"content_type": "text",
"content": {
"html": "<h2>Understanding useState</h2><p>The useState hook...</p>",
"estimated_reading_minutes": 12
},
"free_preview": false
}
}
]
}

Create Lesson

POST /v1/university/modules/{module_id}/lessons

Content Types:

TypeDescription
videoVideo content with optional transcript
textRich text/HTML content
documentPDF or downloadable file
embedExternal embed (YouTube, Vimeo, etc.)
quizInline quiz assessment
assignmentSubmission-based assignment
scormSCORM package

Request Body (Video):

{
"data": {
"type": "lesson",
"attributes": {
"title": "Building Custom Hooks",
"description": "Learn to create reusable custom hooks",
"content_type": "video",
"content": {
"video_url": "https://cdn.23blocks.com/videos/custom-hooks.mp4",
"duration_seconds": 1800,
"allow_download": false
},
"position": 3
}
}
}

Request Body (Text):

{
"data": {
"type": "lesson",
"attributes": {
"title": "Hook Rules and Best Practices",
"content_type": "text",
"content": {
"html": "<h2>Rules of Hooks</h2><p>There are two important rules...</p>",
"estimated_reading_minutes": 8
}
}
}
}

Enrollments API

List Enrollments

Get all enrollments for a course or user.

GET /v1/university/enrollments

Query Parameters:

ParameterTypeDescription
course_idstringFilter by course
user_idstringFilter by user
statusstringFilter by status: active, completed, expired, cancelled

Response:

{
"data": [
{
"id": "enrollment-xyz",
"type": "enrollment",
"attributes": {
"status": "active",
"progress_percent": 65,
"lessons_completed": 16,
"total_lessons": 24,
"time_spent_minutes": 320,
"last_activity_at": "2025-03-20T15:30:00Z",
"enrolled_at": "2025-02-01T10:00:00Z",
"expires_at": null,
"completed_at": null
},
"relationships": {
"user": { "data": { "type": "user", "id": "user-123" } },
"course": { "data": { "type": "course", "id": "course-abc" } }
}
}
]
}

Enroll User

POST /v1/university/enrollments

Request Body:

{
"data": {
"type": "enrollment",
"attributes": {
"user_id": "user-123",
"course_id": "course-abc",
"expires_at": "2025-12-31T23:59:59Z"
}
}
}

Bulk Enroll

Enroll multiple users at once.

POST /v1/university/enrollments/bulk

Request Body:

{
"course_id": "course-abc",
"user_ids": ["user-001", "user-002", "user-003"],
"expires_at": "2025-12-31T23:59:59Z",
"send_notification": true
}

Cancel Enrollment

DELETE /v1/university/enrollments/{enrollment_id}

Progress API

Get User Progress

Get detailed progress for a user in a course.

GET /v1/university/progress/{course_id}/users/{user_id}

Response:

{
"data": {
"id": "progress-xyz",
"type": "progress",
"attributes": {
"course_id": "course-abc",
"user_id": "user-123",
"overall_progress": 65.5,
"status": "in_progress",
"modules": [
{
"module_id": "module-001",
"title": "Getting Started",
"progress": 100,
"completed_at": "2025-02-05T12:00:00Z"
},
{
"module_id": "module-002",
"title": "Core Concepts",
"progress": 66.7,
"completed_at": null
}
],
"lessons_completed": [
{
"lesson_id": "lesson-001",
"completed_at": "2025-02-01T14:30:00Z",
"time_spent_seconds": 780
}
],
"current_lesson": {
"lesson_id": "lesson-010",
"position": 45,
"total": 100
},
"total_time_spent_minutes": 320,
"started_at": "2025-02-01T10:00:00Z",
"last_activity_at": "2025-03-20T15:30:00Z"
}
}
}

Complete Lesson

Mark a lesson as completed.

POST /v1/university/lessons/{lesson_id}/complete

Request Body:

{
"user_id": "user-123",
"time_spent_seconds": 720,
"position": 100
}

Update Progress Position

Save video position or scroll progress.

PATCH /v1/university/lessons/{lesson_id}/progress

Request Body:

{
"user_id": "user-123",
"position": 45,
"time_spent_seconds": 300
}

Reset Progress

Reset user progress for a course.

POST /v1/university/progress/{course_id}/users/{user_id}/reset

Quizzes API

Create Quiz

POST /v1/university/quizzes

Request Body:

{
"data": {
"type": "quiz",
"attributes": {
"title": "Module 1 Assessment",
"description": "Test your understanding of the basics",
"lesson_id": "lesson-005",
"time_limit_minutes": 30,
"passing_score": 80,
"max_attempts": 3,
"shuffle_questions": true,
"show_correct_answers": "after_submission",
"questions": [
{
"type": "multiple_choice",
"question": "What hook is used for side effects?",
"options": [
{ "text": "useState", "correct": false },
{ "text": "useEffect", "correct": true },
{ "text": "useContext", "correct": false },
{ "text": "useReducer", "correct": false }
],
"points": 10,
"explanation": "useEffect is the hook designed for handling side effects."
},
{
"type": "true_false",
"question": "Hooks can be called inside loops.",
"correct_answer": false,
"points": 5,
"explanation": "Hooks must be called at the top level, not inside loops or conditions."
},
{
"type": "fill_blank",
"question": "The ____ hook is used to access context values.",
"correct_answers": ["useContext"],
"case_sensitive": false,
"points": 10
},
{
"type": "matching",
"question": "Match the hook to its purpose:",
"pairs": [
{ "left": "useState", "right": "Local component state" },
{ "left": "useEffect", "right": "Side effects" },
{ "left": "useRef", "right": "Mutable references" }
],
"points": 15
},
{
"type": "essay",
"question": "Explain when you would use useReducer over useState.",
"min_words": 50,
"max_words": 500,
"points": 20,
"rubric": "Look for: complex state logic, multiple sub-values, next state depends on previous"
}
]
}
}
}

Get Quiz

GET /v1/university/quizzes/{quiz_id}

Submit Quiz Attempt

POST /v1/university/quizzes/{quiz_id}/attempts

Request Body:

{
"user_id": "user-123",
"answers": [
{ "question_index": 0, "answer": 1 },
{ "question_index": 1, "answer": false },
{ "question_index": 2, "answer": "useContext" },
{ "question_index": 3, "answer": [[0,0], [1,1], [2,2]] },
{ "question_index": 4, "answer": "I would use useReducer when..." }
],
"time_taken_seconds": 1200
}

Response:

{
"data": {
"id": "attempt-abc",
"type": "quiz_attempt",
"attributes": {
"quiz_id": "quiz-xyz",
"user_id": "user-123",
"score": 85,
"passed": true,
"time_taken_seconds": 1200,
"attempt_number": 1,
"results": [
{ "question_index": 0, "correct": true, "points_earned": 10 },
{ "question_index": 1, "correct": true, "points_earned": 5 },
{ "question_index": 2, "correct": true, "points_earned": 10 },
{ "question_index": 3, "correct": true, "points_earned": 15 },
{ "question_index": 4, "pending_review": true, "points_earned": 0 }
],
"submitted_at": "2025-03-20T16:00:00Z"
}
}
}

Get Quiz Attempts

GET /v1/university/quizzes/{quiz_id}/attempts?user_id={user_id}

Grade Essay Question

PATCH /v1/university/attempts/{attempt_id}/grade

Request Body:

{
"question_index": 4,
"points_earned": 18,
"feedback": "Excellent explanation with clear examples."
}

Certificates API

Certificate Templates

List and manage certificate templates.

GET /v1/university/certificate-templates

Response:

{
"data": [
{
"id": "template-001",
"type": "certificate_template",
"attributes": {
"name": "Course Completion",
"description": "Standard completion certificate",
"html_template": "<div class='cert'>...</div>",
"css_styles": ".cert { ... }",
"variables": ["student_name", "course_name", "completion_date", "instructor_name"],
"paper_size": "A4",
"orientation": "landscape"
}
}
]
}

Create Template

POST /v1/university/certificate-templates

Issue Certificate

POST /v1/university/certificates

Request Body:

{
"data": {
"type": "certificate",
"attributes": {
"user_id": "user-123",
"course_id": "course-abc",
"template_id": "template-001",
"custom_fields": {
"grade": "A",
"distinction": true
}
}
}
}

Response:

{
"data": {
"id": "cert-xyz789",
"type": "certificate",
"attributes": {
"certificate_number": "CERT-2025-0001234",
"user_id": "user-123",
"course_id": "course-abc",
"issued_at": "2025-03-20T16:30:00Z",
"verification_url": "https://verify.23blocks.com/cert/CERT-2025-0001234",
"pdf_url": "https://cdn.23blocks.com/certificates/cert-xyz789.pdf",
"valid": true
}
}
}

Verify Certificate

Public endpoint for certificate verification.

GET /v1/university/certificates/verify/{certificate_number}

Response:

{
"valid": true,
"certificate": {
"certificate_number": "CERT-2025-0001234",
"recipient_name": "John Doe",
"course_name": "Introduction to JavaScript",
"issued_by": "TechCorp Academy",
"issued_at": "2025-03-20T16:30:00Z",
"status": "valid"
}
}

Revoke Certificate

POST /v1/university/certificates/{certificate_id}/revoke

Request Body:

{
"reason": "Academic dishonesty detected"
}

Learning Paths API

List Learning Paths

GET /v1/university/learning-paths

Response:

{
"data": [
{
"id": "path-frontend",
"type": "learning_path",
"attributes": {
"title": "Frontend Developer Path",
"description": "Become a professional frontend developer",
"total_courses": 5,
"total_duration_hours": 40,
"courses": [
{
"course_id": "course-html",
"position": 1,
"required": true,
"prerequisites": []
},
{
"course_id": "course-css",
"position": 2,
"required": true,
"prerequisites": ["course-html"]
},
{
"course_id": "course-js",
"position": 3,
"required": true,
"prerequisites": ["course-html", "course-css"]
},
{
"course_id": "course-react",
"position": 4,
"required": true,
"prerequisites": ["course-js"]
},
{
"course_id": "course-testing",
"position": 5,
"required": false,
"prerequisites": ["course-react"]
}
],
"certificate_id": "template-path-completion"
}
}
]
}

Create Learning Path

POST /v1/university/learning-paths

Get User Path Progress

GET /v1/university/learning-paths/{path_id}/users/{user_id}/progress

Response:

{
"data": {
"path_id": "path-frontend",
"user_id": "user-123",
"overall_progress": 60,
"courses_completed": 3,
"total_courses": 5,
"current_course": "course-react",
"next_available": ["course-react"],
"locked": ["course-testing"],
"time_invested_hours": 24,
"estimated_completion_hours": 16
}
}

Analytics API

Course Analytics

GET /v1/university/analytics/courses/{course_id}

Query Parameters:

ParameterTypeDescription
periodstringTime period: 7d, 30d, 90d, 1y, all
metricsstringComma-separated: enrollments, completions, engagement, ratings

Response:

{
"data": {
"course_id": "course-abc",
"period": "30d",
"metrics": {
"enrollments": {
"total": 245,
"new": 82,
"trend": 15.3
},
"completions": {
"total": 156,
"rate": 63.7,
"average_days_to_complete": 14
},
"engagement": {
"active_learners": 189,
"average_time_per_session_minutes": 28,
"lessons_completed_per_day": 4.2,
"drop_off_lessons": [
{ "lesson_id": "lesson-015", "title": "Advanced Patterns", "drop_rate": 23.5 }
]
},
"ratings": {
"average": 4.7,
"count": 134,
"distribution": { "5": 89, "4": 32, "3": 10, "2": 2, "1": 1 }
}
},
"timeline": [
{ "date": "2025-03-01", "enrollments": 12, "completions": 8 },
{ "date": "2025-03-02", "enrollments": 15, "completions": 5 }
]
}
}

User Analytics

GET /v1/university/analytics/users/{user_id}

Response:

{
"data": {
"user_id": "user-123",
"summary": {
"courses_enrolled": 8,
"courses_completed": 5,
"total_time_hours": 67,
"certificates_earned": 4,
"average_score": 88.5,
"current_streak_days": 12
},
"learning_activity": [
{ "date": "2025-03-19", "time_minutes": 45, "lessons_completed": 3 },
{ "date": "2025-03-20", "time_minutes": 60, "lessons_completed": 4 }
],
"strengths": ["JavaScript", "React", "CSS"],
"recommendations": [
{ "course_id": "course-typescript", "reason": "Based on JavaScript completion" }
]
}
}

Leaderboard

GET /v1/university/analytics/leaderboard

Query Parameters:

ParameterTypeDescription
scopestringScope: course, path, global
course_idstringRequired if scope is course
metricstringRanking metric: progress, score, time, streak
limitintegerNumber of entries (default: 10)

Discussion Forums API

List Discussions

GET /v1/university/courses/{course_id}/discussions

Response:

{
"data": [
{
"id": "discussion-001",
"type": "discussion",
"attributes": {
"title": "Question about useEffect cleanup",
"content": "I'm confused about when cleanup functions run...",
"author_id": "user-456",
"lesson_id": "lesson-008",
"reply_count": 5,
"upvotes": 12,
"pinned": false,
"resolved": true,
"created_at": "2025-03-18T10:00:00Z"
}
}
]
}

Create Discussion

POST /v1/university/courses/{course_id}/discussions

Reply to Discussion

POST /v1/university/discussions/{discussion_id}/replies

Mark as Resolved

PATCH /v1/university/discussions/{discussion_id}/resolve

Assignments API

Create Assignment

POST /v1/university/assignments

Request Body:

{
"data": {
"type": "assignment",
"attributes": {
"title": "Build a Todo App",
"description": "Create a fully functional todo application using React hooks",
"lesson_id": "lesson-020",
"due_date": "2025-04-01T23:59:59Z",
"max_score": 100,
"allow_late_submission": true,
"late_penalty_percent": 10,
"rubric": [
{ "criteria": "Functionality", "max_points": 40, "description": "All features working correctly" },
{ "criteria": "Code Quality", "max_points": 30, "description": "Clean, readable code" },
{ "criteria": "UI/UX", "max_points": 20, "description": "User-friendly interface" },
{ "criteria": "Documentation", "max_points": 10, "description": "README and comments" }
],
"allowed_file_types": [".zip", ".tar.gz"],
"max_file_size_mb": 50
}
}
}

Submit Assignment

POST /v1/university/assignments/{assignment_id}/submissions

Request Body (multipart/form-data):

user_id: user-123
file: [binary]
notes: "Implemented all features including bonus dark mode."

Grade Submission

PATCH /v1/university/submissions/{submission_id}/grade

Request Body:

{
"scores": [
{ "criteria": "Functionality", "points": 38 },
{ "criteria": "Code Quality", "points": 28 },
{ "criteria": "UI/UX", "points": 18 },
{ "criteria": "Documentation", "points": 9 }
],
"total_score": 93,
"feedback": "Excellent work! Consider adding error handling for edge cases."
}

Webhooks

Subscribe to University Block events for real-time notifications.

Available Events

EventDescription
enrollment.createdUser enrolled in a course
enrollment.completedUser completed a course
enrollment.expiredEnrollment access expired
lesson.completedUser completed a lesson
quiz.submittedQuiz attempt submitted
quiz.passedUser passed a quiz
quiz.failedUser failed a quiz
certificate.issuedCertificate generated
assignment.submittedAssignment submitted
assignment.gradedAssignment graded
discussion.createdNew discussion thread
discussion.repliedNew reply to discussion

Webhook Payload Example

{
"event": "enrollment.completed",
"timestamp": "2025-03-20T16:30:00Z",
"data": {
"enrollment_id": "enrollment-xyz",
"user_id": "user-123",
"course_id": "course-abc",
"completed_at": "2025-03-20T16:30:00Z",
"final_score": 92,
"time_spent_hours": 12.5,
"certificate_id": "cert-xyz789"
}
}

Configure Webhooks

POST /v1/university/webhooks

Request Body:

{
"url": "https://your-app.com/webhooks/university",
"events": ["enrollment.completed", "certificate.issued", "quiz.passed"],
"secret": "your-webhook-secret"
}

SDK Examples

JavaScript/TypeScript

import { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { university: 'https://university.api.us.23blocks.com' },
appId: 'your-app-id',
apiKey: 'your-api-key',
});

// Create a complete course structure
async function createCourse() {
// Create course
const course = await client.university.createCourse({
title: 'React Masterclass',
description: 'From beginner to expert',
status: 'draft'
});

// Add module
const module = await client.university.createModule({
courseId: course.id,
title: 'Introduction',
position: 1
});

// Add lessons
await client.university.createLesson({
moduleId: module.id,
title: 'Welcome',
contentType: 'video',
content: {
videoUrl: 'https://cdn.example.com/welcome.mp4',
durationSeconds: 300
}
});

// Add quiz
await client.university.createQuiz({
lessonId: 'lesson-id',
title: 'Module Quiz',
passingScore: 80,
questions: [/* ... */]
});

// Publish course
await client.university.updateCourse(course.id, {
status: 'published'
});

return course;
}

// Track learner progress
async function trackProgress(userId: string, courseId: string) {
// Get detailed progress
const progress = await client.university.getProgress({
userId,
courseId
});

console.log(`Progress: ${progress.overallProgress}%`);
console.log(`Time spent: ${progress.totalTimeSpentMinutes} minutes`);
console.log(`Completed lessons: ${progress.lessonsCompleted.length}`);

return progress;
}

// Issue certificate on completion
async function issueCertificate(userId: string, courseId: string) {
const certificate = await client.university.issueCertificate({
userId,
courseId,
templateId: 'template-001'
});

console.log(`Certificate issued: ${certificate.certificateNumber}`);
console.log(`Verify at: ${certificate.verificationUrl}`);
console.log(`PDF: ${certificate.pdfUrl}`);

return certificate;
}

Python

from blocks_sdk import BlocksClient

client = BlocksClient(
base_url="https://api.23blocks.com",
app_id="your-app-id",
api_key="your-api-key"
)

# Enroll users in bulk
def bulk_enroll(course_id: str, user_ids: list, expires_at: str = None):
result = client.university.bulk_enroll(
course_id=course_id,
user_ids=user_ids,
expires_at=expires_at,
send_notification=True
)
print(f"Enrolled {result['enrolled_count']} users")
return result

# Get course analytics
def get_course_stats(course_id: str):
analytics = client.university.get_analytics(
course_id=course_id,
period="30d",
metrics=["enrollments", "completions", "engagement"]
)

print(f"Enrollments: {analytics['metrics']['enrollments']['total']}")
print(f"Completion rate: {analytics['metrics']['completions']['rate']}%")
print(f"Active learners: {analytics['metrics']['engagement']['active_learners']}")

return analytics

# Export learner data
def export_learner_report(course_id: str):
report = client.university.export_report(
course_id=course_id,
format="csv",
include=["progress", "scores", "time_spent"]
)
return report

SCORM Support

The University Block supports SCORM 1.2 and SCORM 2004 packages.

Upload SCORM Package

POST /v1/university/scorm/upload

Request (multipart/form-data):

file: [scorm.zip]
course_id: course-abc
module_id: module-001
title: "Interactive Simulation"

SCORM Runtime API

The block provides full SCORM runtime API support including:

  • LMSInitialize / Initialize
  • LMSGetValue / GetValue
  • LMSSetValue / SetValue
  • LMSCommit / Commit
  • LMSFinish / Terminate
  • LMSGetLastError / GetLastError

Rate Limits

EndpointRate Limit
Course CRUD100 requests/minute
Enrollment operations200 requests/minute
Progress updates500 requests/minute
Quiz submissions50 requests/minute
Analytics queries30 requests/minute
Certificate generation20 requests/minute

Error Handling

All errors follow JSON:API error format:

{
"errors": [
{
"status": "422",
"code": "enrollment_limit_reached",
"title": "Enrollment Limit Reached",
"detail": "This course has reached its maximum enrollment capacity of 500 students.",
"source": { "pointer": "/data/attributes/course_id" }
}
]
}

Common Error Codes

CodeDescription
course_not_foundCourse does not exist
already_enrolledUser is already enrolled in the course
enrollment_expiredEnrollment has expired
prerequisite_not_metRequired prerequisites not completed
quiz_attempts_exhaustedNo more quiz attempts available
lesson_lockedLesson is locked (drip content or prerequisites)
assignment_past_dueAssignment submission deadline passed

Next Steps