Materials
Materials are files attached to a lesson — documents, slides, images, code files, and notes. After upload, each material goes through a background RAG (Retrieval-Augmented Generation) pipeline that extracts text, chunks it, and builds an embedding index so the AI assistant can cite it during chat.
Material Entity
{
"id": "mat_789",
"title": "Lecture Slides Week 1",
"label": "SLIDE",
"visibility_state": "DRAFT",
"processing_status": "READY",
"processing_stage": "READY",
"processing_progress_percent": 100,
"summary_text": "Introduction to sorting algorithms including bubble sort and merge sort.",
"original_file_name": "week1-slides.pdf",
"mime_type": "application/pdf",
"file_size_bytes": 2048576
}
Processing Status Values
The processing_status field gives a coarse view of where the material stands:
| Status | Description |
|---|---|
PENDING | File accepted; pipeline not yet started. |
PROCESSING | Pipeline is actively running. |
READY | Pipeline completed successfully; material is searchable. |
FAILED | Pipeline encountered an unrecoverable error. |
Processing Stage Values
The processing_stage field provides fine-grained pipeline progress:
| Stage | Description |
|---|---|
QUEUED | Waiting for a pipeline worker to pick up the job. |
EXTRACTING | Extracting raw text from the file. |
CHUNKING | Splitting text into retrieval chunks. |
EMBEDDING | Generating vector embeddings for each chunk. |
FINALIZING | Writing results to the knowledge store. |
READY | All stages complete. |
FAILED | A stage failed; check server logs. |
Label Values
| Label | Description |
|---|---|
DOCUMENT | General document (PDF, DOCX, etc.). |
SLIDE | Presentation slides. |
IMAGE | Image file (PNG, JPG, etc.). |
CODE | Source code file. |
NOTES | Freeform notes (plain text, Markdown). |
Endpoints
GET /api/v1/lessons/{lessonId}/materials
List all materials for a lesson.
Authentication: Required — approved class member or global ADMIN.
Visibility:
- Students see only materials with
visibility_state: "PUBLISHED". - Teachers/Admins see all materials regardless of state.
Response: List of material objects ordered by upload time.
POST /api/v1/lessons/{lessonId}/materials
Upload a new material file to a lesson.
Authentication: Required — class TEACHER or global ADMIN.
Content-Type: multipart/form-data
Form fields:
| Field | Required | Description |
|---|---|---|
file | Yes | The file to upload. Maximum size: 30 MB. |
title | No | Display title. Defaults to the original filename (without extension). |
label | No | One of DOCUMENT, SLIDE, IMAGE, CODE, NOTES. Defaults to DOCUMENT. |
Response: Created material object with processing_status: "PENDING" and 201 Created. Background processing begins immediately after upload.
GET /api/v1/materials/{id}
Retrieve a single material including current processing status and stage.
Authentication: Required — approved class member (published only) or class TEACHER/global ADMIN.
PATCH /api/v1/materials/{id}
Update material metadata (title and/or label). Does not re-trigger processing.
Authentication: Required — class TEACHER or global ADMIN.
Request:
{
"title": "Week 1 Lecture Slides (Updated)",
"label": "SLIDE"
}
POST /api/v1/materials/{id}/publish
Publish a material, making it visible to students.
Authentication: Required — class TEACHER or global ADMIN.
Precondition: processing_status must be READY. Returns PRECONDITION_FAILED otherwise.
Request body: Empty.
POST /api/v1/materials/{id}/unpublish
Revert a published material to draft, hiding it from students.
Authentication: Required — class TEACHER or global ADMIN.
Request body: Empty.
DELETE /api/v1/materials/{id}
Soft-delete a material. The material is removed from the lesson view and excluded from RAG retrieval. The original file and embeddings are retained server-side.
Authentication: Required — class TEACHER or global ADMIN.
Response: 204 No Content.
GET /api/v1/materials/{id}/download
Download the original uploaded file.
Authentication: Required — approved class member (published materials only) or class TEACHER/global ADMIN.
Response: The raw file with appropriate Content-Type and Content-Disposition: attachment headers. The response is a direct file stream, not a JSON envelope.