Timetable Builder API

The public JSON API behind the official University of Toronto Timetable Builder, operated by Enterprise Applications and Solutions Integration (EASI) within U of T Information Technology Services on the University's own host api.easi.utoronto.ca. Serves course, section, meeting-time, instructor, enrolment-control and building data for every division and all three campuses. Six operations verified live and unauthenticated on 2026-08-19: reference-data, current-session, getMatchingDivisions, getPageableCourses, getCourses and getCoursesByCodeAndSectionCode. The University publishes no documentation, no OpenAPI, no terms of use and no rate-limit statement for it; CORS is pinned to https://ttb.utoronto.ca so browser clients from other origins are blocked while server-side clients are not. The OpenAPI in this repository is an API Evangelist observation, not a University artifact.

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/ttb-course-timetable"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

university-of-toronto-timetable-builder-openapi.yml Raw ↑
# Pristine pre-refine copy. Do not edit.
# generated: '2026-08-19'
# method: derived
# source: live probes of https://api.easi.utoronto.ca/ttb (2026-08-19) plus the operation
#   constants read out of the Timetable Builder client bundle
#   https://ttb.utoronto.ca/main.934e36b03104594f.js
openapi: 3.1.0
info:
  title: University of Toronto Timetable Builder API
  version: '2026-08-19'
  x-operator: institution
  x-provenance:
    generated: '2026-08-19'
    method: derived
    source: >-
      Derived by API Evangelist from live, unauthenticated probes of
      https://api.easi.utoronto.ca/ttb on 2026-08-19 and from the operation constants declared in
      the official Timetable Builder client bundle at
      https://ttb.utoronto.ca/main.934e36b03104594f.js. The University of Toronto does not publish
      an OpenAPI description for this API; this document is a third-party observation, not a
      University of Toronto artifact.
  description: >-
    Unofficial, observation-derived description of the public JSON API behind the University of
    Toronto Timetable Builder (https://ttb.utoronto.ca), operated by Enterprise Applications and
    Solutions Integration (EASI) within U of T Information Technology Services. The host
    api.easi.utoronto.ca is under the University's own registrable domain (utoronto.ca), which makes
    this one of the few genuinely institution-operated programmable surfaces at U of T.

    The API serves course, section, meeting-time, instructor, enrolment-control and building data
    for the University's academic timetable across all three campuses (St. George, Mississauga,
    Scarborough) and all divisions. No API key, token or other credential is required. The service
    sets Access-Control-Allow-Origin: https://ttb.utoronto.ca, so browser callers from other origins
    are blocked while server-to-server callers are not.

    NOT AN OFFICIAL CONTRACT. The University publishes no developer portal, no terms of use for this
    API, no rate-limit statement and no versioning policy. Treat every shape here as observed
    behaviour that the University may change without notice.
  contact:
    name: University of Toronto — Enterprise Applications and Solutions Integration (EASI)
    url: https://easi.its.utoronto.ca/
  termsOfService: https://www.utoronto.ca/privacy
servers:
  - url: https://api.easi.utoronto.ca/ttb
    description: Production Timetable Builder API (probed live 2026-08-19)
tags:
  - name: Courses
    description: Course, section and meeting-time retrieval.
  - name: Reference Data
    description: Sessions, divisions, campuses and other search facets.
paths:
  /reference-data:
    get:
      tags: [Reference Data]
      operationId: getReferenceData
      summary: Retrieve every search facet the Timetable Builder UI offers
      description: >-
        Returns the current sessions, divisions, campuses, degree requirements, course levels,
        delivery modes, day and time preferences, credit weights and sort directions. Verified live
        2026-08-19: HTTP 200, application/json, ~11.7 KB.
      responses:
        '200':
          description: Reference data envelope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReferenceDataEnvelope'
              examples:
                live:
                  summary: Live capture, lists trimmed
                  externalValue: ../examples/ttb-reference-data-response.json
        '404':
          $ref: '#/components/responses/GatewayNotFound'
  /current-session:
    get:
      tags: [Reference Data]
      operationId: getCurrentSession
      summary: List the sessions currently open in the timetable
      description: >-
        Returns the session options (for example "Summer 2026", value 20265) that a course search
        may be scoped to. Verified live 2026-08-19: HTTP 200, application/json.
      responses:
        '200':
          description: Session option list.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OptionListEnvelope'
              examples:
                live:
                  externalValue: ../examples/ttb-current-session-response.json
        '404':
          $ref: '#/components/responses/GatewayNotFound'
  /getMatchingDivisions:
    get:
      tags: [Reference Data]
      operationId: getMatchingDivisions
      summary: Type-ahead lookup of academic divisions
      description: >-
        Returns divisions whose name matches the supplied query, as option objects carrying the
        division code in `value` (for example APSC for the Faculty of Applied Science &
        Engineering). Verified live 2026-08-19 with query=arts.
      parameters:
        - name: query
          in: query
          required: true
          description: Free-text fragment matched against division names.
          schema:
            type: string
          example: arts
      responses:
        '200':
          description: Matching divisions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OptionListEnvelope'
              examples:
                live:
                  externalValue: ../examples/ttb-matching-divisions-response.json
        '404':
          $ref: '#/components/responses/GatewayNotFound'
  /getPageableCourses:
    post:
      tags: [Courses]
      operationId: getPageableCourses
      summary: Search the timetable, one page at a time
      description: >-
        The primary search operation. Accepts a faceted search body and returns a page of matching
        courses together with the divisional legends and enrolment-indicator glossaries needed to
        render them. Verified live 2026-08-19: HTTP 200 with course data for
        courseCode CSC108H1, session 20269, division ARTSC.

        A search that matches nothing returns HTTP 404 with a body-level status code 4404 and a
        null payload, not an empty collection — see the ApplicationStatus schema.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CourseSearch'
            examples:
              live:
                externalValue: ../examples/ttb-pageable-courses-request.json
      responses:
        '200':
          description: One page of matching courses.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageableCourseEnvelope'
              examples:
                live:
                  externalValue: ../examples/ttb-pageable-courses-response.json
            application/xml:
              schema:
                type: string
                description: >-
                  Returned when the client does not send Accept: application/json. The service
                  content-negotiates and will emit a <TTBResponse> XML document instead.
        '404':
          description: >-
            Either the gateway did not match the route, or the search matched no courses. The two
            are distinguishable by body: a gateway miss carries statusCode/message, a no-result
            search carries a null payload and status code 4404.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/GatewayError'
                  - $ref: '#/components/schemas/ApplicationStatusEnvelope'
              examples:
                noResults:
                  externalValue: ../examples/ttb-no-results-response.json
                gatewayMiss:
                  externalValue: ../examples/ttb-gateway-404-response.json
  /getCourses:
    post:
      tags: [Courses]
      operationId: getCourses
      summary: Search the timetable without paging
      description: >-
        Same search body as getPageableCourses minus the paging fields, returning every match in one
        response. Verified live 2026-08-19: HTTP 200 with a 12.9 MB body for a division-wide search.
        Callers should prefer getPageableCourses; there is no documented rate limit and no
        compression negotiated by default.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CourseSearch'
      responses:
        '200':
          description: Every matching course.
          content:
            application/json:
              schema:
                type: object
                properties:
                  payload:
                    type: array
                    items:
                      $ref: '#/components/schemas/Course'
                  status:
                    type: array
                    items:
                      $ref: '#/components/schemas/ApplicationStatus'
        '404':
          $ref: '#/components/responses/GatewayNotFound'
  /getCoursesByCodeAndSectionCode/{code}:
    get:
      tags: [Courses]
      operationId: getCoursesByCodeAndSectionCode
      summary: Retrieve every offering of one course code
      description: >-
        Returns the pageable-course envelope for a single course code. Verified live 2026-08-19 with
        code CSC108H1: HTTP 200, ~295 KB. The client bundle also builds a two-segment form carrying
        a section code; that form returned HTTP 404 on 2026-08-19 and is therefore NOT described
        here.
      parameters:
        - name: code
          in: path
          required: true
          description: Uppercase course code, for example CSC108H1.
          schema:
            type: string
            pattern: '^[A-Z]{3}[0-9]{3}[A-Z][0-9]$'
          example: CSC108H1
      responses:
        '200':
          description: Offerings of the requested course.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageableCourseEnvelope'
        '404':
          $ref: '#/components/responses/GatewayNotFound'
components:
  responses:
    GatewayNotFound:
      description: The gateway did not match a route.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/GatewayError'
          examples:
            live:
              externalValue: ../examples/ttb-gateway-404-response.json
  schemas:
    GatewayError:
      type: object
      description: Edge-level error emitted by the api.easi.utoronto.ca gateway before the TTB service is reached.
      properties:
        statusCode:
          type: integer
          example: 404
        message:
          type: string
          example: Resource not found
    ApplicationStatus:
      type: object
      description: >-
        Business-level status returned inside the response body. Observed value 4404 = no results.
        The University publishes no catalogue of these codes; see errors/ for what has been observed.
      properties:
        code:
          type: integer
          example: 4404
        message:
          type: string
          example: No results found. Please try modifying your search criteria.
    ApplicationStatusEnvelope:
      type: object
      properties:
        payload:
          type: 'null'
        status:
          type: array
          items:
            $ref: '#/components/schemas/ApplicationStatus'
    Option:
      type: object
      description: A selectable facet value used by the Timetable Builder UI.
      properties:
        label:
          type: string
          example: Summer 2026
        value:
          type: string
          example: '20265'
        selected:
          type: boolean
        header:
          type: boolean
          description: True when the option is a non-selectable group heading.
        group:
          type: [string, 'null']
          example: Summer-20265
        metadata:
          type: object
          properties:
            name:
              type: [string, 'null']
            type:
              type: [string, 'null']
    OptionListEnvelope:
      type: object
      properties:
        payload:
          type: array
          items:
            $ref: '#/components/schemas/Option'
        status:
          type: array
          items:
            $ref: '#/components/schemas/ApplicationStatus'
    ReferenceDataEnvelope:
      type: object
      properties:
        payload:
          type: object
          properties:
            currentSessions:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            divisions:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            campuses:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            requirements:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            courseLevels:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            temporaryDeliveryModes:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            deliveryModes:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            dayPreferences:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            timePreferences:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            creditWeights:
              type: array
              items: { $ref: '#/components/schemas/Option' }
            directions:
              type: object
              additionalProperties:
                type: string
        status:
          type: array
          items:
            $ref: '#/components/schemas/ApplicationStatus'
    CourseSearch:
      type: object
      description: Faceted timetable search. Empty arrays mean "do not filter on this facet".
      required: [courseCodeAndTitleProps, sessions, divisions]
      properties:
        courseCodeAndTitleProps:
          type: object
          properties:
            courseCode:
              type: string
              example: CSC108H1
            courseTitle:
              type: string
            courseSectionCode:
              type: string
              description: F (fall), S (winter) or Y (full year).
            searchCourseDescription:
              type: boolean
        departmentProps:
          type: array
          items:
            type: object
        campuses:
          type: array
          items:
            type: string
            example: ST_GEORGE
        sessions:
          type: array
          description: Session codes, for example 20269 for Fall 2026.
          items:
            type: string
        requirementProps:
          type: array
          items:
            type: object
        instructor:
          type: string
        courseLevels:
          type: array
          items:
            type: string
        deliveryModes:
          type: array
          items:
            type: string
        dayPreferences:
          type: array
          items:
            type: object
        timePreferences:
          type: array
          items:
            type: object
        divisions:
          type: array
          description: Division codes, for example ARTSC, APSC, ERIN, SCAR.
          items:
            type: string
        creditWeights:
          type: array
          items:
            type: string
        page:
          type: integer
          minimum: 1
          description: getPageableCourses only.
        pageSize:
          type: integer
          description: getPageableCourses only.
        direction:
          type: string
          enum: [asc, desc]
    PageableCourseEnvelope:
      type: object
      properties:
        payload:
          type: object
          properties:
            pageableCourse:
              type: object
              properties:
                courses:
                  type: array
                  items:
                    $ref: '#/components/schemas/Course'
                total:
                  type: integer
                page:
                  type: integer
                pageSize:
                  type: integer
                direction:
                  type: string
            divisionalLegends:
              type: object
              description: Division code to an HTML legend explaining that division's course coding.
              additionalProperties:
                type: string
            divisionalEnrolmentIndicators:
              type: object
              description: Division code to the list of enrolment-control indicator codes it uses.
              additionalProperties:
                type: array
                items:
                  type: object
                  properties:
                    code: { type: string }
                    name: { type: string }
        status:
          type: array
          items:
            $ref: '#/components/schemas/ApplicationStatus'
    Course:
      type: object
      properties:
        id:
          type: string
          description: Opaque identifier. Observed to change between timetable publications — not a stable key.
          example: 69dd3ea4830c3634bbb69786
        name:
          type: string
          example: Mathematics of Finance for Non-Actuaries
        ucName:
          type: [string, 'null']
        code:
          type: string
          example: ACT230H1
        sectionCode:
          type: string
          enum: [F, S, Y]
        campus:
          type: string
          example: St. George
        sessions:
          type: array
          items:
            type: string
        sections:
          type: array
          items:
            $ref: '#/components/schemas/Section'
    Section:
      type: object
      properties:
        name:
          type: string
          example: TUT0102
        type:
          type: string
          example: Tutorial
        teachMethod:
          type: string
          example: TUT
        sectionNumber:
          type: string
        meetingTimes:
          type: array
          items:
            $ref: '#/components/schemas/MeetingTime'
        instructors:
          type: array
          items:
            type: object
        currentEnrolment:
          type: integer
        maxEnrolment:
          type: integer
        currentWaitlist:
          type: integer
        subTitle:
          type: string
        cancelInd:
          type: string
          enum: ['Y', 'N']
        waitlistInd:
          type: string
          enum: ['Y', 'N']
        tbaInd:
          type: string
          enum: ['Y', 'N']
        openLimitInd:
          type: string
          enum: ['Y', 'N']
        deliveryModes:
          type: array
          items:
            type: object
            properties:
              session: { type: string }
              mode:
                type: string
                example: INPER
        notes:
          type: array
          items:
            type: object
            properties:
              name: { type: string }
              type: { type: string }
              content: { type: string }
        enrolmentControls:
          type: array
          items:
            type: object
    MeetingTime:
      type: object
      properties:
        start:
          $ref: '#/components/schemas/DayTime'
        end:
          $ref: '#/components/schemas/DayTime'
        building:
          $ref: '#/components/schemas/Building'
        sessionCode:
          type: string
        repetition:
          type: string
          example: WEEKLY
        repetitionTime:
          type: string
          example: ONCE_A_WEEK
    DayTime:
      type: object
      description: >-
        Non-standard time encoding. `day` is an integer weekday index and `millisofday` is
        milliseconds since local midnight; there is no timezone, date or ISO-8601 field anywhere in
        the response.
      properties:
        day:
          type: integer
          minimum: 1
          maximum: 7
        millisofday:
          type: integer
          example: 43200000
    Building:
      type: object
      properties:
        buildingCode:
          type: string
          example: SF
        buildingRoomNumber:
          type: string
        buildingRoomSuffix:
          type: string
        buildingUrl:
          type: string
          format: uri
          description: Deep link into the official U of T campus map at https://map.utoronto.ca.
          example: https://map.utoronto.ca/?id=1809#!m/494481
        buildingName:
          type: [string, 'null']