API Reference
All endpoints live under /api/v1, return JSON, and use Laravel Sanctum tokens. Send Authorization: Bearer <token> on protected routes.
Account lifecycle — register, login, token management, and email verification.
POST
Register
/api/v1/auth/register
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
POST
Login
/api/v1/auth/login
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
POST
Forgot Password
/api/v1/auth/forgot-password
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
POST
Reset Password
/api/v1/auth/reset-password
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
GET
Verify Email
/api/v1/auth/verify-email/{id}/{hash}
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
POST
Resend Verification
/api/v1/auth/email/resend
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
GET
Current User
/api/v1/auth/me
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
POST
Logout
/api/v1/auth/logout
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
Role-specific summary views aggregating KPIs for each user type.
GET
Admin Overview
/api/v1/dashboard/admin
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
GET
Instructor Snapshot
/api/v1/dashboard/instructor
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
GET
Student Hub
/api/v1/dashboard/student
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
CRUD for courses and participant enrollment.
GET
List Courses
/api/v1/courses
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
POST
Create Course
/api/v1/courses
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
GET
Get Course
/api/v1/courses/{id}
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
PUT
Update Course
/api/v1/courses/{id}
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
DELETE
Delete Course
/api/v1/courses/{id}
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
GET
List Participants
/api/v1/courses/{id}/participants
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
POST
Enroll User
/api/v1/courses/{id}/enroll
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
DELETE
Unenroll User
/api/v1/courses/{id}/enroll/{userId}
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
POST
Self Enroll
/api/v1/courses/{id}/join
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
DELETE
Leave Course
/api/v1/courses/{id}/leave
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
Manage course sections (weeks/topics) and individual learning activities.
GET
List Sections
/api/v1/courses/{id}/sections
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
POST
Create Section
/api/v1/courses/{id}/sections
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
PUT
Update Section
/api/v1/courses/{id}/sections/{sectionId}
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
DELETE
Delete Section
/api/v1/courses/{id}/sections/{sectionId}
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
GET
List Activities
/api/v1/sections/{id}/activities
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
POST
Create Activity
/api/v1/sections/{id}/activities
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
PUT
Update Activity
/api/v1/activities/{id}
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
DELETE
Delete Activity
/api/v1/activities/{id}
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
Retrieve and submit grades for course activities.
GET
Course Gradebook
/api/v1/courses/{id}/grades
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
GET
Get Grade Item
/api/v1/grade-items/{id}
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
POST
Submit Grade
/api/v1/grade-items/{id}/grades
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
GET
Student Grades
/api/v1/courses/{id}/grades/student/{studentId}
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
Hierarchical course categories with parent/child nesting.
GET
List Categories
/api/v1/categories
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
POST
Create Category
/api/v1/categories
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
PUT
Update Category
/api/v1/categories/{id}
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
DELETE
Delete Category
/api/v1/categories/{id}
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
In-app notifications for the authenticated user.
GET
List Notifications
/api/v1/notifications
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
PATCH
Mark as Read
/api/v1/notifications/{id}/read
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
POST
Mark All Read
/api/v1/notifications/mark-all-read
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
DELETE
Delete Notification
/api/v1/notifications/{id}
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
One-to-one conversation threads between platform users.
GET
List Conversations
/api/v1/conversations
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
POST
Create Conversation
/api/v1/conversations
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
GET
Get Messages
/api/v1/conversations/{id}/messages
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
Send Message
/api/v1/conversations/{id}/messages
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
PATCH
Mark Messages Read
/api/v1/conversations/{id}/read
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
Questions (8 types) and answer options with grade fractions.
GET
List Questions
/api/v1/activities/{id}/questions
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
POST
Create Question
/api/v1/activities/{id}/questions
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
PUT
Update Question
/api/v1/questions/{id}
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
DELETE
Delete Question
/api/v1/questions/{id}
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
GET
List Answers
/api/v1/questions/{id}/answers
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
POST
Create Answer
/api/v1/questions/{id}/answers
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
Student submissions with grading, late detection, and multi-attempt support.
GET
List Submissions
/api/v1/activities/{id}/submissions
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
POST
Submit Work
/api/v1/activities/{id}/submissions
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
GET
View Submission
/api/v1/submissions/{id}
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
PUT
Grade Submission
/api/v1/submissions/{id}/grade
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
Session-based attendance tracking with per-student status and bulk recording.
GET
List Sessions
/api/v1/activities/{id}/attendance-sessions
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
POST
Create Session
/api/v1/activities/{id}/attendance-sessions
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
GET
Session Logs
/api/v1/attendance-sessions/{id}/logs
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
POST
Record Attendance
/api/v1/attendance-sessions/{id}/logs
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
POST
Bulk Record
/api/v1/attendance-sessions/{id}/logs/bulk
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
Multi-page book resource with ordered chapters and sub-chapters.
GET
List Chapters
/api/v1/activities/{id}/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
POST
Create Chapter
/api/v1/activities/{id}/chapters
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
PUT
Update Chapter
/api/v1/chapters/{id}
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
DELETE
Delete Chapter
/api/v1/chapters/{id}
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
Task checklist with required/optional items for student self-tracking.
GET
List Items
/api/v1/activities/{id}/checklist-items
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
POST
Create Item
/api/v1/activities/{id}/checklist-items
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
PUT
Update Item
/api/v1/checklist-items/{id}
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
DELETE
Delete Item
/api/v1/checklist-items/{id}
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
Single-choice polling activity with real-time result aggregation.
GET
List Options
/api/v1/activities/{id}/choice-options
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
POST
Create Option
/api/v1/activities/{id}/choice-options
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
POST
Submit Response
/api/v1/activities/{id}/choice-responses
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
GET
Poll Results
/api/v1/activities/{id}/choice-results
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
Custom certificate templates with automatic or manual issuance.
GET
View Template
/api/v1/activities/{id}/certificate
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
POST
Save Template
/api/v1/activities/{id}/certificate
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
GET
List Issues
/api/v1/activities/{id}/certificate/issues
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
POST
Issue Certificate
/api/v1/activities/{id}/certificate/issue
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
Collaborative structured database with custom field definitions and student entries.
GET
List Fields
/api/v1/activities/{id}/db-fields
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
POST
Create Field
/api/v1/activities/{id}/db-fields
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
DELETE
Delete Field
/api/v1/db-fields/{id}
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
GET
List Entries
/api/v1/activities/{id}/db-entries
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
POST
Create Entry
/api/v1/activities/{id}/db-entries
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
PATCH
Approve Entry
/api/v1/db-entries/{id}/approve
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
DELETE
Delete Entry
/api/v1/db-entries/{id}
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
Collection of file resources grouped together.
GET
List Files
/api/v1/activities/{id}/folder-files
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
POST
Add File
/api/v1/activities/{id}/folder-files
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
DELETE
Remove File
/api/v1/folder-files/{id}
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
Discussion forum with threaded posts, pinning, and locking.
GET
List Discussions
/api/v1/activities/{id}/discussions
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
POST
Start Discussion
/api/v1/activities/{id}/discussions
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
GET
List Posts
/api/v1/discussions/{id}/posts
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
Reply
/api/v1/discussions/{id}/posts
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
PATCH
Toggle Lock
/api/v1/discussions/{id}/lock
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
PATCH
Toggle Pin
/api/v1/discussions/{id}/pin
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
Collaborative glossary of terms with approval workflow.
GET
List Entries
/api/v1/activities/{id}/glossary-entries
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
POST
Create Entry
/api/v1/activities/{id}/glossary-entries
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
PUT
Update Entry
/api/v1/glossary-entries/{id}
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
PATCH
Approve Entry
/api/v1/glossary-entries/{id}/approve
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
DELETE
Delete Entry
/api/v1/glossary-entries/{id}
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
Branching lesson with content pages, question pages, and navigation jumps.
GET
List Pages
/api/v1/activities/{id}/lesson-pages
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
POST
Create Page
/api/v1/activities/{id}/lesson-pages
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
PUT
Update Page
/api/v1/lesson-pages/{id}
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
DELETE
Delete Page
/api/v1/lesson-pages/{id}
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 1.2/2004 package tracking with per-student attempt data.
GET
List Tracks
/api/v1/activities/{id}/scorm-tracks
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
POST
Record Track
/api/v1/activities/{id}/scorm-tracks
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
GET
Progress Summary
/api/v1/activities/{id}/scorm-tracks/summary
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
GPT-powered analytics: performance, skill metrics, at-risk detection, recommendations, and question generation.
GET
Performance Snapshots
/api/v1/courses/{id}/ai/performance
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
GET
Skill Metrics
/api/v1/courses/{id}/ai/skills
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
GET
At-Risk Students
/api/v1/courses/{id}/ai/at-risk
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
GET
AI Suggestions
/api/v1/courses/{id}/ai/recommendations
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
GET
Content Recommendations
/api/v1/courses/{id}/ai/content
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
POST
Generate Questions
/api/v1/courses/{id}/ai/generate-questions
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
GET
Generated Questions
/api/v1/courses/{id}/ai/generated-questions
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
PATCH
Update Question Status
/api/v1/ai/generated-questions/{id}
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
GET
Activity Performance
/api/v1/courses/{id}/ai/activity-performance
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
GET
Weekly Engagement
/api/v1/courses/{id}/ai/engagement
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.
GET
Learner Profile
/api/v1/courses/{id}/learners/{userId}/profile
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
POST
Set Learner Profile
/api/v1/courses/{id}/learners/{userId}/profile
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
GET
Behavioral Signals
/api/v1/courses/{id}/learners/{userId}/signals/behavioral
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
GET
Cognitive Signals
/api/v1/courses/{id}/learners/{userId}/signals/cognitive
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
GET
Emotional Signals
/api/v1/courses/{id}/learners/{userId}/signals/emotional
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
POST
Submit Pulse
/api/v1/courses/{id}/learners/{userId}/pulse
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
GET
Risk Score
/api/v1/courses/{id}/learners/{userId}/risk
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
GET
All Risk Scores
/api/v1/courses/{id}/risk-scores
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
GET
List Interventions
/api/v1/courses/{id}/interventions
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
POST
Create Intervention
/api/v1/courses/{id}/interventions
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
GET
Feedback Evaluation
/api/v1/interventions/{id}/evaluation
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
POST
Submit Evaluation
/api/v1/interventions/{id}/evaluation
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
GET
Drift Logs
/api/v1/courses/{id}/learners/{userId}/drift-logs
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
User profile and notification preference toggles.
GET
Get Profile
/api/v1/profile
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
PUT
Update Profile
/api/v1/profile
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
GET
Get Preferences
/api/v1/profile/preferences
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
PUT
Update Preferences
/api/v1/profile/preferences
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