UCL

UCL Timetable API

Fetch timetables with various filters for various groups

OpenAPI Specification

ucl-timetable-api-openapi.yml Raw ↑
openapi: 3.0.0
info:
  title: UCL Analytics Timetable API
  description: "An API generated by a team of student developers to interact with student and university data at UCL.\n\nThe API is made up of several services, each of which will be separately explained. Every service will be documented here with important information, tips and examples.\n\n## Get Your API Key\n\nBefore you can use the API you should head to the API Dashboard and sign up using your UCL user account. Once logged into the dashboard simply name your app and you’ll be given a key that you can use to access all the services. Simple!\n\n## API Rate Limits\n\nRate limiting of the API is primarily on a per-user basis. The limit is calculated against the user, across all their access tokens.\n\nThe limit is 10,000 requests per day and resets every day at midnight, London time.\n\nWhen a request is throttled, the response returned by the server has HTTP Status Code “429 Too Many Requests”. It includes a Retry-After header with the number of seconds the client is throttled for.\n\nIf you would like your rate limit to be increased, contact us at isd.apiteam@ucl.ac.uk\n\n## API Data Freshness\n\nMuch of the data available from the API is served from cache. Bookings and Timetable data are updated every twenty minutes from UCL, and we update the [Library Study Spaces (Workspaces) API](https://uclapi.com/docs/#workspaces) every two minutes. The `Last-Modified` header will provide the time that the most recent caching operation completed in [RFC 2616](https://stackoverflow.com/a/21121453) format. Endpoints that do not rely on cached data will return the current timestamp in this field instead.\n\nThis allows your application to judge whether the data is stale, or might need refreshing. For example, if a booking is added to the database and the data you are using is more than twenty minutes old, it may be that the booking is not visible to you yet. Consider creating a fresh request in this case.\n\nIf you notice that the `Last-Modified` timestamp you see is unreasonably old, please [get in contact with us](mailto:isd.apiteam@ucl.ac.uk) ASAP to report this as it may indicate very stale data and an issue at our end.\n\n## OAuth\n\nOAuth is a protocol that lets external apps request secure access to private UCL account data without getting your password. This can be done with a \"Sign In With UCL\" button on your website or app which saves UCL users the trouble of registering a new account with you. It also allows your app or website to retrieve a user's personal timetable.\n\nCheck out a JS web app demo [here](https://uclapi-oauth-demo.glitch.me/). The source code for the demo is available [here](https://glitch.com/edit/#!/uclapi-oauth-demo).\n\nFor an example of a mobile app implementation, check out [UCL Assistant](https://github.com/uclapi/ucl-assistant-app) (written in React Native) and the accompanying [UCL Assistant API backend](https://github.com/uclapi/ucl-assistant-api/tree/master/src/oauth) (written in Node.JS).\n\n### Sign In With UCL Button\nIf you want to add a \"Sign In With UCL\" button to your site, which looks like this:\n\n<a href=\"https://uclapi.com/oauth/authorise?client_id=CLIENT_ID&state=STATE\">\n  <img width=\"20%\" src=\"https://s3.eu-west-2.amazonaws.com/uclapi-static/SignInWithUCLSmall.png\">\n</a>\n\nyou can copy the following the code below and replace CLIENT_ID and STATE by the `client_id` of your app and a random `state`:\n\n```\n<a href=\"https://uclapi.com/oauth/authorise?client_id=CLIENT_ID&state=STATE\">\n  <img src=\"https://s3.eu-west-2.amazonaws.com/uclapi-static/SignInWithUCLSmall.png\">\n</a>\n```\n\n### Scopes\n\nOAuth scopes specify what access your app needs to a UCL user’s account. As an app developer, you set the desired scopes in the API Dashboard. When a user is responding to your authorisation request, the requested scopes will be displayed to the user.\n\n### OAuth Workflow\n\nIf your application uses OAuth, you must set a callback URL in the dashboard. Then the app should follow this procedure:\n\n1. Redirect the user to `https://uclapi.com/oauth/authorise` with `state` and the application’s `client_id` as query parameters.\n\n2. The user logs in with their UCL credentials on the UCL Single Sign-on website (if not logged in already).\n\n3. The user reviews the OAuth scopes requested and either authorises or denies the application's request. If the application is authorised, the callback URL receives `client_id`, `state` (specified in 1.), `result`, and `code`.\n\nIf the application is denied, the callback URL receives `result` and `state`, and no private data will be provided to the application.\n\n4. To obtain a OAuth user token (necessary for retrieving personal data and certain API endpoints), we require `code` (from 3.), `client_id`, and `client_secret`. These should then be sent to `https://uclapi.com/oauth/token`, which will return a response containing `state`, `ok`, `client_id`, `token` (OAuth user token), and `scope`  (OAuth scopes the app can access on the user’s behalf).\n\n**Note**: OAuth tokens and general API tokes are different. Whilst general API tokens can be used for all non-personal, generic data (such as room bookings), OAuth tokens must be used with an app's client_secret in order to retrieve personal data for a user. To make things easier, you can use personal OAuth tokens in place of general tokens once a user has logged into your app to retrieve generic data too.\n\n### Tokens\n\nTokens uniquely identify an app that is requesting data from the API.\n\nTokens are a long string variable of numbers and letters. e.g. `uclapi-5d58c3c4e6bf9c-c2910ad3b6e054-7ef60f44f1c14f-a05147bfd17fdb`.\n\nThere are two different kinds of tokens you can work with:\n\n1. Generic Tokens: These are tokens that are used to request non-personal data. These tokens are used between applications and the API to request any sort of data that the app may need that is not tied to a specific student. For example, UCL API’s Room booking service uses tokens to return information about rooms - when they are booked and which UCL rooms are free.\n\n2. OAuth Tokens: This type of token is used when an app requires personal data from users. One of the most common uses of this type of token is when you sign in via UCL on an app.  The app will then use a token to request a user’s personal data such as:\n\n- Department\n- Email\n- Full name\n- Given name\n- UPI\n- If they are a student or not\n- Student number (*note:* to get this, you need to tick the relevant scope in the dashboard before a user logs in; more on scopes above).\n\nNote that you can also use OAuth Tokens to access all the same data that generic app tokens can access.\n\nEach token is uniquely generated for each user logging into each app.\n\nPlease note, access to any of this data needs to be approved by the user first.\n\nTo use this type of token for your app, you need to redirect the user to the \"Authorise\" endpoint at: `https://uclapi.com/oauth/authorise` which can be done directly or by including a “Sign in With UCL Button” in your app, such as the one provided below, which links users to the authorisation endpoint with your app’s Client ID (accessible via the dashboard) and a random state number included in the GET parameters.\n\nThe users then sign in with their UCL credentials and, if they authorise your app to use their personal data, a token will be generated which your app can use to get user’s personal data in JSON format from the oauth/user/data. Your application will receive the token at the callback URL you provided in the [Dashboard](https://uclapi.com/dashboard).\n\n## Code Samples\n\nAfter authorisation, calling most of the API endpoints will be fairly similar to each other. Authorisation code samples are provided in their respective descriptions.\n\nIn addition, please find short code examples of how you might call the `/roombookings/equipment` endpoint in your own code (you will find that only the request parameters will change between most different endpoints):\n\nPython:\n```python\nimport requests\n\nparams = {\n  \"token\": \"uclapi-5d58c3c4e6bf9c-c2910ad3b6e054-7ef60f44f1c14f-a05147bfd17fdb\",\n  \"roomid\": \"433\"\n  \"siteid\": \"086\"\n}\n\nr = requests.get(\"https://uclapi.com/roombookings/equipment\", params=params)\nprint(r.json())\n```\n\nShell:\n```shell\ncurl -G https://uclapi.com/roombookings/equipment -d token=uclapi-5d58c3c4e6bf9c-c2910ad3b6e054-7ef60f44f1c14f-a05147bfd17fdb -d roomid=433 -d siteid=086\n```\n\nJavaScript:\n```js\nfetch(\"https://uclapi.com/roombookings/equipment?token=uclapi-5d58c3c4e6bf9c-c2910ad3b6e054-7ef60f44f1c14f-a05147bfd17fdb&roomid=433&siteid=086\")\n  .then(response => response.json())\n  .then(json => console.log(json));\n```"
  contact:
    name: API Support
    email: isd.apiteam@ucl.ac.uk
    url: https://uclapi.com
  version: 1.0.0-oas3
  termsOfService: https://github.com/uclapi/uclapi/blob/master/backend/uclapi/uclapi/UCLAPIAcceptableUsePolicy.txt
  license:
    url: https://github.com/uclapi/uclapi/blob/master/LICENSE
    name: MIT License
servers:
- url: https://uclapi.com
  description: Deployment server
- url: https://staging.ninja
  description: Staging server
tags:
- name: Timetable
  description: Fetch timetables with various filters for various groups
paths:
  /timetable/personal:
    get:
      summary: Returns the personal timetable of the user.
      tags:
      - Timetable
      security:
      - OAuthSecurity:
        - personal_timetable
        OAuthToken: []
      parameters:
      - $ref: '#/components/parameters/client_secret'
      - name: date
        in: query
        description: A date to filter entries by
        required: false
        schema:
          type: string
      responses:
        '200':
          description: A timetable.
          content:
            application/json:
              schema:
                type: object
                properties:
                  timetable:
                    $ref: '#/components/schemas/timetable'
                  ok:
                    type: boolean
        '400':
          description: Request error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
              examples:
                '1':
                  $ref: '#/components/examples/ErrorNoToken'
                '2':
                  $ref: '#/components/examples/ErrorTokenNotExist'
                '3':
                  $ref: '#/components/examples/ErrorInvalidToken'
                '4':
                  $ref: '#/components/examples/ErrorThrottling'
                '5':
                  $ref: '#/components/examples/ErrorNoClientSecret'
                '6':
                  $ref: '#/components/examples/ErrorInvalidClientSecret'
                '7':
                  $ref: '#/components/examples/ErrorInactiveToken'
                '8':
                  $ref: '#/components/examples/ErrorPersonalData'
                '9':
                  $ref: '#/components/examples/ErrorRejectedScope'
  /timetable/bymodule:
    get:
      summary: Returns a yearly timetable for the supplied modules.
      tags:
      - Timetable
      security:
      - OAuthSecurity: []
        OAuthToken: []
      parameters:
      - name: modules
        in: query
        description: A comma-separated list of the module codes you want the timetable of. You can supply either standard module codes (e.g. COMP0133), or full codes including the instance of the module (COMP0133-A7U-T1). Note that if you do not supply an instance, every single timetable entry will be returned including duplicates for the same module taught as multiple instances. It is recommended that a full module code including instance be supplied.
        required: true
        schema:
          type: string
      - name: date
        in: query
        description: A date to filter entries by
        required: false
        schema:
          type: string
      responses:
        '200':
          description: A timetable.
          content:
            application/json:
              schema:
                type: object
                properties:
                  timetable:
                    $ref: '#/components/schemas/timetable'
                  ok:
                    type: boolean
        '400':
          description: Request error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
              examples:
                '1':
                  $ref: '#/components/examples/ErrorNoToken'
                '2':
                  $ref: '#/components/examples/ErrorTokenNotExist'
                '3':
                  $ref: '#/components/examples/ErrorInvalidToken'
                '4':
                  $ref: '#/components/examples/ErrorThrottling'
                '5':
                  $ref: '#/components/examples/ErrorNoClientSecret'
                '6':
                  $ref: '#/components/examples/ErrorInvalidClientSecret'
                '7':
                  $ref: '#/components/examples/ErrorInactiveToken'
                No module IDs provided:
                  value:
                    ok: false
                    error: No module IDs provided.
                Invalid module IDs provided:
                  value:
                    ok: false
                    error: One or mote invalid Module IDs supplied.
  /timetable/data/departments:
    get:
      summary: Returns a list of every department at UCL, along with its internal name. This can be used with the /data/modules endpoint to request information on all modules for a department.
      tags:
      - Timetable
      security:
      - OAuthSecurity: []
        OAuthToken: []
      responses:
        '200':
          description: A list of department objects.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  departments:
                    type: array
                    items:
                      $ref: '#/components/schemas/department'
        '400':
          description: Request error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
              examples:
                '1':
                  $ref: '#/components/examples/ErrorNoToken'
                '2':
                  $ref: '#/components/examples/ErrorTokenNotExist'
                '3':
                  $ref: '#/components/examples/ErrorInvalidToken'
                '4':
                  $ref: '#/components/examples/ErrorThrottling'
                '5':
                  $ref: '#/components/examples/ErrorNoClientSecret'
                '6':
                  $ref: '#/components/examples/ErrorInvalidClientSecret'
                '7':
                  $ref: '#/components/examples/ErrorInactiveToken'
  /timetable/data/modules:
    get:
      summary: Returns a list of every module taught by a given department at UCL.
      tags:
      - Timetable
      security:
      - OAuthSecurity: []
        OAuthToken: []
      parameters:
      - name: department
        in: query
        description: The department ID available from /data/departments.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: A list of department objects.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  modules:
                    type: object
                    additionalProperties:
                      $ref: '#/components/schemas/module_data_courses_modules'
        '400':
          description: Request error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
              examples:
                '1':
                  $ref: '#/components/examples/ErrorNoToken'
                '2':
                  $ref: '#/components/examples/ErrorTokenNotExist'
                '3':
                  $ref: '#/components/examples/ErrorInvalidToken'
                '4':
                  $ref: '#/components/examples/ErrorThrottling'
                '5':
                  $ref: '#/components/examples/ErrorNoClientSecret'
                '6':
                  $ref: '#/components/examples/ErrorInvalidClientSecret'
                '7':
                  $ref: '#/components/examples/ErrorInactiveToken'
  /timetable/data/courses:
    get:
      summary: Returns a list of every course taught by a given department at UCL.
      tags:
      - Timetable
      security:
      - OAuthSecurity: []
        OAuthToken: []
      parameters:
      - name: department
        in: query
        description: The department ID available from /data/departments.
        required: true
        schema:
          type: string
      responses:
        '200':
          description: A list of department objects.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  courses:
                    type: array
                    items:
                      $ref: '#/components/schemas/course'
        '400':
          description: Request error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
              examples:
                '1':
                  $ref: '#/components/examples/ErrorNoToken'
                '2':
                  $ref: '#/components/examples/ErrorTokenNotExist'
                '3':
                  $ref: '#/components/examples/ErrorInvalidToken'
                '4':
                  $ref: '#/components/examples/ErrorThrottling'
                '5':
                  $ref: '#/components/examples/ErrorNoClientSecret'
                '6':
                  $ref: '#/components/examples/ErrorInvalidClientSecret'
                '7':
                  $ref: '#/components/examples/ErrorInactiveToken'
                No department ID provided:
                  value:
                    ok: false
                    error: No department ID provided.
  /timetable/data/courses/modules:
    get:
      summary: Returns a list of every module taught on a given course at UCL.
      tags:
      - Timetable
      security:
      - OAuthSecurity: []
        OAuthToken: []
      parameters:
      - name: course
        in: query
        description: The course ID available from /data/courses.
        required: true
        schema:
          type: string
      - name: term_1
        in: query
        description: Boolean designating if you would like module instances that are taught in term 1.
        required: false
        schema:
          type: boolean
      - name: term_2
        in: query
        description: Boolean designating if you would like module instances that are taught in term 2.
        required: false
        schema:
          type: boolean
      - name: term_3
        in: query
        description: Boolean designating whether or not you want module instances that are taught in term 3.
        required: false
        schema:
          type: boolean
      - name: term_1_next_year
        in: query
        description: Boolean designating if you would like module instances that are taught in term 1 of the next academic year. This is used by admissions to calculate the end dates for non-standard programmes, and therefore is rare
        required: false
        schema:
          type: boolean
      - name: summer
        in: query
        description: Boolean designating if you would like module instances that are timetabled in the summer. This can happen in some Postgraduate and Medicine teaching arrangements, but is rare. Note that this is NOT the same as the UCL Summer School.
        required: false
        schema:
          type: boolean
      - name: year_long
        in: query
        description: Boolean designating if you would like module instances where the course is timetabled to last for an entire academic year.
        required: false
        schema:
          type: boolean
      - name: lsr
        in: query
        description: Boolean designating if you would like module instances where the module is timetabled during the Late Summer Resit period. This is used internally by Examinations to timetable Late Summer Assessments (LSAs).
        required: false
        schema:
          type: boolean
      - name: is_summer_school
        in: query
        description: Boolean designating if you would like module instances where the course is taught as part of the UCL Summer School (true) or standard academic teaching (false).
        required: false
        schema:
          type: boolean
      - name: session_1
        in: query
        description: Boolean designating if you would like module instances where the module is taught in the first summer school session of this academic year's summer.
        required: false
        schema:
          type: boolean
      - name: session_2
        in: query
        description: Boolean designating if you would like module instances where the module is taught in the second summer school session of this academic year's summer.
        required: false
        schema:
          type: boolean
      - name: is_undergraduate
        in: query
        description: Boolean designating if you would like undergraduate module instances.
        required: false
        schema:
          type: boolean
      - name: only_available
        in: query
        description: Boolean designating if you would only like available module instances (i.e. ones that are not compulsory for the course).
        required: false
        schema:
          type: boolean
      - name: only_compulsory
        in: query
        description: Boolean designating if you would only like compulsory module instances.
        required: false
        schema:
          type: boolean
      responses:
        '200':
          description: A list of department objects.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  modules:
                    type: object
                    additionalProperties:
                      $ref: '#/components/schemas/module_data_courses_modules'
        '400':
          description: Request error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error'
              examples:
                '1':
                  $ref: '#/components/examples/ErrorNoToken'
                '2':
                  $ref: '#/components/examples/ErrorTokenNotExist'
                '3':
                  $ref: '#/components/examples/ErrorInvalidToken'
                '4':
                  $ref: '#/components/examples/ErrorThrottling'
                '5':
                  $ref: '#/components/examples/ErrorNoClientSecret'
                '6':
                  $ref: '#/components/examples/ErrorInvalidClientSecret'
                '7':
                  $ref: '#/components/examples/ErrorInactiveToken'
                No course ID provided:
                  value:
                    ok: false
                    error: No course ID provided.
                Invalid paramenter type:
                  value:
                    ok: false
                    error: Given parameter is not of correct type
                Invalid parameters:
                  value:
                    ok: false
                    error: only_available and only_compulsory cannot both be true
components:
  schemas:
    teaching_periods:
      properties:
        term_1:
          type: boolean
          example: false
        term_2:
          type: boolean
          example: true
        term_3:
          type: boolean
          example: false
        term_1_next_year:
          type: boolean
          example: false
        summer:
          type: boolean
          example: false
    delivery:
      properties:
        fheq_level:
          type: number
          example: 7
        is_undergraduate:
          type: boolean
          example: true
        student_type:
          type: string
          example: Campus-based, numeric mark scheme
    timetable:
      properties:
        date:
          type: array
          items:
            $ref: '#/components/schemas/event'
    period:
      properties:
        teaching_periods:
          $ref: '#/components/schemas/teaching_periods'
        year_long:
          type: boolean
          example: false
        lsr:
          type: boolean
          example: false
        summer_school:
          $ref: '#/components/schemas/summer_school'
    department:
      properties:
        department_id:
          type: string
          example: COMPS_ENG
        name:
          type: string
          example: Computer Science
    lecturer:
      properties:
        name:
          type: string
          example: HUNTER, Anthony (Prof)
        department_name:
          type: string
          example: Computer Science
        department_id:
          type: string
          example: COMPS_ENG
        email:
          type: string
          example: ucachun@ucl.ac.yk
    summer_school:
      properties:
        is_summer_school:
          type: boolean
          example: false
        sessions:
          type: object
          properties:
            session_1:
              type: boolean
              example: false
            session_2:
              type: boolean
              example: false
    module_data_courses_modules:
      properties:
        module_id:
          type: string
          example: COMP3004
        name:
          type: string
          example: Computational Complexity
        instances:
          type: array
          items:
            $ref: '#/components/schemas/instance'
    event:
      properties:
        location:
          $ref: '#/components/schemas/location'
        module:
          $ref: '#/components/schemas/module'
        start_time:
          type: string
          example: '2016-09-02T09:00:00+00:00'
        end_time:
          type: string
          example: '2016-09-02T10:00:00+00:00'
        duration:
          type: integer
          format: int64
          example: 60
        session_type:
          type: string
          example: L
        session_type_str:
          type: string
          example: Lecture
        session_group:
          type: string
          example: ''
        session_title:
          type: string
          example: Computational Complexity A
        contact:
          type: string
          example: Prof Robin Hirsch
    instance:
      properties:
        full_module_id:
          type: string
          example: MATH--82-A7P-T2
        class_size:
          type: number
          example: 12
        delivery:
          $ref: '#/components/schemas/delivery'
        periods:
          $ref: '#/components/schemas/period'
        instance_code:
          type: string
          example: A7P-T2
    course:
      properties:
        course_name:
          type: string
          example: MRes Computational Statistics and Machine Learning
        course_id:
          type: string
          example: TMRCOMSSML01
        years:
          type: number
          example: 1
    module:
      properties:
        lecturer:
          $ref: '#/components/schemas/lecturer'
        module_id:
          type: string
          example: COMP3004
        name:
          type: string
          example: Computational Complexity
        department_id:
          type: string
          example: COMPS_ENG
        department_name:
          type: string
          example: Computer Science
    location:
      properties:
        name:
          type: string
          example: Roberts Building 421
        address:
          type: array
          minItems: 4
          maxItems: 4
          items:
            type: string
          example:
          - Torrington Place
          - London
          - WC1E 7JE
        site_name:
          type: string
          example: Roberts Building
        type:
          type: string
          example: CB
        capacity:
          type: integer
          format: int64
          example: 94
        coordinates:
          type: object
          properties:
            lat:
              type: number
              example: null
            lng:
              type: number
              example: null
    error:
      type: object
      properties:
        ok:
          type: boolean
          default: false
        error:
          type: string
  examples:
    ErrorInactiveToken:
      value:
        ok: false
        error: The token is inactive as the user has revoked your app's access to their data.
      summary: Inactive token
    ErrorNoClientSecret:
      value:
        ok: false
        error: No Client Secret provided.
      summary: No Client Secret provided
    ErrorPersonalData:
      value:
        ok: false
        error: Personal data requires OAuth.
      summary: OAuth required
    ErrorThrottling:
      value:
        ok: false
        error: You have been throttled. Please try again in 10 seconds.
      summary: Throttling
    ErrorInvalidToken:
      value:
        ok: false
        error: Token is invalid.
      summary: Invalid token
    ErrorTokenNotExist:
      value:
        ok: false
        error: Token does not exist.
      summary: Non-existent token
    ErrorInvalidClientSecret:
      value:
        ok: false
        error: Client secret incorrect.
      summary: Client secret incorrect
    ErrorRejectedScope:
      value:
        ok: false
        error: The token provided does not have permission to access this data.
      summary: Weak token scope
    ErrorNoToken:
      value:
        ok: false
        error: No token provided.
      summary: No token provided
  parameters:
    client_secret:
      name: client_secret
      in: query
      description: Client secret of the authenticating app
      required: true
      schema:
        type: string
  securitySchemes:
    OAuthToken:
      type: apiKey
      description: This API requires you to pass your OAuth2 token as a query parameter called 'token'. Use the /authorize and /oauth/token endpoints to authorize a user and get this token.
      name: token
      in: query
    OAuthSecurity:
      type: oauth2
      description: This API uses OAuth2 with the implicit grant flow. [More info](https://uclapi.com/docs#OAuthSecurity)
      flows:
        authorizationCode:
          authorizationUrl: /authorise
          tokenUrl: /token
          scopes:
            personal_timetable: read user's timetable
            student_number: read user's student number