Tabula API

REST API for Tabula, the University of Warwick's own system for the administration of teaching and learning. Built and operated by Warwick's IDG / IT Services software engineering team — the iCalendar responses carry PRODID:-//Tabula//University of Warwick IT Services//EN. Resource-oriented URLs, JSON in all responses including errors, and a published versioning promise. Covers departments and modules, coursework and submissions, small group teaching, monitoring points, member profiles, timetabling and asynchronous jobs. Term dates, term weeks and holiday dates are public and need no credentials; everything else requires Warwick Web Sign-on via HTTP Basic Auth or OAuth 1.0a. A sandbox with fake student data is available on request.

Documentation

Specifications

Schemas & Data

Other Resources

OpenAPI Specification

university-of-warwick-tabula-openapi.yml Raw ↑
# generated: '2026-08-19'
# method: derived
# source: https://warwick.ac.uk/services/idg/services-support/web/tabula/api/
# x-operator: institution
#
# Pristine pre-refine copy. Derived by hand from the University of Warwick's own
# published Tabula API documentation (read via Warwick's `?markdown` twin) and
# verified against the live host on 2026-08-19. Every path below was probed:
# public paths returned 200 with the payload shown in examples/, gated paths
# returned the documented 401 envelope (NOT 404), which confirms the route exists.
# No endpoint is included that was not both documented by Warwick AND probed.
openapi: 3.1.0
info:
  title: Tabula API
  version: v1
  summary: University of Warwick's teaching and learning administration API.
  description: >-
    Tabula is the University of Warwick's system for the administration of teaching and
    learning. It is built and operated by the University's own Information and Digital
    Group (IDG) / IT Services software engineering team — the iCal responses it emits
    carry `PRODID:-//Tabula//University of Warwick IT Services//EN`, and the source
    repositories sit under the institution's own GitHub organisation. This is an
    institution-operated contract, not a vendor platform running under Warwick's name.


    The API is resource-oriented, returns JSON in all responses including errors, and
    wraps every payload in a `success`/`status` envelope. A small number of calendar
    endpoints (term dates, term weeks, holiday dates) are fully public and require no
    credentials. Everything else is protected by Warwick Web Sign-on and requires either
    HTTP Basic Auth with an ITS External User account or an OAuth 1.0a token.


    Content negotiation: the calendar endpoints return JSON by default and iCalendar when
    the request carries `Accept: text/calendar` or the path ends in `.ics`.
  termsOfService: https://warwick.ac.uk/terms/
  contact:
    name: University of Warwick ITS Web Team
    url: https://warwick.ac.uk/services/idg/services-support/web/tabula/api/
    email: webteam@warwick.ac.uk
  license:
    name: Warwick website terms of use
    url: https://warwick.ac.uk/terms/
servers:
  - url: https://tabula.warwick.ac.uk/api/v1
    description: Production
  - url: https://tabula-sandbox.warwick.ac.uk/api/v1
    description: >-
      Sandbox. Contains no staff data and only auto-generated fake student data.
      Access is granted on request to tabula@warwick.ac.uk.
externalDocs:
  description: Tabula API documentation
  url: https://warwick.ac.uk/services/idg/services-support/web/tabula/api/
tags:
  - name: Timetabling
    description: Term dates, term weeks, holiday dates, and module/member timetables.
  - name: Administration
    description: Departments and modules.
  - name: Jobs
    description: Long-running asynchronous job instances.
security:
  - {}
paths:
  /termdates:
    get:
      tags: [Timetabling]
      operationId: retrieveTermDates
      summary: Retrieve term dates
      description: >-
        Retrieve the list of term dates for the current academic year plus the previous and
        next years. Documented by Warwick as "This API is public" and verified unauthenticated
        (HTTP 200) on 2026-08-19.
      security:
        - {}
      parameters:
        - $ref: '#/components/parameters/AcceptCalendar'
      responses:
        '200':
          description: Term dates.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TermDatesResponse'
            text/calendar:
              schema:
                type: string
                description: iCalendar (RFC 5545) document.
        '500':
          $ref: '#/components/responses/ServerError'
  /termdates.ics:
    get:
      tags: [Timetabling]
      operationId: retrieveTermDatesIcal
      summary: Retrieve term dates as iCalendar
      description: >-
        Extension-driven form of the term dates endpoint. Verified unauthenticated
        (HTTP 200, text/calendar) on 2026-08-19.
      security:
        - {}
      responses:
        '200':
          description: Term dates as an iCalendar document.
          content:
            text/calendar:
              schema:
                type: string
  /termdates/{academicYear}:
    get:
      tags: [Timetabling]
      operationId: retrieveTermDatesForYear
      summary: Retrieve term dates for an academic year
      security:
        - {}
      parameters:
        - $ref: '#/components/parameters/AcademicYearPath'
        - $ref: '#/components/parameters/AcceptCalendar'
      responses:
        '200':
          description: Term dates for the requested academic year.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TermDatesResponse'
            text/calendar:
              schema:
                type: string
  /termdates/weeks:
    get:
      tags: [Timetabling]
      operationId: retrieveTermWeeks
      summary: Retrieve term weeks
      description: >-
        Retrieve the list of term weeks for the current academic year. Documented public and
        verified unauthenticated (HTTP 200) on 2026-08-19.
      security:
        - {}
      parameters:
        - $ref: '#/components/parameters/NumberingSystem'
        - $ref: '#/components/parameters/AcceptCalendar'
      responses:
        '200':
          description: Term weeks.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TermWeeksResponse'
            text/calendar:
              schema:
                type: string
  /termdates/{academicYear}/weeks:
    get:
      tags: [Timetabling]
      operationId: retrieveTermWeeksForYear
      summary: Retrieve term weeks for an academic year
      security:
        - {}
      parameters:
        - $ref: '#/components/parameters/AcademicYearPath'
        - $ref: '#/components/parameters/NumberingSystem'
      responses:
        '200':
          description: Term weeks for the requested academic year.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TermWeeksResponse'
  /holidaydates:
    get:
      tags: [Timetabling]
      operationId: retrieveHolidayDates
      summary: Retrieve holiday dates
      description: >-
        Retrieve statutory and customary University holiday dates. Documented public and
        verified unauthenticated (HTTP 200, 199 dates) on 2026-08-19.
      security:
        - {}
      parameters:
        - $ref: '#/components/parameters/AcceptCalendar'
      responses:
        '200':
          description: Holiday dates.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HolidayDatesResponse'
            text/calendar:
              schema:
                type: string
  /holidaydates.ics:
    get:
      tags: [Timetabling]
      operationId: retrieveHolidayDatesIcal
      summary: Retrieve holiday dates as iCalendar
      description: >-
        Verified unauthenticated (HTTP 200, text/calendar) on 2026-08-19. Also published for
        calendar subscription as `webcal://tabula.warwick.ac.uk/api/v1/holidaydates.ics`.
      security:
        - {}
      responses:
        '200':
          description: Holiday dates as an iCalendar document.
          content:
            text/calendar:
              schema:
                type: string
  /department:
    get:
      tags: [Administration]
      operationId: listDepartments
      summary: List all departments
      description: >-
        Lists all departments in Tabula. Warwick documents the information itself as public
        but states the API "must be called by an authenticated user". Probed unauthenticated
        on 2026-08-19 and returned the documented 401 envelope.
      security:
        - basicAuth: []
        - oauth1: []
      responses:
        '200':
          description: All departments. `subDepartments` is not returned by this operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DepartmentsResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /department/{departmentCode}:
    get:
      tags: [Administration]
      operationId: retrieveDepartment
      summary: Retrieve a department
      security:
        - basicAuth: []
        - oauth1: []
      parameters:
        - $ref: '#/components/parameters/DepartmentCode'
      responses:
        '200':
          description: The department.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DepartmentResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /department/{departmentCode}/modules:
    get:
      tags: [Administration]
      operationId: listDepartmentModules
      summary: List a department's modules
      security:
        - basicAuth: []
        - oauth1: []
      parameters:
        - $ref: '#/components/parameters/DepartmentCode'
      responses:
        '200':
          description: The department's modules.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModulesResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /module:
    get:
      tags: [Administration]
      operationId: listModules
      summary: List all modules
      security:
        - basicAuth: []
        - oauth1: []
      responses:
        '200':
          description: All modules in the system.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ModulesResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /module/{moduleCode}/timetable:
    get:
      tags: [Timetabling]
      operationId: retrieveModuleTimetable
      summary: Retrieve a module timetable
      description: >-
        All scheduled timetable events assigned to the module. Sourced from Syllabus+.
        Requires `Permissions.Module.ViewTimetable`, which all signed-in users hold on all
        modules by default.
      security:
        - basicAuth: []
        - oauth1: []
      parameters:
        - $ref: '#/components/parameters/ModuleCode'
        - $ref: '#/components/parameters/AcademicYearQuery'
      responses:
        '200':
          description: The module's timetable events.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TimetableEventsResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /module/{moduleCode}/timetable/events:
    get:
      tags: [Timetabling]
      operationId: retrieveModuleTimetableEvents
      summary: Retrieve a module's timetable events between two dates
      security:
        - basicAuth: []
        - oauth1: []
      parameters:
        - $ref: '#/components/parameters/ModuleCode'
        - $ref: '#/components/parameters/AcademicYearQuery'
        - name: start
          in: query
          required: false
          description: Start date, formatted dd-MMM-yyyy (e.g. 01-Dec-2015).
          schema:
            type: string
        - name: end
          in: query
          required: false
          description: End date, formatted dd-MMM-yyyy (e.g. 01-Dec-2015).
          schema:
            type: string
      responses:
        '200':
          description: Timetable events in the requested window.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TimetableEventsResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /member/{universityId}/timetable:
    get:
      tags: [Timetabling]
      operationId: retrieveMemberTimetable
      summary: Retrieve a personal timetable
      description: >-
        All scheduled timetable events in a person's timetable for the current year. Does not
        include one-off events such as personal tutor meetings. Requires
        `Permissions.Profiles.Read.Timetable` on the member.
      security:
        - basicAuth: []
        - oauth1: []
      parameters:
        - $ref: '#/components/parameters/UniversityId'
        - $ref: '#/components/parameters/AcademicYearQuery'
      responses:
        '200':
          description: The member's timetable events.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TimetableEventsResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /job/{jobId}:
    get:
      tags: [Jobs]
      operationId: retrieveJob
      summary: Retrieve a job instance
      description: Retrieve the status of a long-running asynchronous job.
      security:
        - basicAuth: []
        - oauth1: []
      parameters:
        - name: jobId
          in: path
          required: true
          description: The job instance identifier.
          schema:
            type: string
      responses:
        '200':
          description: The job instance.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: >-
        HTTP Basic authentication over HTTPS using a Warwick Web Sign-on ITS user code and
        password. Warwick documents that requests SHOULD use a dedicated External User account
        provisioned for API access.
    oauth1:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        OAuth 1.0a. Warwick supports the RSA-SHA1 and HMAC-SHA1 signature algorithms and
        requires a Warwick-specific `scope` parameter naming the service being accessed.
        Request token, authorise and access token endpoints are on websignon.warwick.ac.uk.
        OpenAPI has no native OAuth 1.0a security scheme type, so this is expressed as the
        Authorization header it actually travels in.
  parameters:
    AcademicYearPath:
      name: academicYear
      in: path
      required: true
      description: >-
        The academic year as a 4-digit start year — for 13/14 use `2013`. Defaults to the
        current academic year, which starts on 1 August.
      schema:
        type: string
        pattern: '^[0-9]{4}$'
      example: '2025'
    AcademicYearQuery:
      name: academicYear
      in: query
      required: false
      description: The academic year in yy/yy form, e.g. `13/14`. Defaults to the current SITS academic year.
      schema:
        type: string
      example: 25/26
    NumberingSystem:
      name: numberingSystem
      in: query
      required: false
      description: >-
        Week naming system. `academic` runs 1–52 through the year; `term` restarts at each
        term; `cumulative` continues across terms; `none` always uses dates.
      schema:
        type: string
        enum: [academic, term, cumulative, none]
        default: academic
    AcceptCalendar:
      name: Accept
      in: header
      required: false
      description: Send `text/calendar` to receive iCalendar instead of JSON.
      schema:
        type: string
        enum: [application/json, text/calendar]
    DepartmentCode:
      name: departmentCode
      in: path
      required: true
      description: The lowercase department code, e.g. `cs`.
      schema:
        type: string
      example: cs
    ModuleCode:
      name: moduleCode
      in: path
      required: true
      description: The lowercase module code, e.g. `cs118`.
      schema:
        type: string
      example: cs118
    UniversityId:
      name: universityId
      in: path
      required: true
      description: >-
        The 7-digit University ID of the member. The special value `me` requests the
        currently authenticated user.
      schema:
        type: string
      example: me
  responses:
    Unauthorized:
      description: HTTP authentication failed or was not supplied.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            status: unauthorized
            errors:
              - message: API requests must be authenticated with HTTP Basic Auth or OAuth
    Forbidden:
      description: Authenticated successfully but lacking permission for this request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: >-
        The resource does not exist. Warwick documents that this can also occur when the
        request Content-Type is not application/json.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            status: not_found
            errors:
              - message: We don't know anything about this page
    ServerError:
      description: Something went wrong on the Tabula end.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    Envelope:
      type: object
      description: Every Tabula response carries this envelope.
      required: [success, status]
      properties:
        success:
          type: boolean
        status:
          type: string
    ErrorResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          required: [errors]
          properties:
            success:
              const: false
            errors:
              type: array
              items:
                type: object
                required: [message]
                properties:
                  message:
                    type: string
    WeekRange:
      type: object
      properties:
        minWeek:
          type: integer
        maxWeek:
          type: integer
    Term:
      type: object
      properties:
        name:
          type: string
          examples: [Autumn]
        weekRange:
          $ref: '#/components/schemas/WeekRange'
        academicYear:
          type: string
          examples: ['25/26']
        start:
          type: string
          format: date
        end:
          type: string
          format: date
    TermDatesResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          required: [terms]
          properties:
            terms:
              type: array
              items:
                $ref: '#/components/schemas/Term'
    Week:
      type: object
      properties:
        name:
          type: string
          examples: ['Term 1, week 1']
        academicYear:
          type: string
        weekNumber:
          type: integer
        start:
          type: string
          format: date
        end:
          type: string
          format: date
    TermWeeksResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          required: [weeks]
          properties:
            weeks:
              type: array
              items:
                $ref: '#/components/schemas/Week'
    HolidayDatesResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          required: [dates]
          properties:
            dates:
              type: array
              description: Holiday dates in ISO date format.
              items:
                type: string
                format: date
    Department:
      type: object
      description: >-
        Shape summarised from Warwick's "The Department object" reference page. Field-level
        detail beyond code/name/subDepartments is behind the authenticated surface and is
        deliberately not asserted here.
      properties:
        code:
          type: string
          examples: [cs]
        name:
          type: string
          examples: [Computer Science]
        subDepartments:
          type: array
          items:
            $ref: '#/components/schemas/Department'
    DepartmentsResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          required: [departments]
          properties:
            departments:
              type: array
              items:
                $ref: '#/components/schemas/Department'
    DepartmentResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          required: [department]
          properties:
            department:
              $ref: '#/components/schemas/Department'
    Module:
      type: object
      properties:
        code:
          type: string
          examples: [cs118]
        name:
          type: string
        adminDepartment:
          $ref: '#/components/schemas/Department'
    ModulesResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          required: [modules]
          properties:
            modules:
              type: array
              items:
                $ref: '#/components/schemas/Module'
    TimetableEvent:
      type: object
      description: >-
        Shape summarised from Warwick's "The Timetable Event object" reference page. Sourced
        from Syllabus+.
      properties:
        name:
          type: string
        title:
          type: string
        eventType:
          type: string
        location:
          type: string
        moduleCode:
          type: string
        weekRanges:
          type: array
          items:
            $ref: '#/components/schemas/WeekRange'
        day:
          type: string
        startTime:
          type: string
        endTime:
          type: string
    TimetableEventsResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          properties:
            events:
              type: array
              items:
                $ref: '#/components/schemas/TimetableEvent'
    JobResponse:
      allOf:
        - $ref: '#/components/schemas/Envelope'
        - type: object
          properties:
            job:
              type: object
              properties:
                id:
                  type: string
                status:
                  type: string
                succeeded:
                  type: boolean
                progress:
                  type: integer