> ## Documentation Index
> Fetch the complete documentation index at: https://docs.terang.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# List Courses

> Get a paginated list of published courses available in the public catalog.



## OpenAPI

````yaml api-reference/lms-openapi.json GET /api/courses
openapi: 3.1.0
info:
  title: Terang AI LMS API
  description: >-
    LMS application endpoints (served from the LMS application host, e.g.
    https://lms.terang.ai). Maintained manually — NOT overwritten by the Core
    API auto-update.
  version: 1.0.0
servers:
  - description: LMS (Production)
    url: https://lms.terang.ai
  - description: LMS (Development)
    url: https://dev.lms.terang.ai
security: []
paths:
  /api/courses:
    get:
      tags:
        - Courses
      summary: List Courses
      description: >-
        Returns a paginated list of published courses available in the public
        catalog. Includes module summaries, category info, pricing, and
        enrollment details. Supports server-side pagination, search, and
        category filtering.


        API key users always see published courses (equivalent to
        `?public=true`). Session-authenticated teachers see their own courses.
      operationId: listCourses
      parameters:
        - name: public
          in: query
          required: false
          description: >-
            Set to `true` to access the public catalog (only works with API key
            auth).
          schema:
            type: boolean
        - name: page
          in: query
          required: false
          description: 'Page number (1-based). Default: `1`.'
          schema:
            type: integer
            minimum: 1
        - name: limit
          in: query
          required: false
          description: 'Results per page (max 50). Default: `12`.'
          schema:
            type: integer
            minimum: 1
            maximum: 50
        - name: search
          in: query
          required: false
          description: >-
            Search courses by name, description, instructor, course code, or
            category.
          schema:
            type: string
        - name: categoryId
          in: query
          required: false
          description: >-
            Filter by category ID. Pass `uncategorized` for courses with no
            category.
          schema:
            type: string
        - name: sortBy
          in: query
          required: false
          description: >-
            Sort field: `name`, `students`, or `modules`. Default: newest first
            (by id).
          schema:
            type: string
            enum:
              - name
              - students
              - modules
        - name: courseId
          in: query
          required: false
          description: Direct deep-link to a specific course by ID.
          schema:
            type: integer
      responses:
        '200':
          description: Courses retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListCoursesResponse'
        '400':
          description: Bad request — missing required parameters for teacher/session auth
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized — missing or invalid API key / session
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: >-
            Rate limit exceeded — 100 requests per minute per API key. Retry
            after `Retry-After` seconds.
          headers:
            Retry-After:
              description: Seconds until the rate limit window resets
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKey: []
        - cookieAuth: []
components:
  schemas:
    ListCoursesResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        courses:
          type: array
          items:
            $ref: '#/components/schemas/PublicCourse'
        pagination:
          allOf:
            - $ref: '#/components/schemas/Pagination'
            - description: >-
                Present only when server-side pagination is used (`page` or
                `limit` params).
    ErrorResponse:
      type: object
      description: Error response returned for 4xx and 5xx status codes.
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          example: Rate limit exceeded
    PublicCourse:
      type: object
      properties:
        id:
          type: string
          example: '1'
        name:
          type: string
          example: Pelatihan Kepemimpinan
        code:
          type: string
          example: COURSE0001
        description:
          type: string
        instructor:
          type: string
          example: Dr. Andi Wijaya
        startDate:
          type: string
          format: date-time
        endDate:
          type: string
          format: date-time
        enrollmentType:
          type: string
          example: code
        enrollmentCode:
          type: string
        isPurchasable:
          type: boolean
        price:
          type: number
          example: 500000
        priceNonMember:
          type: number
          nullable: true
          example: 750000
        priceMahasiswa:
          type: number
          nullable: true
          example: 350000
        currency:
          type: string
          example: IDR
        previewMode:
          type: boolean
        eventCode:
          type: string
          example: EVT-001
          nullable: true
        nilaiKum:
          type: number
          nullable: true
          example: 10
        categoryId:
          type: integer
          nullable: true
        category:
          $ref: '#/components/schemas/Category'
          nullable: true
        thumbnail:
          type: string
          format: uri
          nullable: true
        moduleCount:
          type: integer
          example: 5
        moduleSummaries:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              title:
                type: string
              order:
                type: integer
              chapterCount:
                type: integer
        modules:
          type: array
          items:
            $ref: '#/components/schemas/ModuleSummary'
        admissions:
          $ref: '#/components/schemas/DetailSection'
          nullable: true
        academics:
          $ref: '#/components/schemas/DetailSection'
          nullable: true
        tuitionAndFinancing:
          $ref: '#/components/schemas/DetailSection'
          nullable: true
        careers:
          $ref: '#/components/schemas/DetailSection'
          nullable: true
        studentExperience:
          $ref: '#/components/schemas/DetailSection'
          nullable: true
        finalExam:
          $ref: '#/components/schemas/FinalExam'
        certificate:
          $ref: '#/components/schemas/CertificateInfo'
        minPassingScore:
          type: integer
          example: 70
        totalProgress:
          type: integer
        status:
          type: string
          example: not-started
        studentCount:
          type: integer
          example: 42
    Pagination:
      type: object
      properties:
        page:
          type: integer
          example: 1
        limit:
          type: integer
          example: 12
        total:
          type: integer
          example: 25
        totalPages:
          type: integer
          example: 3
    Category:
      type: object
      properties:
        id:
          type: integer
          example: 1
        code:
          type: string
          example: MANAJEMEN
        name:
          type: string
          example: Manajemen
    ModuleSummary:
      type: object
      properties:
        id:
          type: string
          example: '1'
        title:
          type: string
          example: Dasar Kepemimpinan
        description:
          type: string
        order:
          type: integer
        chapterCount:
          type: integer
          example: 4
        chapters:
          type: array
          items:
            $ref: '#/components/schemas/ChapterSummary'
        moduleQuiz: {}
        isUnlocked:
          type: boolean
        completionPercentage:
          type: integer
    DetailSection:
      type: object
      properties:
        requirements:
          type: string
          example: Minimum 3 tahun pengalaman manajerial
        applicationDeadline:
          type: string
          format: date-time
        prerequisites:
          type: string
          example: Tidak ada
      description: >-
        Course detail sections (admissions, academics, tuition, careers, student
        experience). Fields vary per section.
    FinalExam:
      type: object
      properties:
        id:
          type: string
          example: final-exam
        title:
          type: string
          example: Final Exam
        type:
          type: string
          example: final
        questions:
          type: array
          items: {}
        minimumScore:
          type: integer
          example: 70
        attempts:
          type: integer
        maxAttempts:
          type: integer
          example: 3
        isPassed:
          type: boolean
    CertificateInfo:
      type: object
      properties:
        isEligible:
          type: boolean
        isGenerated:
          type: boolean
    ChapterSummary:
      type: object
      properties:
        id:
          type: string
          example: '1'
        title:
          type: string
          example: Apa itu Kepemimpinan
        order:
          type: integer
          example: 1
        contents:
          type: array
          items: {}
        quiz: {}
        isUnlocked:
          type: boolean
        completionPercentage:
          type: integer
          example: 0
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        API key generated under Teacher Dashboard → Kunci API. Format:
        `lms_key_...`
    cookieAuth:
      type: apiKey
      in: cookie
      name: better-auth.session_token
      description: Browser session cookie (teacher/admin). Used by frontend clients.

````