Public Course Search API

UW-Madison's only openly callable API — the unauthenticated JSON search behind public.enroll.wisc.edu/search. Verified live on 2026-08-19: GET /terms returns the open term codes, GET /aggregate returns 190 subject facets per term, and a POST search returned 226 and 932 course records for two terms. No credential of any kind is required. The OpenAPI here is PROBED, not published by UW-Madison.

OpenAPI Specification

university-of-wisconsin-madison-course-search-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: UW-Madison Public Course Search API
  version: '1'
  description: >-
    The JSON API behind UW-Madison's public course and section search at
    https://public.enroll.wisc.edu/search. It is operated by the University of
    Wisconsin-Madison Office of the Registrar / DoIT on the institution's own
    enroll.wisc.edu host, requires no authentication, and is the institution's
    only openly callable course-catalog surface.


    This document is PROBED, not published. UW-Madison does not publish an
    OpenAPI for this API; every path, parameter and response field below was
    observed in a live request made on 2026-08-19 and is recorded only to the
    extent it was actually verified. Fields the probe did not exercise are
    deliberately absent rather than guessed.
  contact:
    name: UW-Madison Office of the Registrar
    url: https://registrar.wisc.edu/
x-operator: institution
x-provenance:
  generated: '2026-08-19'
  method: probed
  source: https://public.enroll.wisc.edu/api/search/v1
  note: >-
    Reverse-described from live unauthenticated responses. Not a UW-Madison
    publication and must never be counted as one. Probes: GET /terms (200, 499
    bytes, 2 terms), GET /aggregate (200, 127,065 bytes), POST / (200, term
    1266 "computer science" -> found=226; term 1272 -> found=932).
servers:
  - url: https://public.enroll.wisc.edu/api/search/v1
    description: Public production course search (no authentication)
paths:
  /:
    post:
      summary: Search courses for a term
      description: >-
        Full-text course search scoped to one term code. Verified live: returns
        a `found` total and a `hits` array of course documents.
      operationId: searchCourses
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CourseSearchRequest'
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CourseSearchResponse'
        '400':
          description: Malformed or missing request body
  /terms:
    get:
      summary: List available terms
      description: Verified live — returns the term codes the search accepts.
      operationId: listTerms
      responses:
        '200':
          description: Term list
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Term'
  /aggregate:
    get:
      summary: List search facets
      description: >-
        Verified live — returns the facet vocabularies the search UI filters on
        (terms, subjects, sessions, specialGroups).
      operationId: listAggregates
      responses:
        '200':
          description: Facet vocabularies
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Aggregate'
components:
  schemas:
    CourseSearchRequest:
      type: object
      required: [selectedTerm]
      properties:
        selectedTerm:
          type: string
          description: Term code from GET /terms.
          example: '1266'
        queryString:
          type: string
          example: computer science
        filters:
          type: array
          items:
            type: object
        page:
          type: integer
          example: 1
        pageSize:
          type: integer
          example: 2
        sortOrder:
          type: string
          example: SCORE
    CourseSearchResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
          nullable: true
        found:
          type: integer
          description: Total matching courses.
          example: 226
        hits:
          type: array
          items:
            $ref: '#/components/schemas/CourseHit'
    CourseHit:
      type: object
      description: >-
        Field set observed in live responses. Types are inferred from observed
        values; only field names are directly verified.
      properties:
        termCode: { type: string }
        courseId: { type: string }
        subject: { type: object }
        catalogNumber: { type: string }
        title: { type: string }
        description: { type: string }
        minimumCredits: { type: number }
        maximumCredits: { type: number }
        creditRange: { type: string }
        firstTaught: { type: string }
        lastTaught: { type: string }
        typicallyOffered: { type: string }
        currentlyTaught: { type: boolean }
        gradingBasis: { type: string }
        repeatable: { type: string }
        honors: { type: string }
        levels: { type: array, items: { type: object } }
        breadths: { type: array, items: { type: object } }
        generalEd: { type: object, nullable: true }
        coreGeneralEducation: { type: object, nullable: true }
        ethnicStudies: { type: object, nullable: true }
        foreignLanguage: { type: object, nullable: true }
        sustainability: { type: object, nullable: true }
        workplaceExperience: { type: object, nullable: true }
        lettersAndScienceCredits: { type: object, nullable: true }
        openToFirstYear: { type: boolean }
        gradCourseWork: { type: boolean }
        approvedForTopics: { type: boolean }
        topics: { type: array, items: { type: object } }
        advisoryPrerequisites: { type: string, nullable: true }
        enrollmentPrerequisites: { type: string, nullable: true }
        courseRequirements: { type: object, nullable: true }
        courseDesignation: { type: string }
        courseDesignationRaw: { type: string }
        fullCourseDesignation: { type: string }
        fullCourseDesignationRaw: { type: string }
        allCrossListedSubjects: { type: array, items: { type: object } }
        academicGroupCode: { type: string }
        catalogPrintFlag: { type: boolean }
        instructorProvidedContent: { type: string, nullable: true }
        lastUpdated: { type: integer, format: int64 }
        catalogSort: { type: string }
        subjectAggregate: { type: string }
    Term:
      type: object
      properties:
        termCode: { type: string, example: '1266' }
        shortDescription: { type: string, example: '2026 Summr' }
        longDescription: { type: string, example: Summer 2026 }
        beginDate: { type: integer, format: int64 }
        endDate: { type: integer, format: int64 }
        instructionBeginDate: { type: integer, format: int64 }
        instructionEndDate: { type: integer, format: int64 }
        academicYear: { type: string, example: '2025-26' }
        pastTerm: { type: boolean }
    Aggregate:
      type: object
      properties:
        terms: { type: array, items: { $ref: '#/components/schemas/Term' } }
        subjects: { type: array, items: { type: object } }
        sessions: { type: array, items: { type: object } }
        specialGroups: { type: array, items: { type: object } }