Skip to main content

Assignments & Submissions

Assignments live inside lessons and allow teachers to collect file-based work from students. Each assignment defines accepted file types, size limits, and an optional due date. Students submit files via multipart upload and can withdraw their submission before the due date.


Assignment Entity

{
"id": "asgn_001",
"lesson_id": "les_456",
"title": "Implement Bubble Sort",
"instructions": "Write a Python function that sorts a list using bubble sort.",
"due_at": "2026-04-01T23:59:00Z",
"visibility_state": "DRAFT",
"allowed_file_types": ["py", "txt"],
"max_file_size_mb": 10,
"weight": 1.0,
"order_index": 1
}

Field notes:

  • due_at — ISO 8601 UTC timestamp. null means no due date.
  • allowed_file_types — list of file extensions (without dots) allowed for submission. Empty array means all types are accepted.
  • max_file_size_mb — per-file upload limit in megabytes.
  • weight — relative weight used when computing lesson grade averages. Default 1.0.
  • order_index — display order within the lesson.

Submission Entity

{
"id": "sub_001",
"assignment_id": "asgn_001",
"student_user_id": "usr_456",
"status": "SUBMITTED",
"is_late": false,
"submitted_at": "2026-03-30T14:22:00Z",
"files": [
{
"id": "file_001",
"original_name": "bubble_sort.py",
"mime_type": "text/x-python",
"file_size_bytes": 1024
}
]
}

status values:

StatusDescription
NOT_SUBMITTEDStudent has not yet submitted.
SUBMITTEDSubmission is active.
WITHDRAWNStudent withdrew their submission.

is_latetrue when submitted_at is after due_at. Calculated server-side.


Assignment Endpoints

GET /api/v1/lessons/{lessonId}/assignments

List all assignments for a lesson.

Authentication: Required — approved class member or global ADMIN.

Visibility:

  • Students see only published assignments.
  • Teachers/Admins see all assignments regardless of visibility_state.

Response: Ordered list of assignment objects.


POST /api/v1/lessons/{lessonId}/assignments

Create a new assignment within a lesson.

Authentication: Required — class TEACHER or global ADMIN.

Request:

{
"title": "Implement Bubble Sort",
"instructions": "Write a Python function that sorts a list using bubble sort.",
"due_at": "2026-04-01T23:59:00Z",
"allowed_file_types": ["py", "txt"],
"max_file_size_mb": 10,
"weight": 1.0,
"order_index": 1
}

Only title is required. Newly created assignments have visibility_state: "DRAFT".

Response: Created assignment object with 201 Created.


GET /api/v1/assignments/{id}

Retrieve a single assignment by ID.

Authentication: Required — approved class member (published only) or class TEACHER/global ADMIN.


PATCH /api/v1/assignments/{id}

Update assignment fields.

Authentication: Required — class TEACHER or global ADMIN.

Request: Any subset of { "title", "instructions", "due_at", "allowed_file_types", "max_file_size_mb", "weight", "order_index" }.


POST /api/v1/assignments/{id}/publish

Publish an assignment, making it visible to students.

Authentication: Required — class TEACHER or global ADMIN.

Request body: Empty.


POST /api/v1/assignments/{id}/unpublish

Revert a published assignment to draft, hiding it from students.

Authentication: Required — class TEACHER or global ADMIN.

Request body: Empty.

caution

Unpublishing an assignment with existing submissions does not delete those submissions, but students will no longer be able to see the assignment or withdraw their submission while it is in draft state.


Submission Endpoints

POST /api/v1/assignments/{assignmentId}/submit

Submit files for an assignment.

Authentication: Required — STUDENT global role with approved class membership.

Content-Type: multipart/form-data

Form fields:

FieldDescription
filesOne or more files. Each file must match allowed_file_types and max_file_size_mb.

Behavior:

  • If the student has a prior SUBMITTED submission, it is replaced by this one (re-submission).
  • is_late is set automatically by comparing submission time to due_at.

Response: Created or updated submission object with 201 Created.


POST /api/v1/submissions/{submissionId}/withdraw

Withdraw an active submission.

Authentication: Required — submission owner (student).

Precondition: The assignment must not have passed its due_at. Returns PRECONDITION_FAILED if the due date has passed.

Request body: Empty.

Response: Updated submission object with status: "WITHDRAWN".


GET /api/v1/assignments/{assignmentId}/submissions/{studentId}

Retrieve a specific student's submission for an assignment.

Authentication: Required — class TEACHER or global ADMIN.

Response: Submission object including the files array.


GET /api/v1/submissions/{submissionId}/files/{fileId}/download

Download a single submitted file.

Authentication: Required — submission owner (student) or class TEACHER/global ADMIN.

Response: Raw file stream with Content-Disposition: attachment. Not a JSON envelope.