All routes are GET and return JSON unless otherwise noted.
Success:
{ "ok": true, "data": "..." }Error:
{ "error": { "code": "VALIDATION_ERROR", "message": "..." } }Returns courses for a department and semester.
Query parameters:
departmentIdstring, requiredsemesterIdnumber, required
Example:
GET /api/resources/courses?departmentId=ME&semesterId=4
Response data:
[
{
"courseID": "ME2001",
"courseName": "Thermodynamics",
"syllabusAssets": {
"provider": "google-drive",
"folderId": "...",
"folderUrl": "..."
}
}
]Returns available departments and semesters from courseRecords.
Query parameters:
departmentIdstring, optional (scopes semesters)
Example:
GET /api/resources/filters
GET /api/resources/filters?departmentId=ME
Response data:
{
"departments": ["CE", "ME"],
"semesters": [1, 2, 3, 4]
}Searches Drive across allowed course roots.
Query parameters:
qstring, required (min length 2)departmentIdstring, requiredsemesterIdnumber, required
Example:
GET /api/resources/search?q=notes&departmentId=ME&semesterId=4
Response data:
{
"results": [
{
"node": {
"id": "...",
"name": "Unit 1 Notes",
"type": "file",
"mimeType": "application/pdf",
"modifiedTime": "2026-01-01T00:00:00.000Z",
"size": 12345,
"tags": []
},
"resourceId": "...",
"courseId": "ME2001",
"courseName": "Thermodynamics",
"pathIds": ["..."],
"pathNames": ["Thermodynamics"]
}
],
"truncated": false
}Lists children of a Drive folder.
Query parameters:
folderIdstring, required
Example:
GET /api/resources/drive?folderId=...
Response data:
[
{
"id": "...",
"name": "Unit 1",
"type": "folder",
"mimeType": "application/vnd.google-apps.folder",
"modifiedTime": "2026-01-01T00:00:00.000Z",
"size": 12345,
"tags": []
}
]Batch read/write tags for resource IDs.
Query parameters:
idscomma-separated list of resource IDs (optional ifidis repeated)idrepeated resource IDs (optional)
Example:
GET /api/resources/tags?ids=res_1,res_2
GET /api/resources/tags?id=res_1&id=res_2
Response data:
{
"tags": {
"res_1": ["pyq", "important"],
"res_2": ["notes"]
}
}Request body:
{
"updates": [
{ "id": "res_1", "tags": ["pyq", "important"] },
{ "id": "res_2", "tags": [] }
]
}Header:
x-tags-write-token: required whenTAGS_WRITE_TOKENis configured
Response data:
{ "updated": 2 }Fetches Drive file content. Returns the raw file bytes, not JSON.
Query parameters:
fileIdstring, requiredexportstring, optional (for Google Docs export)
Example:
GET /api/resources/drive/file?fileId=...
GET /api/resources/drive/file?fileId=...&export=application/pdf
Response:
200with file bytes429if rate limited