API Reference

All endpoints live under /api/v1, return JSON, and use Laravel Sanctum tokens. Send Authorization: Bearer <token> on protected routes.

Authentication

Account lifecycle — register, login, token management, and email verification.

Account creation for students, instructors, and admins.

/api/v1/auth/register
Public

Request Body

{ "name": "Alice Thompson", "email": "alice@university.edu", "password": "secret123", "password_confirmation": "secret123", "role": "student" }

Response · 200 / 201

{ "message": "Account created. Please verify your email.", "user": { "id": "p1", "name": "Alice Thompson", "email": "alice@university.edu", "role": "student", "join_date": "2025-09-01" }, "token": "1|AbCdEfGhIjKl" }

Status Codes

201 Created — Registration successful, verification email sent
422 Unprocessable Entity — Email already taken or password mismatch

Authenticate and receive a Sanctum bearer token.

/api/v1/auth/login
Public

Request Body

{ "email": "alice@university.edu", "password": "secret123" }

Response · 200 / 201

{ "user": { "id": "p1", "name": "Alice Thompson", "email": "alice@university.edu", "role": "student" }, "token": "2|XyZaBcDeFgHi" }

Status Codes

200 OK — Login successful
401 Unauthorized — Invalid credentials
422 Unprocessable Entity — Validation error

Send a signed password-reset link to the given email.

/api/v1/auth/forgot-password
Public

Request Body

{ "email": "alice@university.edu" }

Response · 200 / 201

{ "message": "We have emailed your password reset link." }

Status Codes

200 OK — Reset link sent
400 Bad Request — Email not found or throttled
422 Unprocessable Entity — Invalid email format

Reset the password using the signed token from the reset email.

/api/v1/auth/reset-password
Public

Request Body

{ "token": "abc123", "email": "alice@university.edu", "password": "newSecret", "password_confirmation": "newSecret" }

Response · 200 / 201

{ "message": "Your password has been reset." }

Status Codes

200 OK — Password reset successful
400 Bad Request — Token expired or invalid

Confirm the signed link sent after registration.

/api/v1/auth/verify-email/{id}/{hash}
Public

Request Body

No request body required

Response · 200 / 201

{ "message": "Email verified successfully." }

Status Codes

200 OK — Email verified
403 Forbidden — Invalid or tampered signature

Re-send the verification email for an unverified account.

/api/v1/auth/email/resend
Student Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "message": "Verification email resent." }

Status Codes

200 OK — Email sent
400 Bad Request — Email already verified

Return the authenticated user's full profile.

/api/v1/auth/me
Student Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "id": "p1", "name": "Alice Thompson", "email": "alice@university.edu", "role": "student", "department": "Computer Science", "institution": "University of Technology", "country": "United States", "timezone": "America\/New_York", "language": "English", "bio": null, "join_date": "2025-09-01", "last_access": "2 hours ago", "enrolled_courses": 3 }

Status Codes

200 OK — Profile returned
401 Unauthorized — Token missing or expired

Revoke the current Sanctum token.

/api/v1/auth/logout
Student Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "message": "Logged out successfully." }

Status Codes

200 OK — Token revoked
401 Unauthorized — No valid token provided

Dashboards

Role-specific summary views aggregating KPIs for each user type.

Platform-wide totals: users, courses, enrollments, system health.

/api/v1/dashboard/admin
Admin

Request Body

No request body required

Response · 200 / 201

{ "total_users": 13, "total_courses": 5, "total_enrollments": 18, "active_courses": 4, "system_health": "ok" }

Status Codes

200 OK — Stats returned
401 Unauthorized
403 Forbidden — Admin role required

Active courses, total enrollments, weekly engagement, and pending grading for the instructor.

/api/v1/dashboard/instructor
Instructor

Request Body

No request body required

Response · 200 / 201

{ "active_courses": [ { "id": "course1", "name": "Introduction to Python Programming", "enrolled_students": 142 } ], "total_enrollments": 240, "weekly_engagement": [ { "day_label": "Mon", "active_students": 120, "submissions": 45 } ], "pending_grading_tasks": [ { "activity_id": "a6", "activity_name": "Assignment 1: FizzBuzz", "ungraded_count": 3 } ] }

Status Codes

200 OK — Snapshot returned
401 Unauthorized
403 Forbidden — Instructor role required

Enrolled courses, progress, upcoming due dates, and recent notifications.

/api/v1/dashboard/student
Student

Request Body

No request body required

Response · 200 / 201

{ "enrolled_courses": [ { "id": "course1", "name": "Introduction to Python Programming", "progress": 85, "next_due": "2026-02-15" } ], "overall_progress": 71, "upcoming_due_dates": [ { "activity_name": "Quiz 2: Functions", "due_date": "2026-02-15" } ], "recent_notifications": [ { "id": "n1", "title": "Quiz Submission", "message": "Alice Thompson submitted Quiz 1", "timestamp": "2 minutes ago", "read": false } ] }

Status Codes

200 OK — Hub data returned
401 Unauthorized
403 Forbidden — Student role required

Courses & Enrollment

CRUD for courses and participant enrollment.

Paginated course list; filter by status, category, instructor.

/api/v1/courses
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "course1", "name": "Introduction to Python Programming", "short_name": "PYTH101", "category_name": "Web Development", "instructor_name": "Dr. Sarah Johnson", "enrolled_students": 142, "status": "active", "format": "topics", "start_date": "2026-01-15", "end_date": "2026-06-15", "tags": [ "python", "programming", "beginner" ] } ], "meta": { "total": 5 } }

Status Codes

200 OK — List returned
401 Unauthorized

Create a new course.

/api/v1/courses
Admin Instructor

Request Body

{ "name": "Introduction to Python Programming", "short_name": "PYTH101", "category_id": "cat2", "format": "topics", "start_date": "2026-01-15", "end_date": "2026-06-15", "description": "Learn Python from scratch", "tags": [ "python", "beginner" ], "visibility": "shown" }

Response · 200 / 201

{ "message": "Course created.", "data": { "id": "course1", "name": "Introduction to Python Programming", "status": "draft" } }

Status Codes

201 Created — Course created
401 Unauthorized
422 Unprocessable Entity — Validation failed

Full detail for one course.

/api/v1/courses/{id}
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": { "id": "course1", "name": "Introduction to Python Programming", "short_name": "PYTH101", "description": "Learn Python from scratch", "category_id": "cat2", "category_name": "Web Development", "instructor_id": "user1", "instructor_name": "Dr. Sarah Johnson", "enrolled_students": 142, "status": "active", "visibility": "shown", "format": "topics", "start_date": "2026-01-15", "end_date": "2026-06-15", "language": "English", "tags": [ "python", "programming", "beginner" ], "max_students": null } }

Status Codes

200 OK — Course returned
401 Unauthorized
404 Not Found — Course not found

Update course metadata, status, or visibility.

/api/v1/courses/{id}
Admin Instructor

Request Body

{ "name": "Python Programming Masterclass", "status": "active", "visibility": "shown", "max_students": 200 }

Response · 200 / 201

{ "message": "Course updated.", "data": { "id": "course1", "name": "Python Programming Masterclass", "status": "active" } }

Status Codes

200 OK — Updated
401 Unauthorized
403 Forbidden
404 Not Found
422 Unprocessable Entity

Permanently remove a course and all related data.

/api/v1/courses/{id}
Admin

Request Body

No request body required

Response · 200 / 201

{ "message": "Course deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
403 Forbidden — Admin only
404 Not Found

All enrollments with role, progress, last-access.

/api/v1/courses/{id}/participants
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "e1", "user_id": "p1", "user_name": "Alice Thompson", "role": "student", "enrolled_date": "2026-01-15", "last_access": "2 hours ago", "progress": 85, "groups": [ "Group A" ] }, { "id": "e7", "user_id": "p7", "user_name": "Grace Chen", "role": "teaching_assistant", "progress": 100, "groups": [] } ], "course_id": "course1" }

Status Codes

200 OK — Participants returned
401 Unauthorized
403 Forbidden

Enroll a user with a specified role.

/api/v1/courses/{id}/enroll
Admin Instructor

Request Body

{ "user_id": "p1", "role": "student" }

Response · 200 / 201

{ "message": "User enrolled." }

Status Codes

201 Created — Enrolled
401 Unauthorized
403 Forbidden
422 Unprocessable Entity — User already enrolled

Remove a user's enrollment.

/api/v1/courses/{id}/enroll/{userId}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "User unenrolled." }

Status Codes

200 OK — Unenrolled
401 Unauthorized
403 Forbidden
404 Not Found

Student self-enrolls into a course. No request body needed — uses the authenticated user's identity.

/api/v1/courses/{id}/join
Student

Request Body

No request body required

Response · 200 / 201

{ "message": "Successfully enrolled in course.", "course_id": "course1", "user_id": "p1", "role": "student" }

Status Codes

201 Created — Enrolled successfully
401 Unauthorized
409 Conflict — Already enrolled in this course
422 Unprocessable Entity — Course is full or enrollment is closed

Student withdraws from a course they are enrolled in.

/api/v1/courses/{id}/leave
Student

Request Body

No request body required

Response · 200 / 201

{ "message": "Successfully left the course.", "course_id": "course1", "user_id": "p1" }

Status Codes

200 OK — Successfully withdrawn
401 Unauthorized
404 Not Found — Not enrolled in this course

Sections & Activities

Manage course sections (weeks/topics) and individual learning activities.

All sections for a course ordered by sort_order.

/api/v1/courses/{id}/sections
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "sec1-c1", "course_id": "course1", "title": "Week 1: Introduction to Python", "summary": null, "sort_order": 1, "visible": true, "collapsed": false }, { "id": "sec2-c1", "course_id": "course1", "title": "Week 2: Control Flow", "sort_order": 2, "visible": true } ], "course_id": "course1" }

Status Codes

200 OK — Sections returned
401 Unauthorized
404 Not Found

Add a new week or topic section.

/api/v1/courses/{id}/sections
Admin Instructor

Request Body

{ "title": "Week 5: Advanced OOP", "sort_order": 5, "visible": true }

Response · 200 / 201

{ "message": "Section created.", "data": { "id": "sec5-c1", "course_id": "course1", "title": "Week 5: Advanced OOP", "sort_order": 5, "visible": true } }

Status Codes

201 Created — Section created
401 Unauthorized
422 Unprocessable Entity

Rename, reorder, or toggle visibility.

/api/v1/courses/{id}/sections/{sectionId}
Admin Instructor

Request Body

{ "title": "Week 1: Python Foundations", "sort_order": 1, "visible": true }

Response · 200 / 201

{ "message": "Section updated.", "data": { "course_id": "course1", "section_id": "sec1-c1", "title": "Week 1: Python Foundations" } }

Status Codes

200 OK — Updated
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Remove a section and cascade-delete all activities in it.

/api/v1/courses/{id}/sections/{sectionId}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Section deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
403 Forbidden
404 Not Found

All activities in a section ordered by sort_order.

/api/v1/sections/{id}/activities
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "a4", "section_id": "sec1-c1", "course_id": "course1", "type": "quiz", "name": "Quiz 1: Python Basics", "due_date": "2026-02-01", "visible": true, "completion_status": "completed", "grade_max": 100, "sort_order": 2 }, { "id": "a3", "section_id": "sec1-c1", "type": "file", "name": "Python Installation Guide.pdf", "grade_max": null } ], "section_id": "sec1-c1" }

Status Codes

200 OK — Activities returned
401 Unauthorized
404 Not Found

Add a new activity. Types: assignment | attendance | bigbluebutton | book | checklist | choice | certificate | database | feedback | file | folder | forum | glossary | h5p | ims_content_package | lesson | page | quiz | scorm | text_and_media_area. Use the settings JSON field for tool-specific configuration.

/api/v1/sections/{id}/activities
Admin Instructor

Request Body

{ "type": "quiz", "name": "Quiz 3: OOP Basics", "visible": true, "grade_max": 100, "due_date": "2026-03-01", "sort_order": 0, "settings": null }

Response · 200 / 201

{ "message": "Activity created.", "data": { "section_id": "sec4-c1", "type": "quiz", "name": "Quiz 3: OOP Basics", "grade_max": 100 } }

Status Codes

201 Created — Activity created
401 Unauthorized
422 Unprocessable Entity — Invalid type enum

Edit activity details, due date, visibility, or grade max.

/api/v1/activities/{id}
Admin Instructor

Request Body

{ "name": "Quiz 1: Python Fundamentals", "due_date": "2026-02-05", "visible": true, "grade_max": 100 }

Response · 200 / 201

{ "message": "Activity updated.", "data": { "id": "a4", "name": "Quiz 1: Python Fundamentals", "due_date": "2026-02-05" } }

Status Codes

200 OK — Updated
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Remove an activity; also deletes associated grade items.

/api/v1/activities/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Activity deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
403 Forbidden
404 Not Found

Grades & Gradebook

Retrieve and submit grades for course activities.

All grade items and student submissions for a course.

/api/v1/courses/{id}/grades
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "g1", "course_id": "course1", "activity_id": "a4", "activity_name": "Quiz 1: Python Basics", "activity_type": "quiz", "grade_max": 100, "grades": [ { "student_id": "p1", "student_name": "Alice Thompson", "grade": 92, "percentage": 92, "status": "graded" }, { "student_id": "p4", "student_name": "David Kim", "grade": null, "status": "not_submitted" } ] }, { "id": "g2", "activity_name": "Assignment 1: FizzBuzz", "grade_max": 50 } ], "course_id": "course1" }

Status Codes

200 OK — Gradebook returned
401 Unauthorized
403 Forbidden

Single grade item with all student grade records.

/api/v1/grade-items/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": { "id": "g2", "course_id": "course1", "activity_id": "a6", "activity_name": "Assignment 1: FizzBuzz", "activity_type": "assignment", "grade_max": 50, "grades": [ { "id": "sg6", "student_id": "p1", "student_name": "Alice Thompson", "grade": 48, "percentage": 96, "feedback": "Excellent work!", "submitted_date": "2026-02-07", "status": "graded" }, { "id": "sg9", "student_id": "p4", "student_name": "David Kim", "grade": 22, "percentage": 44, "status": "late" } ] } }

Status Codes

200 OK — Grade item returned
401 Unauthorized
404 Not Found

Record or update a student grade with optional feedback.

/api/v1/grade-items/{id}/grades
Admin Instructor

Request Body

{ "student_id": "p4", "grade": 75, "feedback": "Good improvement, keep it up!", "graded_by": "user1" }

Response · 200 / 201

{ "message": "Grade submitted.", "data": { "grade_item_id": "g2", "student_id": "p4", "grade": 75, "percentage": 150, "feedback": "Good improvement, keep it up!" } }

Status Codes

201 Created — Grade recorded
401 Unauthorized
403 Forbidden
422 Unprocessable Entity — Grade exceeds grade_max

All grades for one student across all grade items in a course.

/api/v1/courses/{id}/grades/student/{studentId}
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "grade_item_id": "g1", "activity_name": "Quiz 1: Python Basics", "grade": 92, "percentage": 92, "grade_max": 100, "status": "graded", "submitted_date": "2026-02-01" }, { "grade_item_id": "g2", "activity_name": "Assignment 1: FizzBuzz", "grade": 48, "percentage": 96, "grade_max": 50, "status": "graded" } ], "course_id": "course1", "student_id": "p1" }

Status Codes

200 OK — Grades returned
401 Unauthorized
403 Forbidden — Students can only view own grades

Categories

Hierarchical course categories with parent/child nesting.

All categories with parent/child hierarchy and course counts.

/api/v1/categories
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "cat1", "name": "Computer Science", "description": "CS and programming courses", "parent_id": null, "id_number": "CS001", "course_count": 8, "child_count": 2 }, { "id": "cat2", "name": "Web Development", "description": "Frontend and backend development", "parent_id": "cat1", "id_number": "CS-WEB", "course_count": 4 }, { "id": "cat4", "name": "Mathematics", "parent_id": null, "course_count": 5 }, { "id": "cat6", "name": "Business", "parent_id": null, "course_count": 6 } ] }

Status Codes

200 OK — Categories returned
401 Unauthorized

Create a new top-level or nested category.

/api/v1/categories
Admin

Request Body

{ "name": "Artificial Intelligence", "description": "AI and ML fundamentals", "parent_id": "cat1", "id_number": "CS-AI" }

Response · 200 / 201

{ "message": "Category created.", "data": { "id": "cat8", "name": "Artificial Intelligence", "parent_id": "cat1", "id_number": "CS-AI", "course_count": 0 } }

Status Codes

201 Created — Category created
401 Unauthorized
403 Forbidden — Admin only
422 Unprocessable Entity

Update name, description, or parent.

/api/v1/categories/{id}
Admin

Request Body

{ "name": "AI & Machine Learning", "description": "Comprehensive AI track", "parent_id": "cat1" }

Response · 200 / 201

{ "message": "Category updated.", "data": { "id": "cat8", "name": "AI & Machine Learning" } }

Status Codes

200 OK — Updated
401 Unauthorized
403 Forbidden
404 Not Found

Remove category. Returns 422 if courses are still assigned.

/api/v1/categories/{id}
Admin

Request Body

No request body required

Response · 200 / 201

{ "message": "Category deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
403 Forbidden
404 Not Found
422 Unprocessable Entity — Courses still assigned to category

Notifications

In-app notifications for the authenticated user.

All notifications, newest first, with unread count.

/api/v1/notifications
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "n1", "user_id": "user1", "title": "Quiz Submission", "message": "Alice Thompson submitted Quiz 1: Python Basics", "timestamp": "2 minutes ago", "read": false, "type": "info" }, { "id": "n2", "user_id": "user1", "title": "Assignment Due Soon", "message": "Assignment 1: FizzBuzz is due in 24 hours", "timestamp": "1 hour ago", "read": false, "type": "warning" }, { "id": "n3", "title": "New Enrollment", "message": "5 new students enrolled in Introduction to Python", "type": "success", "read": false } ], "unread_count": 3 }

Status Codes

200 OK — Notifications returned
401 Unauthorized

Mark a single notification as read.

/api/v1/notifications/{id}/read
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "message": "Notification marked as read.", "id": "n1" }

Status Codes

200 OK — Marked read
401 Unauthorized
404 Not Found

Mark every unread notification as read.

/api/v1/notifications/mark-all-read
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "message": "All notifications marked as read." }

Status Codes

200 OK — All marked read
401 Unauthorized

Permanently delete a notification.

/api/v1/notifications/{id}
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "message": "Notification deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

Messaging

One-to-one conversation threads between platform users.

All conversations, sorted by latest message.

/api/v1/conversations
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "conv1", "owner_user_id": "user1", "participant_user_id": "p1", "participant_name": "Alice Thompson", "participant_role": "Student", "last_message": "Thank you for the feedback on my assignment!", "last_message_time": "10:32 AM", "unread_count": 2, "course_id": "course1" }, { "id": "conv2", "participant_name": "Bob Martinez", "last_message": "When is the next quiz scheduled?", "unread_count": 1 } ] }

Status Codes

200 OK — Conversations returned
401 Unauthorized

Start a new one-to-one thread.

/api/v1/conversations
Admin Instructor Student

Request Body

{ "recipient_id": "p1", "message": "Hi Alice, I reviewed your assignment. Great work overall!" }

Response · 200 / 201

{ "message": "Conversation created.", "data": { "id": "conv4", "recipient_id": "p1", "message": "Hi Alice, I reviewed your assignment. Great work overall!" } }

Status Codes

201 Created — Conversation created
401 Unauthorized
422 Unprocessable Entity

All messages in a thread, chronological order.

/api/v1/conversations/{id}/messages
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "m1", "conversation_id": "conv1", "sender_id": "user1", "sender_name": "Dr. Sarah Johnson", "content": "Hi Alice, I reviewed your assignment. Great work overall!", "timestamp": "10:15 AM", "read": true }, { "id": "m2", "sender_id": "p1", "sender_name": "Alice Thompson", "content": "Thank you so much! I worked really hard on it.", "timestamp": "10:20 AM", "read": true }, { "id": "m4", "sender_id": "p1", "content": "Thank you for the feedback on my assignment!", "timestamp": "10:32 AM", "read": false } ], "conversation_id": "conv1" }

Status Codes

200 OK — Messages returned
401 Unauthorized
403 Forbidden — Not a participant
404 Not Found

Post a new message to a conversation.

/api/v1/conversations/{id}/messages
Admin Instructor Student

Request Body

{ "message": "Section 3 feedback: please expand your error handling." }

Response · 200 / 201

{ "message": "Message sent.", "data": { "conversation_id": "conv1", "message": "Section 3 feedback: please expand your error handling." } }

Status Codes

201 Created — Message sent
401 Unauthorized
403 Forbidden
404 Not Found

Mark all unread messages in a conversation as read.

/api/v1/conversations/{id}/read
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "message": "Messages marked as read.", "conversation_id": "conv1" }

Status Codes

200 OK — Marked read
401 Unauthorized
404 Not Found

Quiz & Question Bank

Questions (8 types) and answer options with grade fractions.

All questions in the question bank for a quiz activity.

/api/v1/activities/{id}/questions
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "qq1", "activity_id": "a4", "type": "multiple_choice", "question_text": "Which of the following is the correct way to declare a variable in Python?", "category": "Python Basics", "default_mark": 1, "shuffle_answers": true, "penalty": 0 }, { "id": "qq2", "type": "true_false", "question_text": "Python is a statically typed programming language.", "correct_answer": "False", "default_mark": 1 } ], "activity_id": "a4" }

Status Codes

200 OK — Questions returned
401 Unauthorized
404 Not Found

Add a question. Types: multiple_choice | true_false | matching | short_answer | numerical | essay | calculated | drag_drop.

/api/v1/activities/{id}/questions
Admin Instructor

Request Body

{ "type": "multiple_choice", "question_text": "What is a Python list comprehension?", "category": "Python Basics", "default_mark": 1, "shuffle_answers": true, "penalty": 0 }

Response · 200 / 201

{ "message": "Question created.", "data": { "id": "qq9", "activity_id": "a4", "type": "multiple_choice", "question_text": "What is a Python list comprehension?" } }

Status Codes

201 Created — Question created
401 Unauthorized
422 Unprocessable Entity — Invalid type

Edit question text, marks, shuffle, or penalty.

/api/v1/questions/{id}
Admin Instructor

Request Body

{ "question_text": "Which keyword is used to define a function in Python?", "default_mark": 2, "shuffle_answers": true }

Response · 200 / 201

{ "message": "Question updated.", "data": { "id": "qq1", "question_text": "Which keyword is used to define a function in Python?", "default_mark": 2 } }

Status Codes

200 OK — Updated
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Remove a question and all its answer options.

/api/v1/questions/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Question deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

All answer options with grade fractions. grade_fraction: 1.0 = correct, 0 = wrong, negative = penalty.

/api/v1/questions/{id}/answers
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "qa1", "question_id": "qq1", "text": "x = 10", "grade_fraction": 1, "feedback": "Correct! Standard Python variable assignment." }, { "id": "qa2", "text": "int x = 10;", "grade_fraction": 0, "feedback": "Incorrect. That is Java\/C# syntax." }, { "id": "qa3", "text": "var x = 10", "grade_fraction": 0, "feedback": "Incorrect. That is JavaScript." } ], "question_id": "qq1" }

Status Codes

200 OK — Answers returned
401 Unauthorized
404 Not Found

Add an answer option with grade fraction and optional feedback.

/api/v1/questions/{id}/answers
Admin Instructor

Request Body

{ "answer_text": "def", "grade_fraction": 1, "feedback": "Correct! def is used to define functions in Python.", "sort_order": 0 }

Response · 200 / 201

{ "message": "Answer created.", "data": { "id": "qa16", "question_id": "qq1", "answer_text": "def", "grade_fraction": 1 } }

Status Codes

201 Created — Answer created
401 Unauthorized
422 Unprocessable Entity — grade_fraction out of -1 to 1 range

Assignments

Student submissions with grading, late detection, and multi-attempt support.

All submissions for an assignment activity, with student details.

/api/v1/activities/{id}/submissions
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "sub1", "activity_id": "a6", "student_id": "p1", "student": { "id": "p1", "name": "Alice Thompson" }, "status": "graded", "submission_text": "def fizzbuzz()...", "file_path": null, "submitted_at": "2026-02-07T09:30:00Z", "grade": 48, "graded_at": "2026-02-08T14:00:00Z", "feedback": "Excellent work!", "attempt_number": 1, "late": false } ], "activity_id": "a6" }

Status Codes

200 OK — Submissions returned
401 Unauthorized
404 Not Found

Submit text or file for an assignment. Auto-detects late submissions.

/api/v1/activities/{id}/submissions
Student

Request Body

{ "submission_text": "def fizzbuzz(n):\n for i in range(1,n+1):\n ...", "file_path": null, "file_name": null }

Response · 200 / 201

{ "message": "Submission created.", "data": { "id": "sub5", "activity_id": "a6", "student_id": "p1", "status": "submitted", "submitted_at": "2026-02-07T09:30:00Z", "attempt_number": 1, "late": false } }

Status Codes

201 Created — Submitted
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Full detail for a single submission with grader info.

/api/v1/submissions/{id}
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": { "id": "sub1", "activity_id": "a6", "student_id": "p1", "student": { "id": "p1", "name": "Alice Thompson" }, "grader": { "id": "user1", "name": "Dr. Sarah Johnson" }, "status": "graded", "submission_text": "def fizzbuzz()...", "grade": 48, "feedback": "Excellent work!", "submitted_at": "2026-02-07T09:30:00Z", "graded_at": "2026-02-08T14:00:00Z" } }

Status Codes

200 OK — Submission returned
401 Unauthorized
404 Not Found

Instructor grades a submission with score and feedback.

/api/v1/submissions/{id}/grade
Admin Instructor

Request Body

{ "grade": 48, "feedback": "Excellent implementation of FizzBuzz. Clean code." }

Response · 200 / 201

{ "message": "Submission graded.", "data": { "id": "sub1", "grade": 48, "feedback": "Excellent implementation of FizzBuzz. Clean code.", "graded_by": "user1", "graded_at": "2026-02-08T14:00:00Z", "status": "graded" } }

Status Codes

200 OK — Graded
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Attendance

Session-based attendance tracking with per-student status and bulk recording.

All sessions for an attendance activity, with log counts.

/api/v1/activities/{id}/attendance-sessions
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "sess1", "activity_id": "a10", "course_id": "course1", "title": "Week 1 Lecture", "session_date": "2026-01-20T09:00:00Z", "duration_minutes": 60, "status": "open", "logs_count": 28 } ], "activity_id": "a10" }

Status Codes

200 OK — Sessions returned
401 Unauthorized
404 Not Found

Create a new attendance session.

/api/v1/activities/{id}/attendance-sessions
Admin Instructor

Request Body

{ "title": "Week 2 Lecture", "session_date": "2026-01-27T09:00:00Z", "duration_minutes": 90, "description": "Introduction to Control Flow" }

Response · 200 / 201

{ "message": "Session created.", "data": { "id": "sess2", "activity_id": "a10", "title": "Week 2 Lecture", "session_date": "2026-01-27T09:00:00Z", "status": "open" } }

Status Codes

201 Created — Session created
401 Unauthorized
422 Unprocessable Entity

Attendance logs for a specific session with student details.

/api/v1/attendance-sessions/{id}/logs
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "log1", "session_id": "sess1", "student_id": "p1", "student": { "id": "p1", "name": "Alice Thompson" }, "status": "present", "remarks": null, "taken_by": "user1" }, { "id": "log2", "student_id": "p4", "student": { "id": "p4", "name": "David Kim" }, "status": "absent", "remarks": "Notified via email" } ], "session_id": "sess1" }

Status Codes

200 OK — Logs returned
401 Unauthorized
404 Not Found

Record or update a single student's attendance. Status: present | absent | late | excused.

/api/v1/attendance-sessions/{id}/logs
Admin Instructor

Request Body

{ "student_id": "p1", "status": "present", "remarks": null }

Response · 200 / 201

{ "message": "Attendance recorded.", "data": { "id": "log1", "session_id": "sess1", "student_id": "p1", "status": "present" } }

Status Codes

200 OK — Recorded
401 Unauthorized
422 Unprocessable Entity

Record attendance for multiple students at once.

/api/v1/attendance-sessions/{id}/logs/bulk
Admin Instructor

Request Body

{ "records": [ { "student_id": "p1", "status": "present" }, { "student_id": "p4", "status": "absent", "remarks": "Sick leave" }, { "student_id": "p7", "status": "late" } ] }

Response · 200 / 201

{ "message": "Bulk attendance recorded.", "data": [ { "id": "log1", "student_id": "p1", "status": "present" }, { "id": "log2", "student_id": "p4", "status": "absent" }, { "id": "log3", "student_id": "p7", "status": "late" } ] }

Status Codes

200 OK — Bulk recorded
401 Unauthorized
422 Unprocessable Entity

Book

Multi-page book resource with ordered chapters and sub-chapters.

All chapters in a book activity ordered by sort_order.

/api/v1/activities/{id}/chapters
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "ch1", "activity_id": "a11", "title": "1. Getting Started", "content": "<p>Welcome to Python...<\/p>", "sort_order": 0, "sub_chapter": false, "hidden": false }, { "id": "ch2", "title": "1.1 Installing Python", "content": "<p>Download from python.org...<\/p>", "sort_order": 1, "sub_chapter": true, "hidden": false } ], "activity_id": "a11" }

Status Codes

200 OK — Chapters returned
401 Unauthorized
404 Not Found

Add a new chapter or sub-chapter.

/api/v1/activities/{id}/chapters
Admin Instructor

Request Body

{ "title": "2. Variables and Data Types", "content": "<p>In Python, variables are dynamically typed...<\/p>", "sub_chapter": false }

Response · 200 / 201

{ "message": "Chapter created.", "data": { "id": "ch3", "activity_id": "a11", "title": "2. Variables and Data Types", "sort_order": 2, "sub_chapter": false } }

Status Codes

201 Created — Chapter created
401 Unauthorized
422 Unprocessable Entity

Edit a chapter title, content, or visibility.

/api/v1/chapters/{id}
Admin Instructor

Request Body

{ "title": "1. Getting Started with Python", "content": "<p>Updated introduction...<\/p>", "hidden": false }

Response · 200 / 201

{ "message": "Chapter updated.", "data": { "id": "ch1", "title": "1. Getting Started with Python" } }

Status Codes

200 OK — Updated
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Remove a chapter.

/api/v1/chapters/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Chapter deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

Checklist

Task checklist with required/optional items for student self-tracking.

All items in a checklist, ordered by sort_order.

/api/v1/activities/{id}/checklist-items
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "cli1", "activity_id": "a12", "text": "Read Chapter 1", "is_required": true, "checked_by_default": false, "sort_order": 0 }, { "id": "cli2", "text": "Watch introductory video", "is_required": false, "sort_order": 1 }, { "id": "cli3", "text": "Complete pre-quiz", "is_required": true, "sort_order": 2 } ], "activity_id": "a12" }

Status Codes

200 OK — Items returned
401 Unauthorized
404 Not Found

Add a new checklist item.

/api/v1/activities/{id}/checklist-items
Admin Instructor

Request Body

{ "text": "Submit assignment draft", "is_required": true, "checked_by_default": false }

Response · 200 / 201

{ "message": "Checklist item created.", "data": { "id": "cli4", "activity_id": "a12", "text": "Submit assignment draft", "is_required": true, "sort_order": 3 } }

Status Codes

201 Created — Item created
401 Unauthorized
422 Unprocessable Entity

Edit a checklist item text or properties.

/api/v1/checklist-items/{id}
Admin Instructor

Request Body

{ "text": "Read Chapter 1 and 2", "is_required": true }

Response · 200 / 201

{ "message": "Checklist item updated.", "data": { "id": "cli1", "text": "Read Chapter 1 and 2", "is_required": true } }

Status Codes

200 OK — Updated
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Remove a checklist item.

/api/v1/checklist-items/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Checklist item deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

Choice (Poll)

Single-choice polling activity with real-time result aggregation.

All options with response counts.

/api/v1/activities/{id}/choice-options
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "co1", "activity_id": "a13", "option_text": "Python", "max_responses": null, "sort_order": 0, "responses_count": 18 }, { "id": "co2", "option_text": "JavaScript", "sort_order": 1, "responses_count": 12 }, { "id": "co3", "option_text": "Java", "sort_order": 2, "responses_count": 8 } ], "activity_id": "a13" }

Status Codes

200 OK — Options returned
401 Unauthorized
404 Not Found

Add a poll option.

/api/v1/activities/{id}/choice-options
Admin Instructor

Request Body

{ "option_text": "Rust", "max_responses": null }

Response · 200 / 201

{ "message": "Option created.", "data": { "id": "co4", "activity_id": "a13", "option_text": "Rust", "sort_order": 3 } }

Status Codes

201 Created — Option created
401 Unauthorized
422 Unprocessable Entity

Student votes for one option. Only one vote per student allowed.

/api/v1/activities/{id}/choice-responses
Student

Request Body

{ "option_id": "co1" }

Response · 200 / 201

{ "message": "Response recorded.", "data": { "id": "cr1", "activity_id": "a13", "option_id": "co1", "student_id": "p1" } }

Status Codes

201 Created — Vote recorded
401 Unauthorized
409 Conflict — Already responded

Aggregated results with percentages.

/api/v1/activities/{id}/choice-results
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "co1", "option_text": "Python", "count": 18, "percentage": 47.4 }, { "id": "co2", "option_text": "JavaScript", "count": 12, "percentage": 31.6 }, { "id": "co3", "option_text": "Java", "count": 8, "percentage": 21.1 } ], "total_responses": 38, "activity_id": "a13" }

Status Codes

200 OK — Results returned
401 Unauthorized
404 Not Found

Certificate

Custom certificate templates with automatic or manual issuance.

Get the certificate template configuration.

/api/v1/activities/{id}/certificate
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": { "id": "ct1", "activity_id": "a14", "course_id": "course1", "name": "Python Completion Certificate", "body_html": "<h1>Certificate of Completion<\/h1>...", "orientation": "landscape", "required_activities": [ "a4", "a6" ], "min_grade": 60, "expiry_days": null }, "activity_id": "a14" }

Status Codes

200 OK — Template returned
401 Unauthorized
404 Not Found

Create or update the certificate template.

/api/v1/activities/{id}/certificate
Admin Instructor

Request Body

{ "name": "Python Completion Certificate", "body_html": "<h1>Certificate of Completion<\/h1><p>This certifies that {{student_name}} has completed {{course_name}}.<\/p>", "orientation": "landscape", "required_activities": [ "a4", "a6" ], "min_grade": 60 }

Response · 200 / 201

{ "message": "Certificate template saved.", "data": { "id": "ct1", "activity_id": "a14", "name": "Python Completion Certificate" } }

Status Codes

200 OK — Template saved
401 Unauthorized
422 Unprocessable Entity

All certificates issued for this activity.

/api/v1/activities/{id}/certificate/issues
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "ci1", "certificate_id": "ct1", "student_id": "p1", "student": { "id": "p1", "name": "Alice Thompson" }, "issued_at": "2026-06-01T10:00:00Z", "code": "ABCDEF123456", "expires_at": null } ], "activity_id": "a14" }

Status Codes

200 OK — Issues returned
401 Unauthorized
404 Not Found

Issue a certificate to a specific student.

/api/v1/activities/{id}/certificate/issue
Admin Instructor

Request Body

{ "student_id": "p1" }

Response · 200 / 201

{ "message": "Certificate issued.", "data": { "id": "ci2", "certificate_id": "ct1", "student_id": "p1", "issued_at": "2026-06-01T10:00:00Z", "code": "XYZABC789012" } }

Status Codes

201 Created — Certificate issued
401 Unauthorized
409 Conflict — Already issued
422 Unprocessable Entity

Database Activity

Collaborative structured database with custom field definitions and student entries.

All field definitions for a database activity.

/api/v1/activities/{id}/db-fields
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "df1", "activity_id": "a15", "name": "Project Title", "type": "text", "description": "Name of the project", "required": true, "sort_order": 0 }, { "id": "df2", "name": "URL", "type": "url", "required": false, "sort_order": 1 }, { "id": "df3", "name": "Category", "type": "dropdown", "options": [ "Web", "Mobile", "Data Science" ], "sort_order": 2 } ], "activity_id": "a15" }

Status Codes

200 OK — Fields returned
401 Unauthorized
404 Not Found

Add a new field definition. Types: text | number | date | url | image | file | textarea | checkbox | radio | dropdown | latlong.

/api/v1/activities/{id}/db-fields
Admin Instructor

Request Body

{ "name": "Description", "type": "textarea", "description": "Project description", "required": true }

Response · 200 / 201

{ "message": "Field created.", "data": { "id": "df4", "activity_id": "a15", "name": "Description", "type": "textarea", "required": true, "sort_order": 3 } }

Status Codes

201 Created — Field created
401 Unauthorized
422 Unprocessable Entity

Remove a field definition.

/api/v1/db-fields/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Field deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

All entries submitted to the database.

/api/v1/activities/{id}/db-entries
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "de1", "activity_id": "a15", "student_id": "p1", "student": { "id": "p1", "name": "Alice Thompson" }, "content": { "Project Title": "Python Chat Bot", "URL": "https:\/\/github.com\/alice\/chatbot", "Category": "Data Science" }, "approved": true, "approved_by": "user1" } ], "activity_id": "a15" }

Status Codes

200 OK — Entries returned
401 Unauthorized
404 Not Found

Submit a new database entry.

/api/v1/activities/{id}/db-entries
Student

Request Body

{ "content": { "Project Title": "Weather Dashboard", "URL": "https:\/\/github.com\/bob\/weather", "Category": "Web" } }

Response · 200 / 201

{ "message": "Entry created.", "data": { "id": "de2", "activity_id": "a15", "student_id": "p4", "content": { "Project Title": "Weather Dashboard" }, "approved": false } }

Status Codes

201 Created — Entry created
401 Unauthorized
422 Unprocessable Entity

Approve a student entry.

/api/v1/db-entries/{id}/approve
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Entry approved.", "data": { "id": "de2", "approved": true, "approved_by": "user1" } }

Status Codes

200 OK — Approved
401 Unauthorized
404 Not Found

Remove a database entry.

/api/v1/db-entries/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Entry deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

Feedback

Anonymous or named survey/feedback forms with multiple question types.

All questions in a feedback form.

/api/v1/activities/{id}/feedback-questions
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "fq1", "activity_id": "a16", "type": "rating", "question_text": "How would you rate this course overall?", "options": null, "required": true, "sort_order": 0 }, { "id": "fq2", "type": "multichoice", "question_text": "Which topics were most helpful?", "options": [ "Variables", "Functions", "OOP", "Error Handling" ], "required": false, "sort_order": 1 }, { "id": "fq3", "type": "textarea", "question_text": "Any additional comments?", "sort_order": 2 } ], "activity_id": "a16" }

Status Codes

200 OK — Questions returned
401 Unauthorized
404 Not Found

Add a feedback question. Types: text | textarea | numeric | multichoice | rating | info.

/api/v1/activities/{id}/feedback-questions
Admin Instructor

Request Body

{ "type": "rating", "question_text": "How clear were the instructions?", "required": true }

Response · 200 / 201

{ "message": "Question created.", "data": { "id": "fq4", "activity_id": "a16", "type": "rating", "question_text": "How clear were the instructions?", "sort_order": 3 } }

Status Codes

201 Created — Question created
401 Unauthorized
422 Unprocessable Entity

Remove a feedback question and its responses.

/api/v1/feedback-questions/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Question deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

All submitted feedback responses with student and question info.

/api/v1/activities/{id}/feedback-responses
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "fr1", "activity_id": "a16", "question_id": "fq1", "student_id": "p1", "student": { "id": "p1", "name": "Alice Thompson" }, "question": { "id": "fq1", "question_text": "How would you rate this course overall?" }, "response_value": "5" }, { "id": "fr2", "question_id": "fq2", "student_id": "p1", "response_value": "Functions,OOP" } ], "activity_id": "a16" }

Status Codes

200 OK — Responses returned
401 Unauthorized
404 Not Found

Submit all feedback answers in a single batch request.

/api/v1/activities/{id}/feedback-responses
Student

Request Body

{ "answers": [ { "question_id": "fq1", "response_value": "5" }, { "question_id": "fq2", "response_value": "Functions,OOP" }, { "question_id": "fq3", "response_value": "Great course, very well structured!" } ] }

Response · 200 / 201

{ "message": "Feedback submitted.", "data": [ { "id": "fr4", "question_id": "fq1", "response_value": "5" }, { "id": "fr5", "question_id": "fq2", "response_value": "Functions,OOP" }, { "id": "fr6", "question_id": "fq3", "response_value": "Great course, very well structured!" } ] }

Status Codes

201 Created — Feedback submitted
401 Unauthorized
422 Unprocessable Entity

Folder

Collection of file resources grouped together.

All files in a folder activity.

/api/v1/activities/{id}/folder-files
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "ff1", "activity_id": "a17", "file_name": "Week1_Slides.pdf", "file_path": "\/storage\/courses\/course1\/Week1_Slides.pdf", "file_size": 2048576, "mime_type": "application\/pdf", "sort_order": 0 }, { "id": "ff2", "file_name": "Exercise_Sheet.docx", "file_size": 45000, "sort_order": 1 } ], "activity_id": "a17" }

Status Codes

200 OK — Files returned
401 Unauthorized
404 Not Found

Add a file reference to a folder.

/api/v1/activities/{id}/folder-files
Admin Instructor

Request Body

{ "file_name": "Supplementary_Reading.pdf", "file_path": "\/storage\/courses\/course1\/Supplementary_Reading.pdf", "file_size": 1536000, "mime_type": "application\/pdf" }

Response · 200 / 201

{ "message": "File added to folder.", "data": { "id": "ff3", "activity_id": "a17", "file_name": "Supplementary_Reading.pdf", "sort_order": 2 } }

Status Codes

201 Created — File added
401 Unauthorized
422 Unprocessable Entity

Remove a file from a folder.

/api/v1/folder-files/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "File removed from folder." }

Status Codes

200 OK — Removed
401 Unauthorized
404 Not Found

Forum

Discussion forum with threaded posts, pinning, and locking.

All discussion threads, pinned first, then by latest update.

/api/v1/activities/{id}/discussions
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "disc1", "activity_id": "a18", "course_id": "course1", "user_id": "user1", "user": { "id": "user1", "name": "Dr. Sarah Johnson" }, "title": "Welcome & Introductions", "pinned": true, "locked": false, "post_count": 15, "posts_count": 15 }, { "id": "disc2", "user_id": "p1", "user": { "id": "p1", "name": "Alice Thompson" }, "title": "Help with list comprehensions", "pinned": false, "locked": false, "posts_count": 8 } ], "activity_id": "a18" }

Status Codes

200 OK — Discussions returned
401 Unauthorized
404 Not Found

Create a new discussion thread with an initial post.

/api/v1/activities/{id}/discussions
Admin Instructor Student

Request Body

{ "title": "Best practices for error handling?", "content": "I wanted to discuss different approaches to error handling in Python...", "pinned": false }

Response · 200 / 201

{ "message": "Discussion created.", "data": { "id": "disc3", "activity_id": "a18", "title": "Best practices for error handling?", "user_id": "p4", "post_count": 1 } }

Status Codes

201 Created — Discussion created
401 Unauthorized
422 Unprocessable Entity

All posts in a discussion thread, chronological.

/api/v1/discussions/{id}/posts
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "fp1", "discussion_id": "disc1", "user_id": "user1", "user": { "id": "user1", "name": "Dr. Sarah Johnson" }, "subject": "Welcome & Introductions", "content": "Welcome to the Python course! Please introduce yourselves.", "parent_id": null, "created_at": "2026-01-15T10:00:00Z" }, { "id": "fp2", "user_id": "p1", "user": { "id": "p1", "name": "Alice Thompson" }, "content": "Hi everyone! Excited to learn Python.", "parent_id": "fp1", "created_at": "2026-01-15T10:15:00Z" } ], "discussion_id": "disc1" }

Status Codes

200 OK — Posts returned
401 Unauthorized
404 Not Found

Post a reply to a discussion. Optional parent_id for nested replies.

/api/v1/discussions/{id}/posts
Admin Instructor Student

Request Body

{ "content": "Try using try\/except blocks with specific exception types.", "parent_id": "fp1" }

Response · 200 / 201

{ "message": "Reply posted.", "data": { "id": "fp5", "discussion_id": "disc1", "user_id": "p4", "content": "Try using try\/except blocks...", "parent_id": "fp1" } }

Status Codes

201 Created — Reply posted
401 Unauthorized
403 Forbidden — Discussion is locked
422 Unprocessable Entity

Lock or unlock a discussion to prevent/allow further posts.

/api/v1/discussions/{id}/lock
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Discussion locked.", "data": { "id": "disc1", "locked": true } }

Status Codes

200 OK — Toggled
401 Unauthorized
404 Not Found

Pin or unpin a discussion to the top of the list.

/api/v1/discussions/{id}/pin
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Discussion pinned.", "data": { "id": "disc1", "pinned": true } }

Status Codes

200 OK — Toggled
401 Unauthorized
404 Not Found

Glossary

Collaborative glossary of terms with approval workflow.

All glossary entries sorted alphabetically by concept.

/api/v1/activities/{id}/glossary-entries
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "ge1", "activity_id": "a19", "user_id": "p1", "user": { "id": "p1", "name": "Alice Thompson" }, "concept": "Algorithm", "definition": "A step-by-step procedure for solving a problem or accomplishing a task.", "aliases": "algo", "approved": true, "approved_by": "user1" }, { "id": "ge2", "concept": "Variable", "definition": "A named storage location in memory.", "approved": false } ], "activity_id": "a19" }

Status Codes

200 OK — Entries returned
401 Unauthorized
404 Not Found

Add a new glossary term. Pending approval by default.

/api/v1/activities/{id}/glossary-entries
Admin Instructor Student

Request Body

{ "concept": "Recursion", "definition": "A technique where a function calls itself to solve smaller instances of the same problem.", "aliases": "recursive function" }

Response · 200 / 201

{ "message": "Entry created.", "data": { "id": "ge3", "activity_id": "a19", "concept": "Recursion", "approved": false } }

Status Codes

201 Created — Entry created
401 Unauthorized
422 Unprocessable Entity

Edit a glossary entry.

/api/v1/glossary-entries/{id}
Admin Instructor Student

Request Body

{ "concept": "Algorithm", "definition": "A finite sequence of well-defined instructions for solving a class of problems." }

Response · 200 / 201

{ "message": "Entry updated.", "data": { "id": "ge1", "concept": "Algorithm" } }

Status Codes

200 OK — Updated
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Approve a student-submitted glossary entry.

/api/v1/glossary-entries/{id}/approve
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Entry approved.", "data": { "id": "ge2", "approved": true, "approved_by": "user1" } }

Status Codes

200 OK — Approved
401 Unauthorized
404 Not Found

Remove a glossary entry.

/api/v1/glossary-entries/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Entry deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

Lesson

Branching lesson with content pages, question pages, and navigation jumps.

All pages in a lesson ordered by sort_order.

/api/v1/activities/{id}/lesson-pages
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "lp1", "activity_id": "a20", "title": "Introduction", "content": "<p>Welcome to this lesson on Python functions...<\/p>", "page_type": "content", "sort_order": 0, "jumps": null }, { "id": "lp2", "title": "What is a function?", "content": "<p>A function is a reusable block of code...<\/p>", "page_type": "question", "sort_order": 1, "jumps": [ { "answer": "def", "jump_to": "lp3" }, { "answer": "var", "jump_to": "lp1" } ] }, { "id": "lp3", "title": "Summary", "page_type": "end", "sort_order": 2 } ], "activity_id": "a20" }

Status Codes

200 OK — Pages returned
401 Unauthorized
404 Not Found

Add a new page. Types: content | question | branch | end.

/api/v1/activities/{id}/lesson-pages
Admin Instructor

Request Body

{ "title": "Practice Exercise", "content": "<p>Write a function that calculates factorial...<\/p>", "page_type": "content", "jumps": null }

Response · 200 / 201

{ "message": "Page created.", "data": { "id": "lp4", "activity_id": "a20", "title": "Practice Exercise", "page_type": "content", "sort_order": 3 } }

Status Codes

201 Created — Page created
401 Unauthorized
422 Unprocessable Entity

Edit a lesson page content, title, or jump logic.

/api/v1/lesson-pages/{id}
Admin Instructor

Request Body

{ "title": "Introduction to Functions", "content": "<p>Updated content...<\/p>", "jumps": [ { "answer": "correct", "jump_to": "lp3" } ] }

Response · 200 / 201

{ "message": "Page updated.", "data": { "id": "lp1", "title": "Introduction to Functions" } }

Status Codes

200 OK — Updated
401 Unauthorized
404 Not Found
422 Unprocessable Entity

Remove a lesson page.

/api/v1/lesson-pages/{id}
Admin Instructor

Request Body

No request body required

Response · 200 / 201

{ "message": "Page deleted." }

Status Codes

200 OK — Deleted
401 Unauthorized
404 Not Found

SCORM

SCORM 1.2/2004 package tracking with per-student attempt data.

SCORM tracking records. Filter by ?student_id= for a specific learner.

/api/v1/activities/{id}/scorm-tracks
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "st1", "activity_id": "a21", "student_id": "p1", "student": { "id": "p1", "name": "Alice Thompson" }, "attempt": 1, "element": "cmi.core.lesson_status", "value": "completed", "status": "completed", "score_raw": 92, "score_max": 100, "total_time": "00:45:30" }, { "id": "st2", "student_id": "p4", "attempt": 1, "element": "cmi.core.lesson_status", "value": "incomplete", "status": "incomplete", "score_raw": 35, "score_max": 100 } ], "activity_id": "a21" }

Status Codes

200 OK — Tracks returned
401 Unauthorized
404 Not Found

Record or update a SCORM tracking element for the authenticated student.

/api/v1/activities/{id}/scorm-tracks
Student

Request Body

{ "element": "cmi.core.lesson_status", "value": "completed", "attempt": 1, "status": "completed", "score_raw": 92, "score_max": 100, "total_time": "00:45:30" }

Response · 200 / 201

{ "message": "Track recorded.", "data": { "id": "st3", "activity_id": "a21", "student_id": "p1", "element": "cmi.core.lesson_status", "value": "completed", "attempt": 1 } }

Status Codes

200 OK — Track recorded
401 Unauthorized
422 Unprocessable Entity

Summary of SCORM progress for the authenticated student.

/api/v1/activities/{id}/scorm-tracks/summary
Student

Request Body

No request body required

Response · 200 / 201

{ "activity_id": "a21", "student_id": "p1", "total_attempts": 1, "latest_status": "completed", "latest_score": 92, "score_max": 100 }

Status Codes

200 OK — Summary returned
401 Unauthorized
404 Not Found

AI Insights

GPT-powered analytics: performance, skill metrics, at-risk detection, recommendations, and question generation.

Weekly KPI trends: avg grade, completion rate, engagement score.

/api/v1/courses/{id}/ai/performance
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "ps1", "course_id": "course1", "week_label": "W1", "avg_grade": 72, "completion_rate": 88, "engagement_score": 91, "recorded_at": "2026-01-19" }, { "id": "ps5", "week_label": "W5", "avg_grade": 79, "completion_rate": 91, "engagement_score": 93 } ], "course_id": "course1" }

Status Codes

200 OK — Snapshots returned
401 Unauthorized
403 Forbidden

Radar chart data for 6 skill dimensions.

/api/v1/courses/{id}/ai/skills
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "course_id": "course1", "data": [ { "id": "sm1", "skill_label": "Quiz Performance", "score": 78, "full_mark": 100 }, { "id": "sm2", "skill_label": "Assignment Quality", "score": 82 }, { "id": "sm3", "skill_label": "Forum Participation", "score": 65 }, { "id": "sm4", "skill_label": "Completion Rate", "score": 89 }, { "id": "sm5", "skill_label": "Timeliness", "score": 72 }, { "id": "sm6", "skill_label": "Peer Collaboration", "score": 58 } ] }

Status Codes

200 OK — Metrics returned
401 Unauthorized
403 Forbidden

GPT-flagged students with risk level (high/medium/low), missed activities, grade.

/api/v1/courses/{id}/ai/at-risk
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "ar1", "student_id": "p4", "student_name": "David Kim", "progress": 23, "last_access": "5 days ago", "missed_activities": 4, "grade": 32, "risk_level": "high", "ai_recommendation": "Schedule an immediate intervention meeting." }, { "id": "ar3", "student_name": "Frank Lee", "progress": 45, "risk_level": "medium", "ai_recommendation": "Send an engagement reminder with resources." } ], "course_id": "course1" }

Status Codes

200 OK — At-risk list returned
401 Unauthorized
403 Forbidden

Pedagogical recommendations by GPT (impact: high/medium/urgent/low).

/api/v1/courses/{id}/ai/recommendations
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "rec1", "title": "Increase Quiz Frequency", "description": "Students with weekly quizzes show 23% better retention.", "impact_level": "high", "icon_name": "Zap", "color_scheme": "purple" }, { "id": "rec4", "title": "Send Engagement Reminders", "description": "4 students haven't accessed in 3+ days. Reminders reduce dropout by 40%.", "impact_level": "urgent", "color_scheme": "red" } ], "course_id": "course1" }

Status Codes

200 OK — Recommendations returned
401 Unauthorized
403 Forbidden

AI-surfaced external/internal resources for detected gaps.

/api/v1/courses/{id}/ai/content
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "cr1", "title": "Python Classes Deep Dive", "content_type": "Video", "relevance_score": 98, "source": "YouTube", "url": "https:\/\/youtube.com" }, { "id": "cr2", "title": "Object-Oriented Programming in Python", "content_type": "Article", "relevance_score": 94, "source": "Real Python" } ], "course_id": "course1" }

Status Codes

200 OK — Recommendations returned
401 Unauthorized
403 Forbidden

Trigger GPT to generate quiz questions.

/api/v1/courses/{id}/ai/generate-questions
Instructor Admin

Request Body

{ "topic": "Object-Oriented Programming", "difficulty": "Medium", "count": 4, "type": "multiple_choice" }

Response · 200 / 201

{ "message": "Question generation queued.", "course_id": "course1" }

Status Codes

200 OK — Generation queued
401 Unauthorized
403 Forbidden
422 Unprocessable Entity

List AI-generated questions filtered by status.

/api/v1/courses/{id}/ai/generated-questions
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "gq1", "topic": "Object-Oriented Programming", "question_text": "What is the difference between a class and an object in Python?", "question_type": "Essay", "difficulty": "Medium", "status": "generated", "generated_at": "2026-04-13T10:00:00Z" }, { "id": "gq2", "question_type": "Multiple Choice", "difficulty": "Easy", "status": "generated" } ], "course_id": "course1", "status_filter": "generated" }

Status Codes

200 OK — Questions returned
401 Unauthorized
403 Forbidden

Accept (added_to_bank) or dismiss an AI-generated question.

/api/v1/ai/generated-questions/{id}
Instructor Admin

Request Body

{ "status": "added_to_bank" }

Response · 200 / 201

{ "message": "Question status updated.", "id": "gq1", "status": "added_to_bank" }

Status Codes

200 OK — Status updated
401 Unauthorized
403 Forbidden
404 Not Found
422 Unprocessable Entity — Status must be added_to_bank or dismissed

Average score % per activity (horizontal bar chart).

/api/v1/courses/{id}/ai/activity-performance
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "ap1", "activity_name": "Quiz 1", "avg_score_percentage": 85, "grade_max": 100 }, { "id": "ap2", "activity_name": "Assignment 1", "avg_score_percentage": 78, "grade_max": 50 }, { "id": "ap3", "activity_name": "Quiz 2", "avg_score_percentage": 71 }, { "id": "ap4", "activity_name": "Forum", "avg_score_percentage": 90 } ], "course_id": "course1" }

Status Codes

200 OK — Data returned
401 Unauthorized
403 Forbidden

Daily active students and submission counts for the engagement chart.

/api/v1/courses/{id}/ai/engagement
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "de1", "day_label": "Mon", "active_students": 120, "submissions": 45, "week_of": "2026-04-07" }, { "id": "de2", "day_label": "Tue", "active_students": 138, "submissions": 60 }, { "id": "de4", "day_label": "Thu", "active_students": 156, "submissions": 72 }, { "id": "de6", "day_label": "Sat", "active_students": 89, "submissions": 30 } ], "course_id": "course1" }

Status Codes

200 OK — Engagement data returned
401 Unauthorized
403 Forbidden

Learner Analytics Pipeline

Full L0→L1→L2→L3→RE→IE→FL pipeline: HATC profiles, signals, risk scoring, interventions, and feedback loop.

L0 declared HATC profile, LMS flags, and drift status.

/api/v1/courses/{id}/learners/{userId}/profile
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": { "id": "lp4", "learner_id": "p4", "course_id": "course1", "primary_profile": "C", "secondary_profile": "T", "h_score": 7, "a_score": 8, "t_score": 11, "c_score": 14, "declared_preferences": [ "structured pathway", "deadline reminders" ], "lms_flags": { "structured_pathway": true, "deadline_reminders": true, "peer_review": true }, "drift_flag": true, "drift_weeks_count": 2 }, "course_id": "course1", "user_id": "p4" }

Status Codes

200 OK — Profile returned
401 Unauthorized
403 Forbidden
404 Not Found

Create or update HATC profile scores and LMS flags.

/api/v1/courses/{id}/learners/{userId}/profile
Instructor Admin Student

Request Body

{ "profile_type": "H", "h_score": 14, "a_score": 5, "t_score": 11, "c_score": 7, "declared_preferences": [ "self-directed resolution", "reflective processing" ] }

Response · 200 / 201

{ "message": "Learner profile saved.", "course_id": "course1", "user_id": "p1" }

Status Codes

200 OK — Profile saved
401 Unauthorized
422 Unprocessable Entity

L1 weekly behavioral data (login freq, time-on-task, completion rate, quiz attempts, forum posts).

/api/v1/courses/{id}/learners/{userId}/signals/behavioral
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": { "id": "bs_p4_w7", "learner_id": "p4", "week_number": 7, "login_frequency": 2, "time_on_task_hours": 1.8, "content_completion_rate": 0.55, "quiz_attempt_count": 2, "submission_timing": "late_3_5", "forum_post_count": 0, "colour_flags": { "login_frequency": "amber", "time_on_task_hours": "orange", "forum_post_rate": "red" } }, "course_id": "course1", "user_id": "p4", "week": 7 }

Status Codes

200 OK — Signals returned
401 Unauthorized
403 Forbidden

L2 weekly cognitive data (revisit_flag, score trends).

/api/v1/courses/{id}/learners/{userId}/signals/cognitive
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [], "course_id": "course1", "user_id": "p4", "week": null }

Status Codes

200 OK — Signals returned
401 Unauthorized
403 Forbidden

L3 weekly emotional data (mood_drift_flag, pulse scores, badge_earned).

/api/v1/courses/{id}/learners/{userId}/signals/emotional
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [], "course_id": "course1", "user_id": "p4", "week": null }

Status Codes

200 OK — Signals returned
401 Unauthorized
403 Forbidden

Record weekly pulse check-in: confidence and energy (1–5).

/api/v1/courses/{id}/learners/{userId}/pulse
Student

Request Body

{ "week_number": 7, "pulse_confidence": 3, "pulse_energy": 2 }

Response · 200 / 201

{ "message": "Pulse check-in recorded.", "course_id": "course1", "user_id": "p4" }

Status Codes

201 Created — Pulse recorded
401 Unauthorized
422 Unprocessable Entity — Values must be 1-5

RE risk score 0–100, tier (0=GREEN / 1=AMBER / 2=ORANGE / 3=RED), anomaly flag, signal breakdown.

/api/v1/courses/{id}/learners/{userId}/risk
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": { "final_score": 82, "tier": 3, "anomaly_flag": true, "signal_breakdown": { "behavioral": 0.667, "cognitive": 0.5, "emotional": 0.4 } }, "course_id": "course1", "user_id": "p4", "week": 7 }

Status Codes

200 OK — Risk score returned
401 Unauthorized
403 Forbidden

Paginated risk scores for all learners in a course.

/api/v1/courses/{id}/risk-scores
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "learner_id": "p4", "student_name": "David Kim", "final_score": 82, "tier": 3 }, { "learner_id": "p8", "student_name": "Henry Adams", "final_score": 76, "tier": 3 }, { "learner_id": "p6", "student_name": "Frank Lee", "final_score": 48, "tier": 1 } ], "course_id": "course1", "week": null }

Status Codes

200 OK — Risk scores returned
401 Unauthorized
403 Forbidden

All interventions triggered for a course.

/api/v1/courses/{id}/interventions
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [], "course_id": "course1" }

Status Codes

200 OK — Interventions returned
401 Unauthorized
403 Forbidden

Log a facilitator-initiated or automated intervention. Channels: lms_message | email | video_call | pastoral_referral.

/api/v1/courses/{id}/interventions
Instructor Admin

Request Body

{ "learner_id": "p4", "week_number": 7, "tier": 3, "channel": "lms_message", "template_id": "tier3-template-1", "message_body": "Hi David, I noticed you've been struggling. Let's set up a call." }

Response · 200 / 201

{ "message": "Intervention logged.", "course_id": "course1" }

Status Codes

201 Created — Intervention logged
401 Unauthorized
422 Unprocessable Entity

FL feedback-loop evaluation: T+7/T+14 score trajectory and outcome.

/api/v1/interventions/{id}/evaluation
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": null, "intervention_id": "int1" }

Status Codes

200 OK — Evaluation returned
401 Unauthorized
403 Forbidden
404 Not Found

Record T+7/T+14 score trajectory and RE calibration. Outcomes: recovered | partial_recovery | no_change | worsened | escalated.

/api/v1/interventions/{id}/evaluation
Instructor Admin

Request Body

{ "evaluated_at_week": 9, "score_before": 82, "score_at_t7": 65, "score_at_t14": 48, "outcome_label": "partial_recovery", "recovery_threshold_met": false, "model_notes": "Student responded to message but engagement still low." }

Response · 200 / 201

{ "message": "Evaluation submitted.", "intervention_id": "int1" }

Status Codes

201 Created — Evaluation submitted
401 Unauthorized
422 Unprocessable Entity

Profile drift detection history for a learner.

/api/v1/courses/{id}/learners/{userId}/drift-logs
Instructor Admin

Request Body

No request body required

Response · 200 / 201

{ "data": [], "course_id": "course1", "user_id": "p4" }

Status Codes

200 OK — Drift logs returned
401 Unauthorized
403 Forbidden

Profile & Preferences

User profile and notification preference toggles.

Full profile for the authenticated user.

/api/v1/profile
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": { "id": "user1", "name": "Dr. Sarah Johnson", "email": "sarah.johnson@university.edu", "role": "instructor", "initials": "SJ", "department": "Computer Science", "institution": "University of Technology", "country": "United States", "timezone": "America\/New_York", "language": "English", "bio": "Experienced instructor in Computer Science. PhD from MIT.", "join_date": "2019-09-01", "last_access": "Today", "enrolled_courses": 2 } }

Status Codes

200 OK — Profile returned
401 Unauthorized

Update editable fields: name, bio, department, institution, country, timezone, language.

/api/v1/profile
Admin Instructor Student

Request Body

{ "name": "Dr. Sarah Johnson", "bio": "Experienced instructor in CS. PhD from MIT. 10+ years teaching.", "department": "Computer Science", "institution": "University of Technology", "country": "United States", "timezone": "America\/New_York", "language": "English" }

Response · 200 / 201

{ "message": "Profile updated.", "data": { "id": "user1", "name": "Dr. Sarah Johnson", "bio": "Experienced instructor in CS." } }

Status Codes

200 OK — Profile updated
401 Unauthorized
422 Unprocessable Entity

All preference toggles for the user.

/api/v1/profile/preferences
Admin Instructor Student

Request Body

No request body required

Response · 200 / 201

{ "data": [ { "id": "pref1", "preference_key": "email_notifications", "preference_label": "Email notifications", "description": "Receive emails when students submit assignments", "enabled": true }, { "id": "pref2", "preference_key": "forum_subscriptions", "preference_label": "Forum subscriptions", "description": "Get notified of new forum posts in my courses", "enabled": true }, { "id": "pref3", "preference_key": "grading_reminders", "preference_label": "Grading reminders", "description": "Remind me of ungraded submissions after 48 hours", "enabled": true }, { "id": "pref4", "preference_key": "ai_suggestions", "preference_label": "AI suggestions", "description": "Show AI-generated insights and recommendations", "enabled": true } ], "user_id": "user1" }

Status Codes

200 OK — Preferences returned
401 Unauthorized

Enable/disable a preference. Keys: email_notifications | forum_subscriptions | grading_reminders | ai_suggestions.

/api/v1/profile/preferences
Admin Instructor Student

Request Body

{ "preference_key": "grading_reminders", "preference_value": false }

Response · 200 / 201

{ "message": "Preference updated.", "data": { "preference_key": "grading_reminders", "preference_value": false } }

Status Codes

200 OK — Preference updated
401 Unauthorized
422 Unprocessable Entity — Invalid preference_key