Programs, terms and courses
Use to see all courses of a term or Program. To locate one course the user described in words ("my programming course"), prefer academics.course.find.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
term_id?|Only courses in this term, in the term's display order
subject_code?|Only this subject
search?|Fuzzy match on code, title and alias (case and spaces ignored)
fields?array<>|Agent/MCP only: return just these fields of each course (and its id)
cursor?|next_cursor of the previous page
limit?LimitPage size
200Successful Response
application/json- response
items*array<>next_cursor*string|nullcurl -X GET 'https://example.com/programs/string/courses'{ "items": [ { "id": "string", "program_id": "string", "code": "string", "title": "string", "alias": "string", "subject_code": "string", "color": { "palette": 1 }, "resolved_color": "string", "subject_color": "string", "credits": 0, "include_in_gpa": true, "instructors": [ { "name": "string", "email": "string", "role": "string" } ], "description": "string", "website_url": "string", "planned_terms": 0, "sort_order": 0, "term_ids": [ "string" ], "end_term_id": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } ], "next_cursor": "string"}Use when the user adds a course. Get term ids from academics.term.list.
For a year-long course whose second term does not exist yet, link the current term only and set
planned_terms to 2; the term wizard offers to continue it later.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
application/json- body
code?|Course code such as 'APS105H1'
title*TitleCourse title
1 <= length <= 200alias?|Short name shown in navigation
subject_code?|Subject; parsed from the code when omitted
color?||Own color; null uses the subject's
credits?|Credits; the Program default when omitted
include_in_gpa?Include In GpaWhether the course counts for GPA
trueinstructors?array<>Instructors and TAs
items <= 20description?|Course description
website_url?|Course website
planned_terms?Planned TermsConsecutive terms the course spans; 2 for a year-long course
1 <= value <= 61term_ids*array<>Terms the course runs in; consecutive terms for a year-long one
items <= 6Successful Response
application/json- response
id*Idprogram_id*Program Idcode*string|nulltitle*Titlealias*string|nullsubject_code*Subject Codecolor*||The course's own color, if set
resolved_color*Resolved ColorColor to display: 'subject-<1..12>' (palette token) or '#rrggbb'
subject_color*Subject ColorColor the course shows without its own color (its subject's), same format
credits*Creditsinclude_in_gpa*Include In Gpainstructors*array<>description*string|nullwebsite_url*string|nullplanned_terms*Planned Termssort_order*Sort Orderterm_ids*array<string>Linked terms in chronological order
end_term_id*End Term IdThe latest linked term; grades count there
created_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X POST 'https://example.com/programs/string/courses' \ -H 'Content-Type: application/json' \ -d '{ "title": "string", "term_ids": [ "string" ]}'{ "id": "string", "program_id": "string", "code": "string", "title": "string", "alias": "string", "subject_code": "string", "color": { "palette": 1 }, "resolved_color": "string", "subject_color": "string", "credits": 0, "include_in_gpa": true, "instructors": [ { "name": "string", "email": "string", "role": "string" } ], "description": "string", "website_url": "string", "planned_terms": 0, "sort_order": 0, "term_ids": [ "string" ], "end_term_id": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Use when the user adds courses in the chat, one or several. Get term ids from
academics.term.list. For a year-long course whose second term does not exist yet, link the current
term only and set planned_terms to 2; the term wizard offers to continue it later. Courses in a
document or file (a timetable, a syllabus) go through imports.session.create instead.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
application/json- body
courses*array<>Courses to create
1 <= items <= 100Successful Response
application/json- response
items*array<>curl -X POST 'https://example.com/programs/string/courses:batch' \ -H 'Content-Type: application/json' \ -d '{ "courses": [ { "title": "string", "term_ids": [ "string" ] } ]}'{ "items": [ { "id": "string", "program_id": "string", "code": "string", "title": "string", "alias": "string", "subject_code": "string", "color": { "palette": 1 }, "resolved_color": "string", "subject_color": "string", "credits": 0, "include_in_gpa": true, "instructors": [ { "name": "string", "email": "string", "role": "string" } ], "description": "string", "website_url": "string", "planned_terms": 0, "sort_order": 0, "term_ids": [ "string" ], "end_term_id": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } ]}Use when you need the details of a course whose id you know.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
course_id*Course IdCourse id
Successful Response
application/json- response
id*Idprogram_id*Program Idcode*string|nulltitle*Titlealias*string|nullsubject_code*Subject Codecolor*||The course's own color, if set
resolved_color*Resolved ColorColor to display: 'subject-<1..12>' (palette token) or '#rrggbb'
subject_color*Subject ColorColor the course shows without its own color (its subject's), same format
credits*Creditsinclude_in_gpa*Include In Gpainstructors*array<>description*string|nullwebsite_url*string|nullplanned_terms*Planned Termssort_order*Sort Orderterm_ids*array<string>Linked terms in chronological order
end_term_id*End Term IdThe latest linked term; grades count there
created_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X GET 'https://example.com/courses/string'{ "id": "string", "program_id": "string", "code": "string", "title": "string", "alias": "string", "subject_code": "string", "color": { "palette": 1 }, "resolved_color": "string", "subject_color": "string", "credits": 0, "include_in_gpa": true, "instructors": [ { "name": "string", "email": "string", "role": "string" } ], "description": "string", "website_url": "string", "planned_terms": 0, "sort_order": 0, "term_ids": [ "string" ], "end_term_id": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Partial update: only the fields that are sent change. To move a course to other terms or make it year-long, use academics.course.set_terms.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
course_id*Course IdCourse id
application/json- body
code?|Code
title?|Title
alias?|Alias
subject_code?|Subject code
color?||Own color, or null for the subject's
credits?|Credits
include_in_gpa?|Counts for GPA
instructors?array<>|Replaces all instructors
description?|Description
website_url?|Website
planned_terms?|Consecutive terms the course spans
sort_order?|Display position (then code, title)
Successful Response
application/json- response
id*Idprogram_id*Program Idcode*string|nulltitle*Titlealias*string|nullsubject_code*Subject Codecolor*||The course's own color, if set
resolved_color*Resolved ColorColor to display: 'subject-<1..12>' (palette token) or '#rrggbb'
subject_color*Subject ColorColor the course shows without its own color (its subject's), same format
credits*Creditsinclude_in_gpa*Include In Gpainstructors*array<>description*string|nullwebsite_url*string|nullplanned_terms*Planned Termssort_order*Sort Orderterm_ids*array<string>Linked terms in chronological order
end_term_id*End Term IdThe latest linked term; grades count there
created_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X PATCH 'https://example.com/courses/string' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "string", "program_id": "string", "code": "string", "title": "string", "alias": "string", "subject_code": "string", "color": { "palette": 1 }, "resolved_color": "string", "subject_color": "string", "credits": 0, "include_in_gpa": true, "instructors": [ { "name": "string", "email": "string", "role": "string" } ], "description": "string", "website_url": "string", "planned_terms": 0, "sort_order": 0, "term_ids": [ "string" ], "end_term_id": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Irreversible. Use only when the user clearly asks to delete the course.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
course_id*Course IdCourse id
Successful Response
application/json- response
deleted?Deletedtruecurl -X DELETE 'https://example.com/courses/string'{ "deleted": true}Replaces the course's terms. They must belong to its Program and be next to each other in time.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
course_id*Course IdCourse id
application/json- body
term_ids*array<>All terms of the course; must be consecutive
items <= 6Successful Response
application/json- response
id*Idprogram_id*Program Idcode*string|nulltitle*Titlealias*string|nullsubject_code*Subject Codecolor*||The course's own color, if set
resolved_color*Resolved ColorColor to display: 'subject-<1..12>' (palette token) or '#rrggbb'
subject_color*Subject ColorColor the course shows without its own color (its subject's), same format
credits*Creditsinclude_in_gpa*Include In Gpainstructors*array<>description*string|nullwebsite_url*string|nullplanned_terms*Planned Termssort_order*Sort Orderterm_ids*array<string>Linked terms in chronological order
end_term_id*End Term IdThe latest linked term; grades count there
created_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X PUT 'https://example.com/courses/string/terms' \ -H 'Content-Type: application/json' \ -d '{ "term_ids": [ "string" ]}'{ "id": "string", "program_id": "string", "code": "string", "title": "string", "alias": "string", "subject_code": "string", "color": { "palette": 1 }, "resolved_color": "string", "subject_color": "string", "credits": 0, "include_in_gpa": true, "instructors": [ { "name": "string", "email": "string", "role": "string" } ], "description": "string", "website_url": "string", "planned_terms": 0, "sort_order": 0, "term_ids": [ "string" ], "end_term_id": "string", "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Use to find the Program ids of the user, e.g. before listing terms or courses when no Program is given. Most users have exactly one Program.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
Successful Response
application/json- response
items*array<>curl -X GET 'https://example.com/programs'{ "items": [ { "id": "string", "name": "string", "institution": "string", "timezone": "string", "default_course_credits": 0, "credit_requirement": 0, "subject_colors": { "property1": { "palette": 1 }, "property2": { "palette": 1 } }, "sort_order": 0, "term_count": 0, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } ]}Use only when the user explicitly wants a new, separate Program, e.g. a second degree. Do not use to add a term or a course; use academics.term.create or academics.course.create_many.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
application/json- body
name*NameProgram name, e.g. 'BASc Computer Engineering'
1 <= length <= 200institution?|School or university
timezone*TimezoneIANA time zone of the school, e.g. 'America/Toronto'
1 <= length <= 64default_course_credits?Default Course CreditsCredits a new course gets when none are given
0 <= value <= 1000.5credit_requirement?|Credits needed to graduate, if known
setup?Choices of other modules' setup fields (e.g. a GPA scale preset), passed on to them with the academics.program.created event
Successful Response
application/json- response
id*Idname*Nameinstitution*string|nulltimezone*Timezonedefault_course_credits*Default Course Creditscredit_requirement*number|nullsubject_colors*Color of each subject code
sort_order*Sort Orderterm_count*Term Countcourse_count*Course Countcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X POST 'https://example.com/programs' \ -H 'Content-Type: application/json' \ -d '{ "name": "string", "timezone": "string"}'{ "id": "string", "name": "string", "institution": "string", "timezone": "string", "default_course_credits": 0, "credit_requirement": 0, "subject_colors": { "property1": { "palette": 1 }, "property2": { "palette": 1 } }, "sort_order": 0, "term_count": 0, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Use when you need a Program's details such as its time zone or credit goal.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
Successful Response
application/json- response
id*Idname*Nameinstitution*string|nulltimezone*Timezonedefault_course_credits*Default Course Creditscredit_requirement*number|nullsubject_colors*Color of each subject code
sort_order*Sort Orderterm_count*Term Countcourse_count*Course Countcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X GET 'https://example.com/programs/string'{ "id": "string", "name": "string", "institution": "string", "timezone": "string", "default_course_credits": 0, "credit_requirement": 0, "subject_colors": { "property1": { "palette": 1 }, "property2": { "palette": 1 } }, "sort_order": 0, "term_count": 0, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Partial update: only the fields that are sent change. Get the Program with academics.program.get first when you need its current values. Terms and courses are changed with academics.term.update and academics.course.update.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
application/json- body
name?|Program name
institution?|School, or null
timezone?|IANA time zone
default_course_credits?|Credits a new course gets
credit_requirement?|Credits needed to graduate, or null
sort_order?|Position in the Program switcher
Successful Response
application/json- response
id*Idname*Nameinstitution*string|nulltimezone*Timezonedefault_course_credits*Default Course Creditscredit_requirement*number|nullsubject_colors*Color of each subject code
sort_order*Sort Orderterm_count*Term Countcourse_count*Course Countcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X PATCH 'https://example.com/programs/string' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "string", "name": "string", "institution": "string", "timezone": "string", "default_course_credits": 0, "credit_requirement": 0, "subject_colors": { "property1": { "palette": 1 }, "property2": { "palette": 1 } }, "sort_order": 0, "term_count": 0, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Irreversible. Use only when the user clearly asks to delete the whole Program. To remove one term or course use academics.term.delete or academics.course.delete.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
Successful Response
application/json- response
deleted?Deletedtruecurl -X DELETE 'https://example.com/programs/string'{ "deleted": true}Use when the user wants every course of a subject in another color. To color a
single course differently, use academics.course.update with color.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
subject_code*Subject CodeSubject code such as 'APS'
application/json- body
color*|Palette slot or custom hex color
Successful Response
application/json- response
id*Idname*Nameinstitution*string|nulltimezone*Timezonedefault_course_credits*Default Course Creditscredit_requirement*number|nullsubject_colors*Color of each subject code
sort_order*Sort Orderterm_count*Term Countcourse_count*Course Countcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X PUT 'https://example.com/programs/string/subject-colors/string' \ -H 'Content-Type: application/json' \ -d '{ "color": { "palette": 1 }}'{ "id": "string", "name": "string", "institution": "string", "timezone": "string", "default_course_credits": 0, "credit_requirement": 0, "subject_colors": { "property1": { "palette": 1 }, "property2": { "palette": 1 } }, "sort_order": 0, "term_count": 0, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Use to find a term id, or which term is current (is_current), before creating
courses or answering questions about a semester.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram id
Successful Response
application/json- response
items*array<>Sorted by start date
curl -X GET 'https://example.com/programs/string/terms'{ "items": [ { "id": "string", "program_id": "string", "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24", "breaks": [ { "id": "string", "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" } ], "count_break_weeks": true, "is_current": true, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" } ]}Use when the user starts a new semester. Check academics.term.list first so the
term does not exist already. courses creates courses in the new term; continue_course_ids
extends year-long courses of the previous term into it.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
program_id*Program IdProgram to add the term to
application/json- body
name*NameE.g. 'Fall 2026'
1 <= length <= 200start_date*Start DateFirst day of the term
dateend_date*End DateLast day of the term
datebreaks?array<>Reading weeks and holidays
items <= 20count_break_weeks?Count Break WeeksWhether break weeks get a week number
falsecourses?array<>Courses to create in the new term
items <= 50continue_course_ids?array<>Year-long courses of the previous term that continue into the new term (from academics.course.list of that term)
items <= 50Successful Response
application/json- response
term*course_ids*array<string>Ids of the created courses, in input order
continued_course_ids*array<string>curl -X POST 'https://example.com/programs/string/terms' \ -H 'Content-Type: application/json' \ -d '{ "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24"}'{ "term": { "id": "string", "program_id": "string", "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24", "breaks": [ { "id": "string", "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" } ], "count_break_weeks": true, "is_current": true, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z" }, "course_ids": [ "string" ], "continued_course_ids": [ "string" ]}Use when you need a term's dates, reading weeks or holidays. Find the id with academics.term.list; for teaching week numbers use academics.term.get_weeks. Changes go through academics.term.update.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
term_id*Term IdTerm id
Successful Response
application/json- response
id*Idprogram_id*Program Idname*Namestart_date*Start Datedateend_date*End Datedatebreaks*array<>count_break_weeks*Count Break Weeksis_current*Is CurrentThe term the Program is in now (see academics rules)
course_count*Course Countcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X GET 'https://example.com/terms/string'{ "id": "string", "program_id": "string", "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24", "breaks": [ { "id": "string", "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" } ], "count_break_weeks": true, "is_current": true, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Partial update. breaks replaces the whole list; keep the ids of breaks that
stay. Fails with academics.course_terms_not_adjacent when new dates would separate the terms of
a year-long course.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
term_id*Term IdTerm id
application/json- body
name?|Term name
start_date?|First day
end_date?|Last day
breaks?array<>|Replaces all breaks
count_break_weeks?|Whether break weeks get a week number
Successful Response
application/json- response
id*Idprogram_id*Program Idname*Namestart_date*Start Datedateend_date*End Datedatebreaks*array<>count_break_weeks*Count Break Weeksis_current*Is CurrentThe term the Program is in now (see academics rules)
course_count*Course Countcreated_at*Created Atdate-timeupdated_at*Updated Atdate-timecurl -X PATCH 'https://example.com/terms/string' \ -H 'Content-Type: application/json' \ -d '{}'{ "id": "string", "program_id": "string", "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24", "breaks": [ { "id": "string", "name": "string", "start_date": "2019-08-24", "end_date": "2019-08-24" } ], "count_break_weeks": true, "is_current": true, "course_count": 0, "created_at": "2019-08-24T14:15:22Z", "updated_at": "2019-08-24T14:15:22Z"}Irreversible. Year-long courses that also run in other terms are kept and only lose this term. Show academics.term.preview_delete to the user first.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
term_id*Term IdTerm id
Successful Response
application/json- response
deleted_course_count*Deleted Course Countkept_course_count*Kept Course Countcurl -X DELETE 'https://example.com/terms/string'{ "deleted_course_count": 0, "kept_course_count": 0}Use to translate between dates and week numbers ("week 6", "reading week"), e.g. to resolve "the Friday of week 3". Week 1 is the week the term starts in.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
term_id*Term IdTerm id
Successful Response
application/json- response
term_id*Term Idtimezone*Timezoneweek_start*Week Start1 = Monday, 7 = Sunday
17weeks*array<>today*TodayToday in the Program's time zone
datetoday_week*|Index into weeks of today's week, if in term
curl -X GET 'https://example.com/terms/string/calendar-info'{ "term_id": "string", "timezone": "string", "week_start": 1, "weeks": [ { "start_date": "2019-08-24", "end_date": "2019-08-24", "number": 0, "break_info": { "id": "string", "name": "string" } } ], "today": "2019-08-24", "today_week": 0}Use before academics.term.delete to tell the user what will be deleted.
semestra_session<token>Set by the sign-in endpoints for the web app. Requests other than GET, HEAD and OPTIONS also need the X-Semestra-CSRF header set to the semestra_csrf cookie.
term_id*Term IdTerm id
Successful Response
application/json- response
deleted_course_count*Deleted Course CountCourses only in this term, deleted with it
kept_course_count*Kept Course CountMulti-term courses that stay in their other terms
deleted_course_ids*array<string>kept_course_ids*array<string>curl -X GET 'https://example.com/terms/string/delete-preview'{ "deleted_course_count": 0, "kept_course_count": 0, "deleted_course_ids": [ "string" ], "kept_course_ids": [ "string" ]}