Build with the data
Data reference
How the files fit together and what the fields mean. The field tables themselves are in the REST API page.
The files#
| Path | What it holds | Shape |
|---|---|---|
/api/modules/{code} | One module, in full. | A single object. |
/data/api/modules.json | Every module since AY2014, one summary row each, with its latest offering. | An object with a list called modules. |
/data/api/indexes/{year_semester}.json | Every class index in one semester. | Module code, then index number, then a list of class slots. |
/data/api/exams/{year_semester}.json | The exam timetable for one semester. | Module code, then one exam. |
Every field of each file is listed in the REST API reference. All files are served from https://ntumods.com.
Semester codes#
- A semester is written
year_semester, such as2026_2. The year is the academic year, so2026is AY2026/27. - The semester is
1,2orS(special term). Older files, up to 2021, also haveTfor the second special term. - The newest semester with classes and the newest with an exam timetable are often different. Exams are published later, so an exam file can be empty (
{}) for a new semester.
How the files join#
- The module code is the key in every file. Use it to go from a row in
modules.jsonto its class indexes and exam. - A class index is one group of classes a student picks, such as a lecture with one tutorial. It has a number, such as
10052, and a list of class slots. A student picks one index per module. - Index numbers are text and are unique within a semester, not across semesters.
Class slots#
One class slot
{ "key": "10052", "type": "LEC", "group": "SCL1", "day": 3, "time": "0930-1120", "venue": "LT3", "remarks": "Teaching Wk1-9,11-13", "duration": 4}typeisLEC,TUT,LAB,SEMand a few rarer ones such asPRJandDES.daycounts from1for Monday to6for Saturday. A few slots have0, which means online or to be announced, with no fixed time.timeisHHMM-HHMMon a 24 hour clock, with no colon and no time zone. It is Singapore time.durationis in half hours, so4is two hours.remarksis NTU's own note and is empty when there is none. It often gives the weeks the class runs, such asTeaching Wk2-13, or alternate weeks such asTeaching Wk2,4,6,8,10,12. It is free text, so do not rely on parsing it.
Exams#
One exam
{ "key": "SC1004", "name": "LINEAR ALGEBRA FOR COMPUTING", "date": "23 November 2026", "day": 1, "start_time": "5.00 pm", "end_time": "7.00 pm", "duration": 4}date,start_timeandend_timeare text as NTU writes them. Times use a dot, as in9.00 am, not a colon.daycounts from1for Monday to7for Sunday, anddurationis in half hours.- Venues and seats are not published in this data.
Module records#
auis a number in/api/modules/{code}and text, such as"3.0", inmodules.json.prerequisitesis a list of groups. Every group must be met, and any one module in a group meets it. In the example below you need (MH1812 or SC1007) and (SC1007 or SC1124). A code with a suffix, such asSC1003(Corequisite), may be taken at the same time.requiresflattens the groups, andrequiredBylists the modules that need this one.categoriesusesCOREfor programme core,GLOADfor BDE,MLOADfor a minor,GERPfor general education, and a few others.- The
restrictionsfields are free text exactly as NTU publishes them, ornull.description,gradeTypeandschoolcan also benull. Lists are empty, not null. examisnullwhen no exam timetable is published for the latest offering.
From SC2001
"prerequisites": [["MH1812", "SC1007"], ["SC1007", "SC1124"]]