Skip to content

CoursesAPI

Defined in: v1/courses.ts:21

Handles all course-related API operations. Intended to be instantiated by a parent API client that provides the base fetch logic.

new CoursesAPI(baseFetch): CoursesAPI

Defined in: v1/courses.ts:30

Creates a new CoursesAPI instance.

<T>(endpoint, schema) => Promise<T>

A generic fetch function provided by the parent client. Handles request execution and response validation against a Zod schema.

CoursesAPI

const courses = new CoursesAPI((endpoint, schema) => myClient.fetch(endpoint, schema));

getById(id): Promise<{ course: { author_bio?: { bio?: string | null; name?: string; profile_image_url?: string | null; user_id?: number | null; }; description?: string | null; heading?: string | null; id: number; image_url?: string | null; is_published?: boolean | null; lecture_sections?: { id: number; is_published?: boolean; lectures?: { id: number; is_published?: boolean; position?: number; }[]; name?: string; position?: number; }[]; name?: string | null; }; }>

Defined in: v1/courses.ts:81

Retrieves a single course by its unique numeric ID. Includes full lecture section structure and author bio.

number

The unique identifier of the course.

Promise<{ course: { author_bio?: { bio?: string | null; name?: string; profile_image_url?: string | null; user_id?: number | null; }; description?: string | null; heading?: string | null; id: number; image_url?: string | null; is_published?: boolean | null; lecture_sections?: { id: number; is_published?: boolean; lectures?: { id: number; is_published?: boolean; position?: number; }[]; name?: string; position?: number; }[]; name?: string | null; }; }>

A promise resolving to a validated CourseDetailResponse object.

If no course exists with the given ID or the request fails.

const { course } = await coursesAPI.getById(42);

getEnrolments(courseId, page?, per?, filters?): Promise<{ enrollments: { completed_at?: string | null; enrolled_at?: string | null; expires_at?: string | null; percent_complete?: number; user_id: number; }[]; meta?: { from?: number; number_of_pages?: number; page?: number; per_page?: number; to?: number; total?: number; }; }>

Defined in: v1/courses.ts:109

Retrieves a paginated list of active enrolments for a specific course, including student progress. Optionally filter by enrolment date range and control sort direction.

number

The unique identifier of the course.

number = 1

The page number to retrieve. Defaults to 1.

number = 20

The number of results per page. Defaults to 20, maximum 100.

Optional filters to narrow the results.

string

Return only enrolments created after this date (ISO 8601).

string

Return only enrolments created before this date (ISO 8601).

"asc" | "desc"

Sort enrolments by enrolled_at. Accepts asc or desc.

Promise<{ enrollments: { completed_at?: string | null; enrolled_at?: string | null; expires_at?: string | null; percent_complete?: number; user_id: number; }[]; meta?: { from?: number; number_of_pages?: number; page?: number; per_page?: number; to?: number; total?: number; }; }>

A promise resolving to a validated EnrolmentsResponse object.

If no course exists with the given ID or the request fails.

// All enrolments for a course
const { enrollments, meta } = await coursesAPI.getEnrolments(42);
console.log(`${meta?.total} enrolled students`);
// Recent enrolments, newest first
const { enrollments } = await coursesAPI.getEnrolments(42, 1, 100, {
enrolledInAfter: '2026-01-01T00:00:00Z',
sortDirection: 'desc',
});

getLecture(courseId, lectureId): Promise<{ lecture: { attachments?: { file_extension?: string | null; file_size?: number | null; id: number; kind: "text" | "native_comments" | "video" | "audio" | "image" | "pdf" | "quiz" | "code_display" | "code_embed" | "upsell"; name: string | null; position: number | null; quiz?: { id: number; questions: { answers: …[]; correct_answers: …[]; graded: boolean; question: string; question_type: … | …; }[]; } | null; text?: string | null; url?: string | null; }[]; id: number; is_published?: boolean; lecture_section_id?: number; name?: string; position?: number; }; }>

Defined in: v1/courses.ts:136

Retrieves a single lecture within a course by its unique ID. Includes all attachments and quiz content if present.

number

The unique identifier of the course.

number

The unique identifier of the lecture.

Promise<{ lecture: { attachments?: { file_extension?: string | null; file_size?: number | null; id: number; kind: "text" | "native_comments" | "video" | "audio" | "image" | "pdf" | "quiz" | "code_display" | "code_embed" | "upsell"; name: string | null; position: number | null; quiz?: { id: number; questions: { answers: …[]; correct_answers: …[]; graded: boolean; question: string; question_type: … | …; }[]; } | null; text?: string | null; url?: string | null; }[]; id: number; is_published?: boolean; lecture_section_id?: number; name?: string; position?: number; }; }>

A promise resolving to a validated LectureDetailResponse object.

If no course or lecture exists with the given IDs or the request fails.

const { lecture } = await coursesAPI.getLecture(42, 7);

getList(page?, per?, filters?): Promise<{ courses: {[key: string]: unknown; description?: string | null; heading?: string | null; id: number; image_url?: string | null; is_published?: boolean | null; name?: string | null; }[]; meta?: { from?: number; number_of_pages?: number; page?: number; per_page?: number; to?: number; total?: number; }; }>

Defined in: v1/courses.ts:53

Retrieves a paginated list of courses with optional filters.

number = 1

The page number to retrieve. Defaults to 1.

number = 20

The number of results per page. Defaults to 20, maximum 100.

Optional filters to narrow the results.

number

Restricts results to courses by this author.

string

Restricts results to courses created at this timestamp (ISO 8601).

boolean

If true, returns only published courses.

string

Restricts results to courses matching this name.

Promise<{ courses: {[key: string]: unknown; description?: string | null; heading?: string | null; id: number; image_url?: string | null; is_published?: boolean | null; name?: string | null; }[]; meta?: { from?: number; number_of_pages?: number; page?: number; per_page?: number; to?: number; total?: number; }; }>

A promise resolving to a validated CoursesResponse object.

// All courses, first page
const { courses, meta } = await coursesAPI.getList();
console.log(`Page 1 of ${meta?.number_of_pages}${meta?.total} courses total`);
// Published courses by a specific author
const { courses } = await coursesAPI.getList(1, 100, {
isPublished: true,
authorBioId: 11111,
});

getProgress(courseId, userId, page?, per?): Promise<{ course_progress: { certificate: { issued_at: string | null; page_id: number | null; serial_number: string | null; }; completed_at: string | null; enrolled_at: string | null; id: number; lecture_sections: { id: number; lectures?: { completed_at?: string | null; id: number; is_completed?: boolean; name?: string; }[]; name?: string; }[]; percent_complete: number; }; meta?: { from?: number; number_of_pages?: number; page?: number; per_page?: number; to?: number; total?: number; }; }>

Defined in: v1/courses.ts:161

Retrieves the progress record for a specific user on a specific course. Both courseId and userId are required by the Teachable API.

number

The unique identifier of the course.

number

The unique identifier of the user. Required.

number = 1

The page number to retrieve. Defaults to 1.

number = 20

The number of results per page. Defaults to 20, maximum 100.

Promise<{ course_progress: { certificate: { issued_at: string | null; page_id: number | null; serial_number: string | null; }; completed_at: string | null; enrolled_at: string | null; id: number; lecture_sections: { id: number; lectures?: { completed_at?: string | null; id: number; is_completed?: boolean; name?: string; }[]; name?: string; }[]; percent_complete: number; }; meta?: { from?: number; number_of_pages?: number; page?: number; per_page?: number; to?: number; total?: number; }; }>

A promise resolving to a validated CourseProgressResponse object.

If either ID is invalid or the request fails.

Unlike most list endpoints, userId is a required query parameter here — omitting it will result in an API error. Progress is always scoped to a single user and course combination.

const { course_progress } = await coursesAPI.getProgress(2550579, 8167328);
console.log(`${course_progress.percent_complete}% complete`);
if (course_progress.certificate.issued_at) {
console.log(`Certificate issued: ${course_progress.certificate.issued_at}`);
}

getQuiz(courseId, lectureId, quizId): Promise<{ quiz: { id: number; kind: "quiz"; name: string | null; position: number; quiz: { id: number; questions: { answers: string[]; correct_answers: string[]; graded: boolean; question: string; question_type: "single" | "multiple"; }[]; type: "Quiz"; }; text: string | null; url: string | null; }; }>

Defined in: v1/courses.ts:209

Retrieves a specific quiz attachment by its ID, including all questions, answers, and grading configuration.

number

The unique identifier of the course.

number

The unique identifier of the lecture.

number

The unique identifier of the quiz. Retrieve via getQuizIds.

Promise<{ quiz: { id: number; kind: "quiz"; name: string | null; position: number; quiz: { id: number; questions: { answers: string[]; correct_answers: string[]; graded: boolean; question: string; question_type: "single" | "multiple"; }[]; type: "Quiz"; }; text: string | null; url: string | null; }; }>

A promise resolving to a validated LectureQuizResponse object.

If any of the provided IDs are invalid or the request fails.

const { quiz_ids } = await coursesAPI.getQuizIds(204306, 61498574);
for (const quizId of quiz_ids) {
const { quiz } = await coursesAPI.getQuiz(204306, 61498574, quizId);
console.log(`Quiz ${quiz.id} has ${quiz.quiz.questions.length} questions`);
}

getQuizIds(courseId, lectureId): Promise<{ quiz_ids: number[]; }>

Defined in: v1/courses.ts:186

Retrieves the quiz IDs associated with a specific lecture. Use the returned IDs with getQuiz or getQuizResponses.

number

The unique identifier of the course.

number

The unique identifier of the lecture.

Promise<{ quiz_ids: number[]; }>

A promise resolving to a validated QuizIdsResponse object.

If no course or lecture exists with the given IDs or the request fails.

const { quiz_ids } = await coursesAPI.getQuizIds(204306, 61498574);
console.log(`Found ${quiz_ids.length} quiz(zes) on this lecture`);
// Fetch full details for each quiz
for (const quizId of quiz_ids) {
const quiz = await coursesAPI.getQuiz(204306, 61498574, quizId);
}

getQuizResponses(courseId, lectureId, quizId): Promise<{ quiz_responses: { course_id: number; course_name?: string; graded: boolean; lecture_id: number; lecture_name?: string; responses: { percent_correct?: number | null; student_email?: string | null; student_id: number; student_name?: string | null; submitted_at?: string | null; }[]; }; }>

Defined in: v1/courses.ts:239

Retrieves all student responses for a specific quiz.

number

The unique identifier of the course.

number

The unique identifier of the lecture.

number

The unique identifier of the quiz. Retrieve via getQuizIds.

Promise<{ quiz_responses: { course_id: number; course_name?: string; graded: boolean; lecture_id: number; lecture_name?: string; responses: { percent_correct?: number | null; student_email?: string | null; student_id: number; student_name?: string | null; submitted_at?: string | null; }[]; }; }>

A promise resolving to a validated QuizResponsesResponse object.

If any of the provided IDs are invalid or the request fails.

Student grades (percent_correct) are only recorded if the ‘Record grades for this quiz’ toggle is enabled in the Teachable admin dashboard under the quiz settings. If this setting is off, percent_correct will be null for all responses even if students have completed the quiz.

const { quiz_responses } = await coursesAPI.getQuizResponses(204306, 61498574, 122226740);
console.log(`${quiz_responses.responses.length} students responded`);
quiz_responses.responses.forEach(r => {
const pct = r.percent_correct != null
? `${(r.percent_correct * 100).toFixed(0)}%`
: 'not graded';
console.log(`${r.student_name}: ${pct}`);
});

getVideo(courseId, lectureId, videoId, filters?): Promise<{ video: { id: number; media_duration?: number | null; media_type?: string; status?: string; url_thumbnail?: string | null; video_asset?: { content_type?: string | null; url?: string | null; }; }; }>

Defined in: v1/courses.ts:274

Retrieves the video asset and metadata for a specific lecture video. Returns a time-limited HLS stream URL and thumbnail URL via Hotmart’s CDN.

number

The unique identifier of the course.

number

The unique identifier of the lecture.

number

The attachment ID of the video. Use getLecture to find this value — it is the id of the attachment where kind === 'video'.

Optional filters.

number

The ID of the user watching the video. May scope the returned stream URL to a specific user session.

Promise<{ video: { id: number; media_duration?: number | null; media_type?: string; status?: string; url_thumbnail?: string | null; video_asset?: { content_type?: string | null; url?: string | null; }; }; }>

A promise resolving to a validated LectureVideoResponse object.

If any of the provided IDs are invalid or the request fails.

The stream URL in video.video_asset.url is time-limited and will expire. Always fetch a fresh response when you need a playable URL — never cache the stream URL between requests.

userId — observed to return the same response with or without this parameter in testing. May have an effect on the signed URL scope in production environments with DRM or per-user access controls.

const { video } = await coursesAPI.getVideo(1886748, 42809204, 111817954);
// Scoped to a specific user
const { video } = await coursesAPI.getVideo(1886748, 42809204, 111817954, {
userId: 8167328,
});