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: One URL, one environment. All shared-platform API keys are live keys:

  • pk_live_* / sk_live_* → your production tenant. Need a separate staging environment? It is available as a paid add-on on deployments in your own cloud account — see 23blocks in a Box.

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', // Your live API key (pk_live_*)
});

// 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

Use This Block with AI Agents

This block ships an official Claude Code plugin from the public 23blocks marketplace (19 plugins, 205 skills). Your agent gets full working knowledge of this API — endpoints, identity registration, and conventions.

# one-time: add the 23blocks marketplace
claude plugin marketplace add https://github.com/23blocks-OS/ai-agents

# install this block's plugin
claude plugin install university-block

Configure BLOCKS_API_URL, BLOCKS_API_KEY, and BLOCKS_AUTH_TOKEN. Register identity first: each block is autonomous — register the user with this block's identity endpoint before private calls (only user_unique_id is required; email/phone are optional notification-routing fields).

Full reference: AI Agents & Claude Code Plugins · github.com/23blocks-OS/ai-agents