openapi: '3.0.1'
info:
  description: |
    NUSMods API contains data used to render <https://nusmods.com>. It includes data on modules offered by NUS and their timetables, as well as information on the locations the classes take place in. You are welcome to use and experiment with the data, which is extracted from official APIs provided by the Registrar's Office.

    The API consists of static JSON files scraped daily from the school's APIs. This means it only partially follow REST conventions, and all resources are read only. All successful responses will return JSON, and all endpoints end in `.json`.

    The shape of the data returned by these endpoints are designed for NUSMods in mind. If you have any questions or find that you need the data in other shapes for other purposes, feel free to reach out to us:

    - **Telegram**: <https://telegram.me/nusmods>
    - **Mailing list**: <mods@nusmods.com>

    ## Fetching data

    Any HTTP client can be used to fetch data from the API. HTTPS is preferred, but the server will also respond to HTTP requests. The server supports HTTP 1.1 as well as HTTP 2 over HTTPS, and supports gzip compression.

    The API has no authentication, and is not rate limited. While the server can respond to a large number of requests simultaneously, we request that you be polite with resource usage so as not to disrupt nusmods.com, which relies on the same API server. In general there is no need to fetch data from the API more than once per day, as that is the frequency at which we update the data.

    [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) headers are enabled on all endpoints, so client-side JavaScript can use also use the API.

    ## TypeScript types

    Since the NUSMods is written in TypeScript, typings are available in the source for the scraper. These may be easier to read than the documentation generated by Swagger.

    - Module types: <https://github.com/nusmodifications/nusmods/blob/master/scrapers/nus-v2/src/types/modules.ts>
    - Venue types: <https://github.com/nusmodifications/nusmods/blob/master/scrapers/nus-v2/src/types/venues.ts>

    ## Data

    Below are some notes about the data returned from the API. Feel free to talk to us or create an issue if any of it is not clear.

    ### Module data

    Module endpoints return information on modules offered by NUS. Most of the module data is self-explanatory, but some of the data are more complex and is explained here.

    #### Lessons

    Each lesson in a timetable has a lesson type `lessonType` and class number `ClassNo`. Every student must take one of each lesson type offered by the module. For example, this module offers two tutorials and one lecture. That means the student must attend the lecture, and can choose one of the two tutorials to attend.

    ```json
    {
      "timetable": [
        {
          "classNo": "1",
          "lessonType": "Lecture",
          "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
          "day": "Tuesday",
          "startTime": "1600",
          "endTime": "1800",
          "venue": "I3-AUD"
        },
        {
          "classNo": "01",
          "lessonType": "Tutorial",
          "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
          "day": "Wednesday",
          "startTime": "1100",
          "endTime": "1200",
          "venue": "COM1-0207"
        },
        {
          "classNo": "02",
          "lessonType": "Tutorial",
          "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
          "day": "Friday",
          "startTime": "0900",
          "endTime": "1000",
          "venue": "COM1-0209"
        }
      ]
    }
    ```

    Each lesson has a `classNo` key. There can be multiple lessons of the same type and class number, in which case students must attend both. In this example, students can choose to attend either lecture group 1 on Tuesdays and Wednesdays, or lecture group 2 on Mondays and Wednesdays.

    ```json
    {
      "timetable": [
        {
          "classNo": "1",
          "lessonType": "Lecture",
          "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
          "day": "Tuesday",
          "startTime": "1600",
          "endTime": "1800",
          "venue": "I3-AUD"
        },
        {
          "classNo": "1",
          "lessonType": "Lecture",
          "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
          "day": "Wednesday",
          "startTime": "1400",
          "endTime": "1500",
          "venue": "I3-AUD"
        },
        {
          "classNo": "2",
          "lessonType": "Lecture",
          "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
          "day": "Monday",
          "startTime": "1000",
          "endTime": "1200",
          "venue": "I3-AUD"
        },
        {
          "classNo": "2",
          "lessonType": "Lecture",
          "weeks": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
          "day": "Wednesday",
          "startTime": "1500",
          "endTime": "1600",
          "venue": "I3-AUD"
        }
      ]
    }
    ```

    #### Lesson Weeks

    The `weeks` key on lessons can return data in one of two forms.

    Weeks is usually a sorted array of numbers. In this case it represents the school weeks the lesson occurs on, from 1 to 13.

    Some classes have lessons outside of the school timetable. In this case a `WeekRange` object is returned. The object will always contain a `start` and `end` key representing the start and end date of lessons. The example below has classes every week from 17th Jan to 18th April.

    ``` json
    "weeks": {
      "start": "2019-01-17",
      "end": "2019-04-18"
    }
    ```

    Optionally it can also include `weekInterval`, a positive integer describing the number of weeks between each lesson, and `weeks`, an array of positive integers describing the weeks on which the lesson will fall, with week 1 being the starting date. If these are not present you can assume lessons will occur every week.

    The following example has lessons on 17th Jan (week 1), 24th Jan (week 2), 7th Feb (week 4) and 21st Feb (week 6).

    ``` json
    "weeks": {
      "start": "2019-01-17",
      "end": "2019-02-21",
      "weeks": [1, 2, 4, 6]
    }
    ```

    The following example has lessons on 17th Jan (week 1), 31st Jan (week 3), 14th Feb (week 5) and 28th Feb (week 7).

    ``` json
    "weeks": {
      "start": "2019-01-17",
      "end": "2019-02-28",
      "weekInterval": 2
    }
    ```

    #### Workload

    The `workload` key can return data in one of two forms.

    Workload is usually a **5-tuple of numbers**, describing the estimated number of hours per week the student is expected to put in for the module for **lectures, tutorials, laboratory, projects/fieldwork, and preparatory work** respectively. For example, a workload of `[2, 1, 1, 3, 3]` means the student should spend every week

    - 2 hours in lectures
    - 1 hour in tutorials
    - 1 hour at the lab
    - 3 hours doing project work
    - 3 hours preparing for classes

    Each module credit represents 2.5 hours of work each week, so the standard 4 MC module represents 10 hours of work each week. Module credit may not be integers.

    Note that this is only an estimate, and may be outdated or differ significantly in reality. Some modules also incorrectly lists the **total** workload hours instead of weekly, so very large values may show up.

    This value is parsed from a string provided by the school, and occasionally this field will contain unusual values which cannot be parsed. In this case this field will contain the original **string** instead, which should be displayed as-is to the user.

    #### Prerequisite, corequisite and preclusions

    These three keys determine whether a student can take a module.

    **Prerequisites** are requirements you have to meet before you can take a module. These are usually in the form of other modules (see prerequisite tree below for a machine readable format), but can also be things like 'taken A-level H2 math' or '70 MCs and above'.

    **Preclusions** refer to modules or requirements that cannot be taken if this module is taken, and vice versa. These are usually modules whose content overlaps significantly with this module, and can usually be used to replace each other to fulfill prerequisites.

    **Corequisites** are modules that must be taken together with this module in the same semester. This usually refer to twined modules - modules which have linked syllabuses.

    #### Prerequisite Tree

    The `prereqTree` key is return on the individual module endpoint (`/modules/{moduleCode`). Not all modules have prerequisites, and some have prerequisites that cannot be properly represented as a tree, in which case this key will not appear.

    This describes the prerequisites that need to be fulfilled before this module can be taken. The data structure is recursive and represents a tree.

    ```json
    {
      "and": [
        "CS1231",
        {
          "or": ["CS1010S", "CS1010X"]
        }
      ]
    }
    ```

    In the example, this module requires CS1231 and either CS1010S or CS1010X. This can be visualized as

    ```
               ┌ CS1231
    ── all of ─┤
               │         ┌ CS1010
               └ one of ─┤
                         └ CS1010X
    ```

    The module information also contains the inverse of this, that is, modules whose requirements are fulfilled by this module (taking this module will allow you to take these modules in the following semester). The data is found on the `fulfillRequirements` key as an array of module codes.

    ### Venue data

    Venue data is simply the module timetable restructured to show the lessons happening at each classroom.

    The venue list endpoint returns a list of all locations that are used in the semester. Note that this is not a comprehensive list of locations, but rather just a list of venues that appears in module lessons.

    The venue information endpoint returns the full class and occupancy information about a venue. The `classes` key contains a list of lessons similar to the `timetable` key in module data, but without a `venue` key and with `moduleCode`.

  title: 'NUSMods API'
  version: '2.0.0'
  contact:
    email: 'mods@nusmods.com'

servers:
  - url: 'https://api.nusmods.com/v2'
  - url: 'http://api.nusmods.com/v2'

tags:
  - name: 'Modules'
  - name: 'Venues'

paths:
  /{acadYear}/moduleList.json:
    summary: 'Module list'
    get:
      summary: 'Get summaries of all modules'
      description: |
        Get the module code, title and semesters which the module is available in for all modules in a year. This is useful for tasks that only require a minimal set of information, such as simple search, autocompleting module code and titles, and checking if a module code is valid.

        NUSMods uses this information to validate module codes and for searching.
      tags:
        - Modules
      parameters:
        - $ref: '#/components/parameters/acadYear'
      responses:
        200:
          description: 'Success'
          content:
            application/json:
              schema:
                type: 'array'
                items:
                  $ref: '#/components/schemas/ModuleCondensed'
        404:
          $ref: '#/components/responses/404'

  /{acadYear}/moduleInformation.json:
    get:
      deprecated: true
      summary: 'Get detailed information about all modules'
      description: |
        Get all information about modules except for timetable and prereq tree in a year. This is compact enough to be loaded and filtered in browsers without lag and is useful for faceted search and detailed module listing.

        In AY2018/2019, NUSMods used this information for the detailed module search page. This endpoint will no longer be present starting in AY2019/2020. Please use the moduleInfo.json endpoint instead, which contains modules which are not offered in the specified academic year, but is otherwise identical to this endpoint.
      parameters:
        - $ref: '#/components/parameters/acadYear'
      tags:
        - 'Modules'
      responses:
        200:
          description: 'Success'
          content:
            application/json:
              schema:
                type: 'array'
                items:
                  $ref: '#/components/schemas/ModuleInformation'
        404:
          $ref: '#/components/responses/404'

  /{acadYear}/moduleInfo.json:
    get:
      summary: 'Get detailed information about all modules'
      description: |
        Get all information about modules except for timetable and prereq tree in a year. This is compact enough to be loaded and filtered in browsers without lag and is useful for faceted search and detailed module listing.

        NUSMods feeds this information into an Elasticsearch search server for the detailed module search page.
      parameters:
        - $ref: '#/components/parameters/acadYear'
      tags:
        - 'Modules'
      responses:
        200:
          description: 'Success'
          content:
            application/json:
              schema:
                type: 'array'
                items:
                  $ref: '#/components/schemas/ModuleInformation'
        404:
          $ref: '#/components/responses/404'

  /{acadYear}/modules/{moduleCode}.json:
    get:
      summary: 'Get all information about a specific module'
      description: |
        Get all information available for a specific module including prerequite tree and timetable.

        NUSMods uses this on the module information page.
      parameters:
        - $ref: '#/components/parameters/acadYear'
        - $ref: '#/components/parameters/moduleCode'
      tags:
        - 'Modules'
      responses:
        200:
          description: 'Success'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Module'
        404:
          $ref: '#/components/responses/404'

  /{acadYear}/semesters/{semester}/venues.json:
    get:
      summary: 'Get a list of all venues'
      parameters:
        - $ref: '#/components/parameters/acadYear'
        - $ref: '#/components/parameters/semester'
      description: |
        Get a list of all venues, including lecture theatres, seminar rooms, laboratories, etc. used in the given semester's classes. This endpoint only returns an array of names, and is useful for searching and autocompletion.
      tags:
        - 'Venues'
      responses:
        200:
          description: 'Success'
          content:
            application/json:
              schema:
                type: 'array'
                items:
                  type: 'string'
                  example: 'LT19'
        404:
          $ref: '#/components/responses/404'

  /{acadYear}/semesters/{semester}/venueInformation.json:
    get:
      summary: 'Get detailed information on all venues'
      parameters:
        - $ref: '#/components/parameters/acadYear'
        - $ref: '#/components/parameters/semester'
      description: |
        Get detailed venue information including classes and occupancy for every venue. This is useful for displaying a timetable of the given venue as well as for checking if a venue is occupied at any given time.
      tags:
        - 'Venues'
      responses:
        200:
          description: 'Success'
          content:
            application/json:
              schema:
                type: 'object'
                additionalProperties:
                  type: 'array'
                  items:
                    $ref: '#/components/schemas/VenueInformation'
                example:
                  LT19:
                    - day: 'Monday'
                      classes:
                        - classNo: '1'
                          startTime: '1830'
                          endTime: '2030'
                          weeks: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
                          day: 'Wednesday'
                          lessonType: 'Lecture'
                          moduleCode: 'CS5322'
                          size: 40
                      availability:
                        0900: 'occupied'
                        0930: 'occupied'
                        1000: 'occupied'
        404:
          $ref: '#/components/responses/404'

components:
  responses:
    404:
      description: 'Not found'

  parameters:
    acadYear:
      name: 'acadYear'
      in: 'path'
      description: 'academic year, with the slash (/) replaced by a dash'
      required: true
      schema:
        type: 'string'
        example: '2018-2019'

    moduleCode:
      name: 'moduleCode'
      in: 'path'
      description: 'module code'
      required: true
      schema:
        type: 'string'
        example: 'CS1010S'

    semester:
      name: 'semester'
      in: 'path'
      description: 'semester, with 1 and 2 representing semester 1 and 2, and 3, 4 representing special term 1 and 2'
      required: true
      schema:
        type: 'number'
        enum: [1, 2, 3, 4]

  schemas:
    VenueInformation:
      properties:
        day:
          type: 'string'
          enum:
            - 'Monday'
            - 'Tuesday'
            - 'Wednesday'
            - 'Thursday'
            - 'Friday'
            - 'Saturday'
        classes:
          type: 'array'
          items:
            $ref: '#/components/schemas/VenueLesson'
        availability:
          type: 'object'
          additionalProperties:
            enum:
              - occupied
          example:
            0900: occupied
            0930: occupied
            1000: occupied

    VenueLesson:
      allOf:
        - $ref: '#/components/schemas/Lesson'
        - type: 'object'
          required:
            - 'moduleCode'
          properties:
            moduleCode:
              type: 'string'
              example: 'CS1010S'

    PrereqTree:
      oneOf:
        - type: 'string'
          example: 'CS1010S'
        - type: 'object'
          required:
            - 'or'
          properties:
            or:
              type: 'array'
              items:
                $ref: '#/components/schemas/PrereqTree'
        - type: 'object'
          required:
            - 'and'
          properties:
            and:
              type: 'array'
              items:
                $ref: '#/components/schemas/PrereqTree'
        - type: 'object'
          required:
            - 'nOf'
          properties:
            nOf:
              type: 'array'
              minItems: 2
              maxItems: 2
              items:
                - type: 'number'
                  description: 'Number of prerequisites required'
                - type: 'array'
                  items:
                    $ref: '#/components/schemas/PrereqTree'
              example: [2, ["CS1010", "CS2100", "CS2103T"]]

      example:
        and:
          - or:
              - 'CS1010S'
              - 'CS1010X'
          - 'CS1231'

    Workload:
      oneOf:
        - type: 'array'
          items:
            type: 'number'
          example: [3, 1, 1, 3, 2]
        - type: 'string'
          example: 'A good background in the topics selected'

    WeekRange:
      required:
        - 'start'
        - 'end'
      properties:
        start:
          type: 'string'
          format: 'date'
          example: '2019-01-17'
        end:
          type: 'string'
          format: 'date'
          example: '2019-06-20'
        weekInterval:
          type: 'number'
          example: 2
          default: 1
        weeks:
          type: 'array'
          items:
            type: 'number'
          example: [1, 2, 4, 5, 6]

    Lesson:
      required:
        - 'classNo'
        - 'startTime'
        - 'endTime'
        - 'weeks'
        - 'venue'
        - 'lessonType'
      properties:
        classNo:
          type: 'string'
          example: '08'
        startTime:
          type: 'string'
          example: '1100'
        endTime:
          type: 'string'
          example: '1200'
        weeks:
          oneOf:
            - $ref: '#/components/schemas/WeekRange'
            - type: 'array'
              items:
                type: 'number'
              example: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
        venue:
          type: 'string'
          example: 'COM1-0208'
        day:
          type: 'string'
          example: 'Friday'
        lessonType:
          type: 'string'
          example: 'Tutorial'
        size:
          type: 'number'
          example: 30

    ModuleCondensed:
      required:
        - 'moduleCode'
        - 'title'
        - 'semesters'
      properties:
        moduleCode:
          type: 'string'
          example: 'EL1101E'
        title:
          type: 'string'
          example: 'The Nature of Language'
        semesters:
          type: 'array'
          items:
            type: 'number'
            enum: [1, 2, 3, 4]
          example: [1, 2]

    SemesterData:
      required:
        - 'semester'
      properties:
        semester:
          type: 'number'
          example: 1
        examDate:
          type: 'string'
          format: 'date-time'
          example: '2018-11-27T09:00:00.000Z'
        examDuration:
          type: 'number'
          example: 120
        timetable:
          type: 'array'
          items:
            $ref: '#/components/schemas/Lesson'

    Module:
      required:
        - 'acadYear'
        - 'description'
        - 'title'
        - 'department'
        - 'faculty'
        - 'workload'
        - 'moduleCredit'
        - 'moduleCode'
        - 'semesterData'
      properties:
        acadYear:
          type: 'string'
          example: '2018/2019'
        preclusion:
          type: 'string'
          example: 'CS1104 or Students from department of ECE'
        description:
          type: 'string'
          example: 'The objective of this module is to familiarise students with the fundamentals of computing devices. Through this module students will understand the basics of data representation, and how the various parts of a computer work, separately and with each other. This allows students to understand the issues in computing devices, and how these issues affect the implementation of solutions. Topics covered include data representation systems, combinational and sequential circuit design techniques, assembly language, processor execution cycles, pipelining, memory hierarchy and input/output systems.'
        title:
          type: 'string'
          example: 'Computer Organisation'
        department:
          type: 'string'
          example: 'Computer Science'
        faculty:
          type: 'string'
          example: 'Computing'
        workload:
          $ref: '#/components/schemas/Workload'
        prerequisite:
          type: 'string'
          example: 'CS1010 or its equivalent'
        moduleCredit:
          type: 'string'
          example: '4'
        moduleCode:
          type: 'string'
          example: 'CS2100'
        semesterData:
          type: 'array'
          items:
            $ref: '#/components/schemas/SemesterData'
        prereqTree:
          $ref: '#/components/schemas/PrereqTree'
        fulfillRequirements:
          type: 'array'
          items:
            type: 'string'
          example:
            - 'CS2106'
            - 'CS3210'

    ModuleInformation:
      required:
        - 'moduleCode'
        - 'title'
        - 'description'
        - 'moduleCredit'
        - 'department'
        - 'faculty'
        - 'workload'
        - 'semesterData'
      properties:
        moduleCode:
          type: 'string'
          example: 'CS2100'
        title:
          type: 'string'
          example: 'Computer Organisation'
        description:
          type: 'string'
          example: 'The objective of this module is to familiarise students with the fundamentals of computing devices. Through this module students will understand the basics of data representation, and how the various parts of a computer work, separately and with each other. This allows students to understand the issues in computing devices, and how these issues affect the implementation of solutions. Topics covered include data representation systems, combinational and sequential circuit design techniques, assembly language, processor execution cycles, pipelining, memory hierarchy and input/output systems.'
        moduleCredit:
          type: 'string'
          example: '4'
        department:
          type: 'string'
          example: 'Computer Science'
        faculty:
          type: 'string'
          example: 'Computing'
        workload:
          $ref: '#/components/schemas/Workload'
        prerequisite:
          type: 'string'
          example: 'CS1010 or its equivalent'
        preclusion:
          type: 'string'
          example: 'CS1104 or Students from department of ECE'
        corequisite:
          type: 'string'
          example: 'Students must take CS2101 in the same semester as this module'
        semesterData:
          type: 'array'
          items:
            type: 'object'
            properties:
              semester:
                type: 'number'
                example: 1
              examDate:
                type: 'string'
                format: 'date-time'
                example: '2018-11-27T09:00:00.000Z'
              examDuration:
                description: 'Duration of the exam in minutes'
                type: 'number'
                example: 120
