Spaces:
Sleeping
π EduVerse API Documentation β Courses / Assignments / Labs
Purpose: Complete Flutter frontend integration guide. Base URL:
http://<host>:3001(default port3001) Auth: Most endpoints requireAuthorization: Bearer <JWT>header. Content-Type:application/jsonunless otherwise noted (file uploads usemultipart/form-data).
Table of Contents
- Global Information
- Enums Reference
- Courses Module
- Course Sections Module
- Course Schedules Module
- Assignments Module
- Labs Module
- Role-Based Access Matrix
- Error Handling
- Flutter Integration Tips
1. Global Information
1.1 Authentication
All authenticated endpoints require the header:
Authorization: Bearer <access_token>
The token is obtained from POST /api/auth/login.
1.2 Roles
| Role Enum Value | Display Name | Description |
|---|---|---|
student |
Student | Regular student users |
instructor |
Instructor | Faculty members |
teaching_assistant |
TA | Teaching assistants |
admin |
Admin | Administrative staff |
it_admin |
IT Admin | Full system access |
department_head |
Department Head | Department leadership |
1.3 Pagination Response Shape
All paginated endpoints return:
{
"data": [ /* array of items */ ],
"meta": {
"total": 150, // integer β total matching records
"page": 1, // integer β current page number
"limit": 20, // integer β items per page
"totalPages": 8 // integer β total number of pages
}
}
1.4 Validation Rules
The API uses class-validator with:
whitelist: trueβ unknown properties are strippedforbidNonWhitelisted: trueβ unknown properties cause 400 errortransform: trueβ query strings auto-converted to proper types
2. Enums Reference
2.1 Course Enums
CourseLevel
| Value | Description |
|---|---|
FRESHMAN |
Freshman-level course |
SOPHOMORE |
Sophomore-level course |
JUNIOR |
Junior-level course |
SENIOR |
Senior-level course |
GRADUATE |
Graduate-level course |
CourseStatus
| Value | Description |
|---|---|
ACTIVE |
Course is currently active |
INACTIVE |
Course is inactive |
ARCHIVED |
Course is archived |
SectionStatus
| Value | Description |
|---|---|
OPEN |
Section accepting enrollments |
CLOSED |
Section manually closed |
FULL |
Section at max capacity |
CANCELLED |
Section cancelled |
ScheduleType
| Value | Description |
|---|---|
LECTURE |
Lecture session |
LAB |
Laboratory session |
TUTORIAL |
Tutorial/recitation session |
EXAM |
Examination session |
DayOfWeek
| Value |
|---|
MONDAY |
TUESDAY |
WEDNESDAY |
THURSDAY |
FRIDAY |
SATURDAY |
SUNDAY |
2.2 Assignment Enums
SubmissionType
| Value | Description |
|---|---|
file |
File-based submission |
text |
Text-based submission |
link |
Link/URL submission |
multiple |
Combination of types |
AssignmentStatus
| Value | Description |
|---|---|
draft |
Not visible to students |
published |
Visible and accepting submissions |
closed |
No longer accepting submissions |
archived |
Hidden from all views |
Status Transitions:
draftβpublishedβclosedβarchived(one-way only)
SubmissionStatus
| Value | Description |
|---|---|
submitted |
Student has submitted |
graded |
Submission has been graded |
returned |
Returned to student for review |
resubmit |
Student must resubmit |
2.3 Lab Enums
LabStatus
| Value | Description |
|---|---|
draft |
Not visible to students |
published |
Visible and accepting submissions |
closed |
No longer accepting submissions |
archived |
Hidden from all views |
LabSubmissionStatus
| Value | Description |
|---|---|
submitted |
Student has submitted |
graded |
Submission has been graded |
returned |
Returned to student |
resubmit |
Student must resubmit |
LabAttendanceStatus
| Value | Description |
|---|---|
present |
Student was present |
absent |
Student was absent |
excused |
Excused absence |
late |
Student arrived late |
3. Courses Module
Base Path: /api/courses
Authentication: Courses listing/viewing endpoints are public (no auth required). Course creation/update/delete endpoints need authentication and specific roles.
3.1 List All Courses
GET /api/courses
Auth Required: β No (Public) Roles: All (public endpoint)
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
departmentId |
integer |
β | β | Filter by department ID |
level |
string |
β | β | Filter by course level enum (e.g. FRESHMAN, GRADUATE) |
status |
string |
β | β | Filter by CourseStatus enum (ACTIVE, INACTIVE, ARCHIVED) |
search |
string |
β | β | Search in course name or code (partial match) |
page |
integer |
β | 1 |
Page number (1-indexed) |
limit |
integer |
β | 20 |
Items per page (max 100) |
Response 200 OK
{
"data": [
{
"id": 1, // number β Course ID (bigint)
"departmentId": 3, // number β FK to departments
"name": "Introduction to CS", // string β Course name
"code": "CS101", // string β Unique course code
"description": "Fundamentals of...", // string | null β Description
"credits": 3, // number β Credit hours (1-6)
"level": "FRESHMAN", // string β CourseLevel enum
"syllabusUrl": "https://...", // string | null β Syllabus URL
"instructorId": 5, // number | null β Assigned instructor
"taIds": [1, 2], // number[] | null β Assigned TA IDs
"status": "ACTIVE", // string β CourseStatus enum
"createdAt": "2025-01-15T10:00:00Z", // string (ISO 8601) β Creation timestamp
"updatedAt": "2025-01-15T10:00:00Z", // string (ISO 8601) β Last update
"department": { // object β Joined department info
"id": 3,
"name": "Computer Science",
"code": "CS"
}
}
],
"meta": {
"total": 42,
"page": 1,
"limit": 20,
"totalPages": 3
}
}
3.2 Get Courses by Department
GET /api/courses/department/:deptId
Auth Required: β No (Public) Roles: All
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
deptId |
integer |
β | Department ID |
Response 200 OK
Returns an array of course objects (same shape as items in data array above, including department relation).
Error Responses
| Status | Description |
|---|---|
404 |
Department not found |
3.3 Get Course by ID
GET /api/courses/:id
Auth Required: β No (Public) Roles: All
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Course ID |
Response 200 OK
{
"id": 1,
"departmentId": 3,
"name": "Introduction to CS",
"code": "CS101",
"description": "Fundamentals of programming...",
"credits": 3,
"level": "FRESHMAN",
"syllabusUrl": "https://example.com/syllabus.pdf",
"instructorId": 5,
"taIds": [1, 2],
"status": "ACTIVE",
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T10:00:00Z",
"department": {
"id": 3,
"name": "Computer Science",
"code": "CS"
},
"prerequisites": [], // CoursePrerequisite[] β loaded relation
"sections": [], // CourseSection[] β loaded relation
"prerequisitesCount": 0, // number β count of prerequisites
"sectionsCount": 2 // number β count of active sections
}
Error Responses
| Status | Description |
|---|---|
404 |
Course not found |
3.4 Create Course
POST /api/courses
Auth Required: β
Yes
Roles: admin, it_admin, instructor
Request Body (application/json)
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
departmentId |
number |
β | Must exist | Department to assign course to |
name |
string |
β | β | Course name |
code |
string |
β | 2-10 uppercase alphanumeric (/^[A-Z0-9]{2,10}$/) |
Unique course code |
description |
string |
β | β | Course description |
credits |
integer |
β | 1β6 | Credit hours |
level |
string |
β | CourseLevel enum |
Course level |
syllabusUrl |
string |
β | Valid URL | Syllabus URL |
instructorId |
number |
β | Must reference valid user | Instructor user ID |
taIds |
number[] |
β | Array of valid user IDs | TA user IDs |
Example Request
{
"departmentId": 1,
"name": "Introduction to Computer Science",
"code": "CS101",
"description": "Fundamentals of programming and computational thinking.",
"credits": 3,
"level": "FRESHMAN",
"syllabusUrl": "https://example.com/syllabus/cs101.pdf",
"instructorId": 5,
"taIds": [10, 11]
}
Response 201 Created
Returns the created course object (same shape as Get Course by ID, without prerequisitesCount/sectionsCount).
Error Responses
| Status | Description |
|---|---|
400 |
Invalid input data / validation failure |
404 |
Department not found |
409 |
Course code already exists in department |
3.5 Update Course
PATCH /api/courses/:id
Auth Required: β
Yes
Roles: admin, it_admin, instructor
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Course ID |
Request Body (application/json) β All fields optional
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
name |
string |
β | β | Updated course name |
description |
string |
β | β | Updated description |
credits |
integer |
β | 1β6 | Updated credit hours |
level |
string |
β | CourseLevel enum |
Updated course level |
syllabusUrl |
string |
β | β | Updated syllabus URL |
status |
string |
β | CourseStatus enum |
Change course status |
instructorId |
number |
β | β | Change instructor |
taIds |
number[] |
β | β | Change TAs |
Response 200 OK
Returns the updated course object.
Error Responses
| Status | Description |
|---|---|
400 |
Invalid input data |
404 |
Course not found |
3.6 Delete Course (Soft Delete)
DELETE /api/courses/:id
Auth Required: β
Yes
Roles: admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Course ID |
Response 204 No Content
Empty body.
Error Responses
| Status | Description |
|---|---|
400 |
Cannot delete course with active enrollments |
404 |
Course not found |
3.7 Get Course Prerequisites
GET /api/courses/:id/prerequisites
Auth Required: β No (Public) Roles: All
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Course ID |
Response 200 OK
[
{
"id": 1, // number β Prerequisite record ID
"courseId": 5, // number β The course that has this prerequisite
"prerequisiteCourseId": 2, // number β The required prereq course ID
"isMandatory": true, // boolean β Whether this prereq is mandatory
"prerequisiteCourse": { // object β Joined prerequisite course info
"id": 2,
"name": "Programming Basics",
"code": "CS100",
"level": "FRESHMAN"
},
"createdAt": "2025-01-10T08:00:00Z" // string (ISO 8601)
}
]
3.8 Add Prerequisite
POST /api/courses/:id/prerequisites
Auth Required: β
Yes
Roles: admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Course ID to add prerequisite to |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
prerequisiteCourseId |
number |
β | ID of the prerequisite course |
isMandatory |
boolean |
β | Whether this prerequisite is mandatory |
Example Request
{
"prerequisiteCourseId": 2,
"isMandatory": true
}
Response 201 Created
Returns the created prerequisite record.
Error Responses
| Status | Description |
|---|---|
400 |
Circular dependency detected / Self-prerequisite |
404 |
Course or prerequisite course not found |
409 |
Prerequisite already exists |
3.9 Remove Prerequisite
DELETE /api/courses/:id/prerequisites/:prereqId
Auth Required: β
Yes
Roles: admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Course ID |
prereqId |
integer |
β | Prerequisite record ID |
Response 204 No Content
Empty body.
4. Course Sections Module
Base Path: /api/sections
4.1 Get Sections by Course
GET /api/sections/course/:courseId
Auth Required: β No (Public) Roles: All
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
courseId |
integer |
β | Course ID |
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
semesterId |
integer |
β | β | Filter by semester |
Response 200 OK
[
{
"id": 11, // number β Section ID (bigint)
"courseId": 1, // number β FK to courses
"semesterId": 1, // number β FK to semesters
"sectionNumber": "1", // string β Section number
"maxCapacity": 30, // number β Maximum students
"currentEnrollment": 25, // number β Currently enrolled
"location": "Room A101", // string | null β Room/location
"status": "OPEN", // string β SectionStatus enum
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T10:00:00Z",
"course": {
"id": 1,
"name": "Introduction to CS",
"code": "CS101"
},
"semester": {
"id": 1,
"name": "Fall 2025",
"startDate": "2025-09-01",
"endDate": "2025-12-15"
},
"schedules": [
{
"id": 1,
"dayOfWeek": "MONDAY", // DayOfWeek enum
"startTime": "09:00", // string (HH:mm)
"endTime": "10:30", // string (HH:mm)
"room": "A101", // string | null
"building": "Main Building", // string | null
"scheduleType": "LECTURE" // ScheduleType enum
}
]
}
]
4.2 Get Section by ID
GET /api/sections/:id
Auth Required: β No (Public) Roles: All
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Section ID |
Response 200 OK
Same shape as a single item from the array above (includes course, semester, schedules relations).
4.3 Create Section
POST /api/sections
Auth Required: β
Yes
Roles: admin, it_admin, instructor
Request Body
| Field | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
courseId |
number |
β | β | Must exist | Course to create section for |
semesterId |
number |
β | β | Must exist | Semester ID |
sectionNumber |
integer |
β | Auto-generated | >= 1 | Section number |
maxCapacity |
integer |
β | β | >= 1 | Maximum student capacity |
currentEnrollment |
integer |
β | 0 |
>= 0 | Current enrollment count |
location |
string |
β | null |
β | Room/location |
Example Request
{
"courseId": 1,
"semesterId": 1,
"maxCapacity": 30,
"location": "Room A101"
}
Response 201 Created
Returns the created section object.
Error Responses
| Status | Description |
|---|---|
400 |
Invalid input data |
404 |
Course or semester not found |
409 |
Section number already exists for this course/semester combo |
4.4 Update Section
PATCH /api/sections/:id
Auth Required: β
Yes
Roles: admin, it_admin, instructor (section owner)
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Section ID |
Request Body β All fields optional
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
maxCapacity |
integer |
β | >= 1, cannot be less than current enrollment | Updated max capacity |
currentEnrollment |
integer |
β | >= 0 | Updated enrollment count |
location |
string |
β | β | Updated location |
status |
string |
β | SectionStatus enum |
Change section status |
Response 200 OK
Returns the updated section object.
4.5 Update Section Enrollment Count
PATCH /api/sections/:id/enrollment
Auth Required: β
Yes
Roles: admin, it_admin, instructor
Typically called automatically by the enrollment system.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Section ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
currentEnrollment |
number |
β | New enrollment count |
Response 200 OK
Returns the updated section object with recalculated status.
5. Course Schedules Module
Base Path: /api/schedules
5.1 Get Schedules by Section
GET /api/schedules/section/:sectionId
Auth Required: β No (Public) Roles: All
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
sectionId |
integer |
β | Section ID |
Response 200 OK
[
{
"id": 1, // number β Schedule ID
"sectionId": 11, // number β FK to sections
"dayOfWeek": "MONDAY", // string β DayOfWeek enum
"startTime": "09:00", // string β HH:mm format (24-hour)
"endTime": "10:30", // string β HH:mm format (24-hour)
"room": "A101", // string | null
"building": "Main Building", // string | null
"scheduleType": "LECTURE", // string β ScheduleType enum
"createdAt": "2025-01-15T10:00:00Z"
}
]
5.2 Get Schedule by ID
GET /api/schedules/:id
Auth Required: β No (Public) Roles: All
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Schedule ID |
Response 200 OK
Returns single schedule object with section relation included.
5.3 Create Schedule
POST /api/schedules/section/:sectionId
Auth Required: β
Yes
Roles: admin, it_admin, instructor
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
sectionId |
integer |
β | Section to add schedule to |
Request Body
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
dayOfWeek |
string |
β | DayOfWeek enum |
Day of week |
startTime |
string |
β | HH:mm format 24-hour (/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/) |
Start time |
endTime |
string |
β | HH:mm format (same regex, must be after startTime) | End time |
room |
string |
β | β | Room number/name |
building |
string |
β | β | Building name |
scheduleType |
string |
β | ScheduleType enum |
Type of session |
Example Request
{
"dayOfWeek": "MONDAY",
"startTime": "09:00",
"endTime": "10:30",
"room": "A101",
"building": "Main Building",
"scheduleType": "LECTURE"
}
Response 201 Created
Returns the created schedule object.
Error Responses
| Status | Description |
|---|---|
400 |
Invalid time range (end <= start) or schedule conflict detected |
404 |
Section not found |
5.4 Delete Schedule
DELETE /api/schedules/:id
Auth Required: β
Yes
Roles: admin, it_admin, instructor
Response 204 No Content
Empty body.
6. Assignments Module
Base Path: /api/assignments
All endpoints require JWT authentication (
@UseGuards(JwtAuthGuard, RolesGuard)).
6.1 List Assignments
GET /api/assignments
Auth Required: β Yes Roles: All authenticated users
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
courseId |
integer |
β | β | Filter by course ID |
sectionId |
integer |
β | β | Filter by section ID |
status |
string |
β | β | Filter by AssignmentStatus enum (draft, published, closed, archived) |
dueBefore |
string |
β | β | Filter assignments due before this date (ISO 8601) |
dueAfter |
string |
β | β | Filter assignments due after this date (ISO 8601) |
search |
string |
β | β | Search in assignment title (partial match) |
page |
integer |
β | 1 |
Page number |
limit |
integer |
β | 10 |
Items per page |
sortBy |
string |
β | createdAt |
Sort field: dueDate, createdAt, title |
sortOrder |
string |
β | DESC |
Sort order: ASC or DESC |
Response 200 OK
{
"data": [
{
"id": 3, // number β Assignment ID (bigint)
"courseId": 1, // number β FK to courses
"title": "Homework 1 - Binary Search", // string β Assignment title
"description": "Implement binary search...", // string | null
"instructions": "Submit as .zip file...", // string | null
"maxScore": 100.00, // number (decimal) β Maximum possible score
"weight": 15.00, // number (decimal) β Weight % in final grade
"dueDate": "2025-06-15T23:59:59Z", // string | null β Due date (ISO 8601)
"availableFrom": "2025-06-01T00:00:00Z", // string | null β Available from date
"lateSubmissionAllowed": 0, // number (0 or 1) β 0=false, 1=true
"latePenaltyPercent": 10.00, // number (decimal) β Late penalty %
"submissionType": "file", // string β SubmissionType enum
"maxFileSizeMb": 10, // number β Max file size in MB
"allowedFileTypes": "[\"pdf\",\"zip\"]", // string | null β JSON string of allowed types
"status": "published", // string β AssignmentStatus enum
"createdBy": 5, // number β Creator user ID
"createdAt": "2025-06-01T08:00:00Z", // string (ISO 8601)
"updatedAt": "2025-06-01T08:00:00Z", // string (ISO 8601)
"course": { // object β Joined course info
"id": 1,
"departmentId": 3,
"name": "Introduction to CS",
"code": "CS101",
"description": "...",
"credits": 3,
"level": "FRESHMAN",
"status": "ACTIVE"
}
}
],
"meta": {
"total": 12,
"page": 1,
"limit": 10,
"totalPages": 2
}
}
6.2 Get Assignment Details
GET /api/assignments/:id
Auth Required: β Yes Roles: All authenticated users
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Response 200 OK
{
"id": 3,
"courseId": 1,
"title": "Homework 1 - Binary Search",
"description": "Implement binary search...",
"instructions": "Submit as .zip file...",
"maxScore": 100.00,
"weight": 15.00,
"dueDate": "2025-06-15T23:59:59Z",
"availableFrom": "2025-06-01T00:00:00Z",
"lateSubmissionAllowed": 0,
"latePenaltyPercent": 10.00,
"submissionType": "file",
"maxFileSizeMb": 10,
"allowedFileTypes": "[\"pdf\",\"zip\"]",
"status": "published",
"createdBy": 5,
"createdAt": "2025-06-01T08:00:00Z",
"updatedAt": "2025-06-01T08:00:00Z",
"course": { /* full course object */ },
"submissions": [
{
"id": 1, // number β Submission ID
"assignmentId": 3, // number
"userId": 57, // number β Student user ID
"submissionText": "My essay...", // string | null
"submissionLink": "https://...", // string | null
"fileId": 12, // number | null β FK to files
"submissionStatus": "submitted", // string β SubmissionStatus enum
"isLate": 0, // number (0 or 1)
"attemptNumber": 1, // number β Attempt count
"submittedAt": "2025-06-10T14:30:00Z",
"score": null, // number | null β Graded score
"feedback": null, // string | null β Grader feedback
"gradedBy": null, // number | null β Grader user ID
"gradedAt": null, // string | null β Grading timestamp
"user": {
"user_id": 57,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com"
}
}
]
}
Error Responses
| Status | Description |
|---|---|
404 |
Assignment not found |
6.3 Create Assignment
POST /api/assignments
Auth Required: β
Yes
Roles: instructor, admin
Request Body
| Field | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
courseId |
number |
β | β | Must exist | Course ID |
title |
string |
β | β | 3-200 chars | Assignment title |
description |
string |
β | null |
β | Description |
instructions |
string |
β | null |
β | Detailed instructions |
submissionType |
string |
β | file |
SubmissionType enum |
How students submit |
maxScore |
number |
β | 100 |
0-1000 | Maximum score |
weight |
number |
β | 0 |
0-100 | Weight percentage in final grade |
dueDate |
string |
β | null |
ISO 8601 datetime | Due date |
availableFrom |
string |
β | null |
ISO 8601 datetime | Available from date |
lateSubmissionAllowed |
boolean |
β | false |
β | Allow late submissions |
latePenaltyPercent |
number |
β | 0 |
0-100 | Late penalty % |
maxFileSizeMb |
number |
β | 10 |
β | Max file size in MB |
allowedFileTypes |
string |
β | null |
JSON string array | Allowed file extensions |
status |
string |
β | draft |
AssignmentStatus enum |
Initial status |
Example Request
{
"courseId": 1,
"title": "Homework 1 - Binary Search",
"description": "Implement a binary search tree with insert, delete, and search operations.",
"instructions": "Submit your code as a single .zip file. Include a README with compilation instructions.",
"submissionType": "file",
"maxScore": 100,
"weight": 15,
"dueDate": "2025-06-15T23:59:59Z",
"availableFrom": "2025-06-01T00:00:00Z",
"lateSubmissionAllowed": true,
"latePenaltyPercent": 10,
"maxFileSizeMb": 10,
"allowedFileTypes": "[\"pdf\",\"docx\",\"zip\"]",
"status": "draft"
}
Response 201 Created
Returns the created assignment with joined course relation.
6.4 Update Assignment
PATCH /api/assignments/:id
Auth Required: β
Yes
Roles: instructor, admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Request Body
All fields from CreateAssignmentDto are optional (uses PartialType).
Response 200 OK
Returns the updated assignment object.
6.5 Delete Assignment (Soft Delete)
DELETE /api/assignments/:id
Auth Required: β
Yes
Roles: instructor, admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Response 200 OK
Empty body (assignment removed).
6.6 Change Assignment Status
PATCH /api/assignments/:id/status
Auth Required: β
Yes
Roles: instructor, admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Request Body
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
status |
string |
β | Must follow: draft -> published -> closed -> archived |
New status |
WARNING β Transition rules: Only the next status in the chain is allowed. You cannot skip statuses. E.g., you cannot go from
draftdirectly toclosed.
Example Request
{
"status": "published"
}
Response 200 OK
Returns the updated assignment object.
Error Responses
| Status | Description |
|---|---|
400 |
Invalid status transition |
404 |
Assignment not found |
6.7 Submit Assignment (Student)
POST /api/assignments/:id/submit
Auth Required: β
Yes
Roles: student only
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
submissionText |
string |
β | Text content for text submissions |
fileId |
number |
β | File ID from the files module (for file submissions) |
submissionLink |
string |
β | External URL (e.g., GitHub repo link) |
At least one of
submissionText,fileId, orsubmissionLinkshould be provided.
Example Request
{
"submissionText": "This is my essay submission about data structures...",
"submissionLink": "https://github.com/student/project"
}
Response 201 Created (via POST)
{
"id": 15, // number β Submission ID
"assignmentId": 3, // number
"userId": 57, // number β From JWT
"submissionText": "This is my essay...",
"submissionLink": "https://github.com/student/project",
"fileId": null,
"submissionStatus": "submitted",
"isLate": 0, // number β 0=on-time, 1=late
"attemptNumber": 1, // number β Auto-incremented
"submittedAt": "2025-06-10T14:30:00Z",
"score": null,
"feedback": null,
"gradedBy": null,
"gradedAt": null
}
Error Responses
| Status | Description |
|---|---|
400 |
Student not enrolled in course / Late submission not allowed / Assignment not available yet |
404 |
Assignment not found |
Business Rules
- Assignment must be in
publishedstatus - If
availableFromis set, current time must be after it - If
dueDateis set and past,lateSubmissionAllowedmust betrue(otherwise 400) - Auto-marks
isLate = 1if submitted afterdueDate - Auto-increments
attemptNumber - Student must be enrolled in the assignment's course
6.8 Get My Submission (Student)
GET /api/assignments/:id/submissions/my
Auth Required: β
Yes
Roles: student only
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Response 200 OK
Returns the student's latest submission (highest attemptNumber):
{
"id": 15,
"assignmentId": 3,
"userId": 57,
"submissionText": "My submission...",
"submissionLink": null,
"fileId": 12,
"submissionStatus": "graded",
"isLate": 0,
"attemptNumber": 2,
"submittedAt": "2025-06-10T14:30:00Z",
"score": 85.00,
"feedback": "Well done! Consider improving error handling.",
"gradedBy": 5,
"gradedAt": "2025-06-12T10:00:00Z"
}
Error Responses
| Status | Description |
|---|---|
404 |
No submission found for this student/assignment |
6.9 List All Submissions (Instructor/TA/Admin)
GET /api/assignments/:id/submissions
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Response 200 OK
[
{
"id": 15,
"assignmentId": 3,
"userId": 57,
"submissionText": "My submission...",
"submissionLink": null,
"fileId": 12,
"submissionStatus": "submitted",
"isLate": 0,
"attemptNumber": 1,
"submittedAt": "2025-06-10T14:30:00Z",
"score": null,
"feedback": null,
"gradedBy": null,
"gradedAt": null,
"user": {
"user_id": 57,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com"
}
}
]
Returns submissions sorted by
submittedAtDESC.
6.10 Grade a Submission
PATCH /api/assignments/:id/submissions/:subId/grade
Auth Required: β
Yes
Roles: instructor, teaching_assistant
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
subId |
integer |
β | Submission ID |
Request Body
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
score |
number |
β | >= 0 | Numeric score |
feedback |
string |
β | β | Feedback comments |
Example Request
{
"score": 85,
"feedback": "Well done! Consider improving the conclusion."
}
Response 200 OK
{
"submissionId": 15, // number β Graded submission ID
"score": 85, // number β Score assigned
"maxScore": 100, // number β Assignment max score
"feedback": "Well done!", // string | undefined
"gradeId": 42 // number β Created grade record ID in central gradebook
}
Side effect: Also creates a grade record in the central
gradestable withgradeType = 'assignment',isPublished = true.
6.11 Upload Assignment Instruction (Google Drive)
POST /api/assignments/:id/instructions/upload
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin
Content-Type: multipart/form-data
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Form Data Fields
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
file |
binary |
β | PDF, DOCX, etc. | The instruction file |
title |
string |
β | Max 255 chars | Instruction title |
orderIndex |
integer |
β | >= 0, default 0 |
Sort order |
Response 201 Created
{
"assignmentId": 3,
"driveFile": {
"driveFileId": 123, // number β Internal drive file record ID
"driveId": "1abc...", // string β Google Drive file ID
"fileName": "HW1_Instructions_v1.pdf",
"webViewLink": "https://drive.google.com/file/d/1abc.../view",
"webContentLink": "https://drive.google.com/uc?id=1abc..."
}
}
6.12 Upload Assignment Submission (Google Drive β Student)
POST /api/assignments/:id/submissions/upload
Auth Required: β
Yes
Roles: student only
Content-Type: multipart/form-data
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Assignment ID |
Form Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
file |
binary |
β | Submission file |
submissionText |
string |
β | Notes/comments |
submissionLink |
string |
β | External link (e.g., GitHub) |
Response 201 Created
{
"submission": {
"id": 16,
"assignmentId": 3,
"userId": 57,
"submissionText": "Completed all tasks.",
"submissionLink": "https://github.com/student/project",
"fileId": null,
"submissionStatus": "submitted",
"isLate": 0,
"attemptNumber": 1,
"submittedAt": "2025-06-10T14:30:00Z",
"score": null,
"feedback": null,
"gradedBy": null,
"gradedAt": null
},
"driveFile": {
"driveFileId": 124,
"driveId": "1def...",
"fileName": "Assignment_3_Submission_20250610.zip",
"webViewLink": "https://drive.google.com/file/d/1def.../view",
"webContentLink": "https://drive.google.com/uc?id=1def..."
},
"isLate": false // boolean β Whether submission was late
}
Business Rules
Same as regular submit (section 6.7): must be published, enrolled, respects late submission rules.
7. Labs Module
Base Path: /api/labs
All endpoints require JWT authentication (
@UseGuards(JwtAuthGuard, RolesGuard)).
7.1 List Labs
GET /api/labs
Auth Required: β Yes Roles: All authenticated users
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
courseId |
integer |
β | β | Filter by course ID |
status |
string |
β | β | Filter by LabStatus enum (draft, published, closed, archived) |
page |
integer |
β | 1 |
Page number (>= 1) |
limit |
integer |
β | 20 |
Items per page (1-100) |
Response 200 OK
{
"data": [
{
"id": 1, // number β Lab ID (bigint)
"courseId": 1, // number β FK to courses
"title": "Binary Search Lab", // string β Lab title
"description": "Implement binary...", // string | null
"labNumber": 1, // number | null β Lab sequence number
"dueDate": "2026-04-15T23:59:59Z", // string | null β Due date (ISO 8601)
"availableFrom": "2026-04-01T00:00:00Z", // string | null
"maxScore": 100.00, // number (decimal) β Max score
"weight": 10.00, // number (decimal) β Weight in final grade
"status": "published", // string β LabStatus enum
"createdBy": 5, // number β Creator user ID
"createdAt": "2026-04-01T08:00:00Z",
"updatedAt": "2026-04-01T08:00:00Z",
"course": {
"id": 1,
"departmentId": 3,
"name": "Introduction to CS",
"code": "CS101"
}
}
],
"meta": {
"total": 8,
"page": 1,
"limit": 20,
"totalPages": 1
}
}
7.2 Get Lab by ID
GET /api/labs/:id
Auth Required: β Yes Roles: All authenticated users
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Response 200 OK
{
"id": 1,
"courseId": 1,
"title": "Binary Search Lab",
"description": "Implement binary search in Python",
"labNumber": 1,
"dueDate": "2026-04-15T23:59:59Z",
"availableFrom": "2026-04-01T00:00:00Z",
"maxScore": 100.00,
"weight": 10.00,
"status": "published",
"createdBy": 5,
"createdAt": "2026-04-01T08:00:00Z",
"updatedAt": "2026-04-01T08:00:00Z",
"course": { /* course object */ },
"instructions": [
{
"id": 1, // number β Instruction ID
"labId": 1, // number
"fileId": null, // number | null β FK to files
"instructionText": "Step 1: Create a new Python file", // string | null
"orderIndex": 1, // number β Sort order
"createdAt": "2026-04-01T08:00:00Z"
}
]
}
7.3 Create Lab
POST /api/labs
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Request Body
| Field | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
courseId |
integer |
β | β | Must exist | Course ID |
title |
string |
β | β | β | Lab title |
description |
string |
β | null |
β | Lab description |
labNumber |
integer |
β | null |
β | Lab sequence number |
dueDate |
string |
β | null |
ISO 8601 | Due date |
availableFrom |
string |
β | null |
ISO 8601 | Available from date |
maxScore |
number |
β | 100 |
β | Maximum score |
weight |
number |
β | 0 |
β | Weight in final grade |
status |
string |
β | draft |
LabStatus enum |
Initial status |
Example Request
{
"courseId": 1,
"title": "Binary Search Lab",
"description": "Implement binary search in Python",
"labNumber": 1,
"dueDate": "2026-04-15T23:59:59Z",
"availableFrom": "2026-04-01T00:00:00Z",
"maxScore": 100,
"weight": 10,
"status": "draft"
}
Response 201 Created
Returns the created lab object.
7.4 Update Lab
PUT /api/labs/:id
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Note: This endpoint uses PUT (full replacement), but since
UpdateLabDto extends PartialType(CreateLabDto), all fields are optional.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Request Body
All fields from CreateLabDto are optional (uses PartialType).
Response 200 OK
Returns the updated lab object.
7.5 Delete Lab
DELETE /api/labs/:id
Auth Required: β
Yes
Roles: instructor, admin, it_admin
Note: TAs cannot delete labs.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Response 204 No Content
Empty body.
7.6 Change Lab Status
PATCH /api/labs/:id/status
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
status |
string |
β | One of: draft, published, closed, archived |
Note: Unlike assignments, lab status changes do not enforce strict one-way transitions. Any valid status value can be set.
Response 200 OK
Returns the updated lab object (full Lab entity with relations).
7.7 Get Lab Instructions
GET /api/labs/:id/instructions
Auth Required: β Yes Roles: All authenticated users
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Response 200 OK
[
{
"id": 1, // number β Instruction ID
"labId": 1, // number β FK to labs
"fileId": null, // number | null β FK to files table
"instructionText": "Step 1...", // string | null β Markdown text
"orderIndex": 1, // number β Sort order (ascending)
"createdAt": "2026-04-01T08:00:00Z"
},
{
"id": 2,
"labId": 1,
"fileId": 5,
"instructionText": "See attached PDF",
"orderIndex": 2,
"createdAt": "2026-04-01T08:05:00Z"
}
]
7.8 Add Instruction to Lab
POST /api/labs/:id/instructions
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
instructionText |
string |
β | null |
Instruction content (supports markdown) |
fileId |
integer |
β | null |
FK to files table for attachment |
orderIndex |
integer |
β | 0 |
Sort order |
Example Request
{
"instructionText": "Step 1: Create a new Python file called `binary_search.py`",
"orderIndex": 1
}
Response 201 Created
Returns the created instruction object.
7.9 Submit Lab Work (Student)
POST /api/labs/:id/submit
Auth Required: β
Yes
Roles: student only
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
submissionText |
string |
β | Text/code submission content |
fileId |
integer |
β | File ID from files module |
Example Request
{
"submissionText": "def binary_search(arr, target):\n ...",
"fileId": 10
}
Response 201 Created
{
"id": 5, // number β Submission ID
"labId": 1, // number
"userId": 57, // number β From JWT
"submissionText": "def binary...", // string | null
"fileId": 10, // number | null
"submittedAt": "2026-04-10T14:30:00Z",
"isLate": false, // boolean β Auto-detected
"status": "submitted", // string β LabSubmissionStatus
"score": null, // number | null
"feedback": null, // string | null
"gradedBy": null, // number | null
"gradedAt": null // string | null
}
Business Rules
- Auto-detects late submission based on
lab.dueDate - Sets
isLate = trueif current time > dueDate
7.10 List Lab Submissions (Instructor/TA/Admin)
GET /api/labs/:id/submissions
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Response 200 OK
[
{
"id": 5,
"labId": 1,
"userId": 57,
"submissionText": "My solution...",
"fileId": 10,
"submittedAt": "2026-04-10T14:30:00Z",
"isLate": false,
"status": "submitted",
"score": null,
"feedback": null,
"gradedBy": null,
"gradedAt": null,
"user": {
"user_id": 57,
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com"
},
"file": {
"file_id": 10,
"file_name": "solution.py",
"file_path": "/uploads/...",
"mime_type": "text/x-python"
}
}
]
Sorted by
submittedAtDESC.
7.11 Get My Lab Submission (Student)
GET /api/labs/:id/submissions/my
Auth Required: β
Yes
Roles: student only
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Response 200 OK
Returns an array of the student's submissions for this lab (may have multiple), sorted by submittedAt DESC. Includes user and file relations.
[
{
"id": 5,
"labId": 1,
"userId": 57,
"submissionText": "...",
"fileId": 10,
"submittedAt": "2026-04-10T14:30:00Z",
"isLate": false,
"status": "graded",
"score": 90.00,
"feedback": "Great work!",
"gradedBy": 5,
"gradedAt": "2026-04-12T10:00:00Z",
"user": { /* student info */ },
"file": { /* file info or null */ }
}
]
Note: Unlike assignments (which returns the latest single submission), labs returns all submissions as an array.
7.12 Grade Lab Submission
PATCH /api/labs/:id/submissions/:subId/grade
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
subId |
integer |
β | Submission ID |
Request Body
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
status |
string |
β | One of: submitted, graded, returned, resubmit |
Submission status |
score |
number |
β | >= 0 | Score to assign |
feedback |
string |
β | β | Feedback for student |
Example Request
{
"status": "graded",
"score": 85,
"feedback": "Good work! Consider optimizing your code for better performance."
}
Response 200 OK
Returns the updated submission object with user, file, and grader relations:
{
"id": 5,
"labId": 1,
"userId": 57,
"submissionText": "...",
"fileId": 10,
"submittedAt": "2026-04-10T14:30:00Z",
"isLate": false,
"status": "graded",
"score": 85.00,
"feedback": "Good work!...",
"gradedBy": 5,
"gradedAt": "2026-04-12T10:00:00Z",
"user": { /* student info */ },
"file": { /* file info or null */ },
"grader": {
"user_id": 5,
"first_name": "Prof. Smith",
"last_name": "Smith",
"email": "smith@example.com"
}
}
Side effect: When
status = 'graded'andscoreis provided, automatically creates a grade record in the centralgradestable withgradeType = 'lab',isPublished = true.
7.13 Mark Lab Attendance
POST /api/labs/:id/attendance
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
userId |
integer |
β | Student user ID to mark |
attendanceStatus |
string |
β | One of: present, absent, excused, late |
notes |
string |
β | Additional notes |
Example Request
{
"userId": 57,
"attendanceStatus": "present",
"notes": "Arrived on time"
}
Response 201 Created
{
"id": 10, // number β Attendance record ID
"labId": 1, // number
"userId": 57, // number
"attendanceStatus": "present", // string β LabAttendanceStatus
"checkInTime": "2026-04-10T09:00:00Z", // string | null β Auto-set for present/late
"notes": "Arrived on time", // string | null
"markedBy": 5, // number β User who marked (from JWT)
"createdAt": "2026-04-10T09:00:00Z"
}
Business Rules
- If a record already exists for this student+lab, it updates the existing record
checkInTimeis automatically set when status ispresentorlate
7.14 Get Lab Attendance
GET /api/labs/:id/attendance
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Response 200 OK
[
{
"id": 10,
"labId": 1,
"userId": 57,
"attendanceStatus": "present",
"checkInTime": "2026-04-10T09:00:00Z",
"notes": "Arrived on time",
"markedBy": 5,
"createdAt": "2026-04-10T09:00:00Z"
}
]
Sorted by
createdAtASC.
7.15 Upload Lab Instruction (Google Drive)
POST /api/labs/:id/instructions/upload
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Content-Type: multipart/form-data
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Form Data Fields
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
file |
binary |
β | PDF, DOCX, etc. | Instruction file |
title |
string |
β | Max 255 chars | Instruction title |
orderIndex |
integer |
β | >= 0, default 0 |
Sort order |
Response 201 Created
{
"instruction": {
"id": 3,
"labId": 1,
"instructionText": "Lab 1 - Getting Started Guide",
"orderIndex": 1,
"createdAt": "2026-04-01T08:00:00Z"
},
"driveFile": {
"driveId": "1abc...",
"fileName": "Lab_1_-_Getting_Started_Guide_v1.pdf",
"webViewLink": "https://drive.google.com/file/d/1abc.../view",
"webContentLink": "https://drive.google.com/uc?id=1abc..."
}
}
7.16 Upload TA Material (Google Drive)
POST /api/labs/:id/ta-materials/upload
Auth Required: β
Yes
Roles: instructor, teaching_assistant, admin, it_admin
Content-Type: multipart/form-data
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Form Data Fields
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
file |
binary |
β | β | TA material file |
title |
string |
β | Max 255 chars | Material title |
materialType |
string |
β | One of: answer_key, grading_rubric, solution, notes |
Type of TA material |
Response 201 Created
{
"driveFile": {
"driveFileId": 125,
"driveId": "1ghi...",
"fileName": "solution_Lab_1_Answer_Key.pdf",
"webViewLink": "https://drive.google.com/file/d/1ghi.../view",
"webContentLink": "https://drive.google.com/uc?id=1ghi..."
}
}
7.17 Upload Lab Submission (Google Drive β Student)
POST /api/labs/:id/submissions/upload
Auth Required: β
Yes
Roles: student only
Content-Type: multipart/form-data
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
integer |
β | Lab ID |
Form Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
file |
binary |
β | Submission file |
submissionText |
string |
β | Notes/comments |
Response 201 Created
{
"submission": {
"id": 6,
"labId": 1,
"userId": 57,
"submissionText": "My implementation uses iterative approach",
"submittedAt": "2026-04-10T14:30:00Z",
"isLate": false,
"status": "submitted",
"score": null,
"feedback": null,
"gradedBy": null,
"gradedAt": null
},
"driveFile": {
"driveFileId": 126,
"driveId": "1jkl...",
"fileName": "Lab1_Submission_20260410.py",
"webViewLink": "https://drive.google.com/file/d/1jkl.../view",
"webContentLink": "https://drive.google.com/uc?id=1jkl..."
},
"isLate": false
}
Business Rules
- If a submission already exists for this student+lab, the existing record is updated (not duplicated)
- Auto-detects
isLatebased onlab.dueDate
8. Role-Based Access Matrix
8.1 Courses
| Endpoint | Student | Instructor | TA | Admin | IT Admin |
|---|---|---|---|---|---|
GET /api/courses (list) |
β Public | β Public | β Public | β Public | β Public |
GET /api/courses/:id (details) |
β Public | β Public | β Public | β Public | β Public |
GET /api/courses/department/:deptId |
β Public | β Public | β Public | β Public | β Public |
POST /api/courses (create) |
β | β | β | β | β |
PATCH /api/courses/:id (update) |
β | β | β | β | β |
DELETE /api/courses/:id (delete) |
β | β | β | β | β |
GET /api/courses/:id/prerequisites |
β Public | β Public | β Public | β Public | β Public |
POST /api/courses/:id/prerequisites |
β | β | β | β | β |
DELETE /api/courses/:id/prerequisites/:id |
β | β | β | β | β |
8.2 Course Sections
| Endpoint | Student | Instructor | TA | Admin | IT Admin |
|---|---|---|---|---|---|
GET /api/sections/course/:courseId |
β Public | β Public | β Public | β Public | β Public |
GET /api/sections/:id |
β Public | β Public | β Public | β Public | β Public |
POST /api/sections (create) |
β | β | β | β | β |
PATCH /api/sections/:id (update) |
β | β | β | β | β |
PATCH /api/sections/:id/enrollment |
β | β | β | β | β |
8.3 Course Schedules
| Endpoint | Student | Instructor | TA | Admin | IT Admin |
|---|---|---|---|---|---|
GET /api/schedules/section/:sectionId |
β Public | β Public | β Public | β Public | β Public |
GET /api/schedules/:id |
β Public | β Public | β Public | β Public | β Public |
POST /api/schedules/section/:sectionId |
β | β | β | β | β |
DELETE /api/schedules/:id |
β | β | β | β | β |
8.4 Assignments
| Endpoint | Student | Instructor | TA | Admin | IT Admin |
|---|---|---|---|---|---|
GET /api/assignments (list) |
β | β | β | β | β |
GET /api/assignments/:id (details) |
β | β | β | β | β |
POST /api/assignments (create) |
β | β | β | β | β |
PATCH /api/assignments/:id (update) |
β | β | β | β | β |
DELETE /api/assignments/:id (delete) |
β | β | β | β | β |
PATCH /api/assignments/:id/status |
β | β | β | β | β |
POST /api/assignments/:id/submit |
β | β | β | β | β |
GET /api/assignments/:id/submissions/my |
β | β | β | β | β |
GET /api/assignments/:id/submissions |
β | β | β | β | β |
PATCH /:id/submissions/:subId/grade |
β | β | β | β | β |
POST /:id/instructions/upload |
β | β | β | β | β |
POST /:id/submissions/upload |
β | β | β | β | β |
8.5 Labs
| Endpoint | Student | Instructor | TA | Admin | IT Admin |
|---|---|---|---|---|---|
GET /api/labs (list) |
β | β | β | β | β |
GET /api/labs/:id (details) |
β | β | β | β | β |
POST /api/labs (create) |
β | β | β | β | β |
PUT /api/labs/:id (update) |
β | β | β | β | β |
DELETE /api/labs/:id (delete) |
β | β | β | β | β |
PATCH /api/labs/:id/status |
β | β | β | β | β |
GET /api/labs/:id/instructions |
β | β | β | β | β |
POST /api/labs/:id/instructions |
β | β | β | β | β |
POST /api/labs/:id/submit |
β | β | β | β | β |
GET /api/labs/:id/submissions |
β | β | β | β | β |
GET /api/labs/:id/submissions/my |
β | β | β | β | β |
PATCH /:id/submissions/:subId/grade |
β | β | β | β | β |
POST /api/labs/:id/attendance |
β | β | β | β | β |
GET /api/labs/:id/attendance |
β | β | β | β | β |
POST /:id/instructions/upload |
β | β | β | β | β |
POST /:id/ta-materials/upload |
β | β | β | β | β |
POST /:id/submissions/upload |
β | β | β | β | β |
9. Error Handling
9.1 Standard Error Response Shape
{
"statusCode": 404,
"message": "Assignment not found",
"error": "Not Found"
}
Or for validation errors (400):
{
"statusCode": 400,
"message": [
"courseId must be a number",
"title must be longer than or equal to 3 characters"
],
"error": "Bad Request"
}
9.2 Common Error Codes
| Status | When |
|---|---|
400 |
Validation failure, invalid state transition, business rule violation |
401 |
Missing or invalid JWT token |
403 |
Insufficient role permissions |
404 |
Resource not found |
409 |
Duplicate resource (e.g., course code) |
9.3 Business Rule Errors (400)
| Module | Error | Description |
|---|---|---|
| Courses | Course code exists | CourseCodeAlreadyExistsException β code+department must be unique |
| Courses | Circular prerequisite | CircularPrerequisiteDetectedException β detected via DFS |
| Courses | Delete with sections | CannotDeleteCourseWithActiveSectionsException |
| Assignments | Not published | AssignmentNotPublishedException β must be published to submit |
| Assignments | Not available yet | AssignmentNotAvailableYetException β before availableFrom |
| Assignments | Deadline passed | SubmissionDeadlinePassedException β past dueDate and late not allowed |
| Assignments | Not enrolled | Student not enrolled in the course |
| Assignments | Invalid transition | Status transition not allowed (e.g., draft to closed) |
| Sections | Section full | SectionFullException β enrollment exceeds capacity |
| Sections | Capacity reduction | Cannot reduce capacity below current enrollment |
| Schedules | Invalid time | InvalidTimeRangeException β end time <= start time |
| Schedules | Conflict | ScheduleConflictException β room/time overlap |
10. Flutter Integration Tips
10.1 HTTP Client Setup
// Base configuration
const baseUrl = 'http://your-server:3001';
// Auth header
final headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer $accessToken',
};
10.2 Parsing lateSubmissionAllowed
The backend stores this as a MySQL TINYINT(1) β it comes back as 0 or 1 (number), not true/false:
final isLateAllowed = (assignment['lateSubmissionAllowed'] as num) == 1;
10.3 Parsing allowedFileTypes
This field is a JSON string (not an array). Parse it:
final List<String> fileTypes = assignment['allowedFileTypes'] != null
? List<String>.from(jsonDecode(assignment['allowedFileTypes']))
: [];
10.4 Decimal Fields
maxScore, weight, latePenaltyPercent, score come back as decimal numbers (may be strings from some DB drivers). Always parse:
final maxScore = double.tryParse(assignment['maxScore'].toString()) ?? 100.0;
10.5 File Uploads (multipart/form-data)
Use dio or http.MultipartRequest:
// Using Dio
final formData = FormData.fromMap({
'file': await MultipartFile.fromFile(filePath, filename: fileName),
'title': 'My submission',
'submissionText': 'Notes here',
});
final response = await dio.post(
'$baseUrl/api/assignments/3/submissions/upload',
data: formData,
options: Options(headers: {'Authorization': 'Bearer $token'}),
);
10.6 Pagination Helper
class PaginatedResponse<T> {
final List<T> data;
final int total;
final int page;
final int limit;
final int totalPages;
bool get hasNextPage => page < totalPages;
bool get hasPreviousPage => page > 1;
}
10.7 Enum Mapping
enum AssignmentStatus { draft, published, closed, archived }
extension AssignmentStatusExt on AssignmentStatus {
String get value => name; // 'draft', 'published', etc.
static AssignmentStatus fromString(String s) =>
AssignmentStatus.values.firstWhere((e) => e.name == s);
}
10.8 Date Handling
All dates are ISO 8601 strings. Parse with:
final dueDate = DateTime.parse(assignment['dueDate']); // UTC
final localDueDate = dueDate.toLocal(); // Convert to local timezone
10.9 Role-Based UI
// Show/hide actions based on role
final userRoles = currentUser.roles; // List<String>
final canCreateAssignment = userRoles.any(
(r) => ['instructor', 'admin'].contains(r),
);
final canSubmit = userRoles.contains('student');
final canGrade = userRoles.any(
(r) => ['instructor', 'teaching_assistant'].contains(r),
);
10.10 Handling isLate Differences
| Module | isLate Type |
Values |
|---|---|---|
| Assignments | number (tinyint) |
0 = on-time, 1 = late |
| Labs | boolean |
true / false |
// Assignments
final isLate = (submission['isLate'] as num) == 1;
// Labs
final isLate = submission['isLate'] as bool;
Last Updated: April 2026 Backend Framework: NestJS (TypeScript) Database: MySQL with TypeORM File Storage: Google Drive API