# info.description
# Introduction
Penn Courses ([GitHub](https://github.com/pennlabs/penn-courses)) is the umbrella
categorization for [Penn Labs](https://pennlabs.org/)
products designed to help students navigate the course registration process. It currently
includes three products, each with their own API documented on this page:
Penn Course Alert, Penn Course Plan, and Penn Course Review.

See `Penn Labs Notion > Penn Courses` for more details on each of our (currently) three apps.

For instructions on how to maintain this documentation while writing code,
see the comments in `backend/PennCourses/docs_settings.py` (it is easy, and will be helpful
for maintaining Labs knowledge in spite of our high member turnover rate).

See our [GitHub](https://github.com/pennlabs/penn-courses) repo for instructions on
installation, running in development, and loading in course data for development. Visit
the `/admin/doc/` route ([link](/admin/doc/)) for the backend documentation generated by Django
(admin account required, which can be made by running
`python manage.py createsuperuser` in terminal/CLI).

# Unified Penn Courses
By virtue of the fact that all Penn Courses products deal with, well, courses,
it would make sense for all three products to share the same backend.

We realized the necessity of a unified backend when attempting to design a new Django backend
for Penn Course Plan. We like to live by the philosophy of keeping it
[DRY](https://en.wikipedia.org/wiki/Don't_repeat_yourself), and
PCA and PCP's data models both need to reference course and
section information. We could have simply copied over code (a bad idea)
or created a shared reusable Django app (a better idea) for course data,
but each app would still need to download copies of the same data.
Additionally, this will help us build integrations between our Courses products.

# Authentication
PCx user authentication is handled by platform's Penn Labs Accounts Engine.
See [Penn Labs Notion > Platform > The Accounts Engine](https://www.notion.so/pennlabs/The-Accounts-Engine-726ccf8875e244f4b8dbf8a8f2c97a87?pvs=4)
for extensive documentation and links to repositories for this system. When tags or routes
are described as requiring user authentication, they are referring to this system.

I highly recommend the [official video course on OAuth2](https://oauth.net/2/) (by Aaron Parecki),
then the Platform Notion docs on the "Accounts Engine" for anyone who wants to understand
Labs authentication better. Platform is our OAuth2 "Authorization Server",
and Django Labs Accounts is an OAuth2 client run by our Django backends (Clubs, Penn Courses, etc),
exposing client-facing authentication routes like `penncourseplan.com/accounts/login`.
There's also this Wikipedia page explaining [Shibboleth](https://en.wikipedia.org/wiki/Shibboleth_(software))
(which is used by Penn for authentication, and by the Platform authorization server).

See the Django docs for more on Django's features for
[User Authentication](https://docs.djangoproject.com/en/3.0/topics/auth/),
which are used by PCX apps, as part of Platform's accounts system.

# paths./accounts/me/.get.description
(GET `/accounts/me/`)

This view exposes the Penn Labs Accounts User object.

User authentication required.

# paths./accounts/me/.get.responses.200.content.application/json.schema.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# paths./accounts/me/.get.responses.200.content.application/json.schema.properties.profile.properties.email.description
The email of the User. Defaults to null.

# paths./accounts/me/.get.responses.200.content.application/json.schema.properties.profile.properties.phone.description
The phone number of the user. Defaults to null.
The phone number will be stored in the E164 format, but any form parseable by the
[phonenumbers library](https://pypi.org/project/phonenumbers/)
will be accepted and converted to E164 format automatically upon saving.

# paths./accounts/me/.get.responses.200.content.application/json.schema.properties.profile.properties.push_notifications.description
Defaults to False, changed to True if the User enables mobile push notifications
for PCA, rather than text notifications.

# paths./accounts/me/.get.responses.200.content.application/json.schema.properties.profile.description
The user profile object, storing collected info about the user.

# paths./accounts/me/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./accounts/me/.put.description
(PUT `/accounts/me/`)

This view exposes the Penn Labs Accounts User object.

User authentication required.

# paths./accounts/me/.put.requestBody.content.application/json.schema.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# paths./accounts/me/.put.requestBody.content.application/json.schema.properties.profile.properties.email.description
The email of the User. Defaults to null.

# paths./accounts/me/.put.requestBody.content.application/json.schema.properties.profile.properties.phone.description
The phone number of the user. Defaults to null.
The phone number will be stored in the E164 format, but any form parseable by the
[phonenumbers library](https://pypi.org/project/phonenumbers/)
will be accepted and converted to E164 format automatically upon saving.

# paths./accounts/me/.put.requestBody.content.application/json.schema.properties.profile.properties.push_notifications.description
Defaults to False, changed to True if the User enables mobile push notifications
for PCA, rather than text notifications.

# paths./accounts/me/.put.requestBody.content.application/json.schema.properties.profile.description
The user profile object, storing collected info about the user.

# paths./accounts/me/.put.responses.200.content.application/json.schema.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# paths./accounts/me/.put.responses.200.content.application/json.schema.properties.profile.properties.email.description
The email of the User. Defaults to null.

# paths./accounts/me/.put.responses.200.content.application/json.schema.properties.profile.properties.phone.description
The phone number of the user. Defaults to null.
The phone number will be stored in the E164 format, but any form parseable by the
[phonenumbers library](https://pypi.org/project/phonenumbers/)
will be accepted and converted to E164 format automatically upon saving.

# paths./accounts/me/.put.responses.200.content.application/json.schema.properties.profile.properties.push_notifications.description
Defaults to False, changed to True if the User enables mobile push notifications
for PCA, rather than text notifications.

# paths./accounts/me/.put.responses.200.content.application/json.schema.properties.profile.description
The user profile object, storing collected info about the user.

# paths./accounts/me/.put.responses.403.description
Access denied (missing or improper authentication).

# paths./accounts/me/.patch.description
(PATCH `/accounts/me/`)

This view exposes the Penn Labs Accounts User object.

User authentication required.

# paths./accounts/me/.patch.requestBody.content.application/json.schema.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# paths./accounts/me/.patch.requestBody.content.application/json.schema.properties.profile.properties.email.description
The email of the User. Defaults to null.

# paths./accounts/me/.patch.requestBody.content.application/json.schema.properties.profile.properties.phone.description
The phone number of the user. Defaults to null.
The phone number will be stored in the E164 format, but any form parseable by the
[phonenumbers library](https://pypi.org/project/phonenumbers/)
will be accepted and converted to E164 format automatically upon saving.

# paths./accounts/me/.patch.requestBody.content.application/json.schema.properties.profile.properties.push_notifications.description
Defaults to False, changed to True if the User enables mobile push notifications
for PCA, rather than text notifications.

# paths./accounts/me/.patch.requestBody.content.application/json.schema.properties.profile.description
The user profile object, storing collected info about the user.

# paths./accounts/me/.patch.responses.200.content.application/json.schema.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# paths./accounts/me/.patch.responses.200.content.application/json.schema.properties.profile.properties.email.description
The email of the User. Defaults to null.

# paths./accounts/me/.patch.responses.200.content.application/json.schema.properties.profile.properties.phone.description
The phone number of the user. Defaults to null.
The phone number will be stored in the E164 format, but any form parseable by the
[phonenumbers library](https://pypi.org/project/phonenumbers/)
will be accepted and converted to E164 format automatically upon saving.

# paths./accounts/me/.patch.responses.200.content.application/json.schema.properties.profile.properties.push_notifications.description
Defaults to False, changed to True if the User enables mobile push notifications
for PCA, rather than text notifications.

# paths./accounts/me/.patch.responses.200.content.application/json.schema.properties.profile.description
The user profile object, storing collected info about the user.

# paths./accounts/me/.patch.responses.403.description
Access denied (missing or improper authentication).

# paths./api/review/course/{course_code}.get.description
(GET `/api/review/course/{course_code}`)

User authentication required.

# paths./api/review/course/{course_code}.get.parameters[].description
The dash-joined department and code of the course you want reviews for, e.g. `CIS-120` for CIS-120.

# paths./api/review/course/{course_code}.get.parameters[].description
Optionally specify the semester of the desired course (defaults to most recent course with the specified course code).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.code.description
The dash-joined department and most-recent code of this course, e.g. `CIS-1200`.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.last_offered_sem_if_superceded.description
The last semester in which this course was offered, if it has been superseded by a more recent course (with the same full code).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.aliases.description
A list of courses that are crosslisted with this course (each represented by its dash-joined department and code).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.historical_codes.description
The historical lineage of primary course codes that have represented this course (from most recent to oldest).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.historical_codes.items.properties.full_code.description
The dash-joined department and course code.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.historical_codes.items.properties.branched_from.description
A flag indicating whether this code was branched into multiple new codes (e.g. in fall 2022). In these cases we should link to the old course on PCR because its reviews will not be included on the same page (unlike linear links).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.historical_codes.items.properties.semester.description
The most recent semester this code was used (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2022C` for fall 2022.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.name.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.description.description
The description of the course, e.g. 'A fast-paced introduction to the fundamental concepts of programming... [etc.]' for CIS-120.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.latest_semester.description
The most recent semester this course was offered (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2022C` for fall 2022.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.registration_metrics.description
True if this course has registration metrics that you can access via the Retrieve Plots route.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.num_sections.description
The number of sections belonging to this course (excluding non-primary crosslisted sections) across all semesters (that we have data for).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.num_sections_recent.description
The number of sections belonging to this course (excluding non-primary crosslisted sections) in its most recent semester.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.average_reviews.description
This course's average reviews across all of its sections (excluding non-primary crosslisted sections) from all semesters. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.average_reviews.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.average_reviews.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.average_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.average_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.average_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.recent_reviews.description
This course's average reviews across all of its sections (excluding non-primary crosslisted sections) from the most recent semester. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.recent_reviews.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.recent_reviews.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.recent_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.recent_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.recent_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.num_semesters.description
The number of semesters for which this course has been taught (that we have data for).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.description
Reviews for this course broken down by instructor. Note that each key in this subdictionary is a stringified instructor id (indicated by `STRINGIFIED_INSTRUCTOR_ID`; this is not an actual key but a placeholder for potentially many keys).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.description
This key `STRINGIFIED_INSTRUCTOR_ID` is a placeholder for potentially many stringified instructor id keys.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.id.description
The integer id of this instructor; note that this is just the int version of this subdictionary's key in the parent dictionary.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.average_reviews.description
This instructor's average reviews across all of the sections of this course that he/she has taught. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.average_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.average_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.average_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.recent_reviews.description
This instructor's average reviews across all of the sections of this course that he/she has taught in his/her most recent semester teaching this course that has review data. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.recent_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.recent_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.recent_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.latest_semester.description
The most recent semester this instructor taught this course (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/review/course/{course_code}.get.responses.200.content.application/json.schema.properties.instructors.properties.STRINGIFIED_INSTRUCTOR_ID.properties.num_semesters.description
The number of semesters that this instructor has taught this course (that we have data for).

# paths./api/review/course/{course_code}.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/review/course/{course_code}.get.responses.404.description
Course with given course_code not found.

# paths./api/review/course_plots/{course_code}.get.description
(GET `/api/review/course_plots/{course_code}`)

Get all PCR plots for a given course.

User authentication required.

# paths./api/review/course_plots/{course_code}.get.parameters[].description
The dash-joined department and code of the course you want plots for, e.g. `CIS-120` for CIS-120.

# paths./api/review/course_plots/{course_code}.get.parameters[].description
Optionally specify the semester of the desired course (defaults to most recent course with the specified course code).

# paths./api/review/course_plots/{course_code}.get.parameters[].description
A comma-separated list of instructor IDs with which to filter the sections underlying the returned plots.Note that if only invalid instructor IDs are present, plot response fields will be null or 0.

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.code.description
The dash-joined department and most-recent (across all codes representing the topic) code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.current_add_drop_period.description
The start and end dates of the upcoming/current semester's add/drop period

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.current_add_drop_period.properties.start.description
A string datetime representation of the start of the current/upcoming add/drop period.

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.current_add_drop_period.properties.end.description
A string datetime representation of the end of the current/upcoming add/drop period.

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.average_plots.description
This course's plots (PCA demand, percent sections open), averaged across all of its sections from all semesters. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.average_plots.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.average_plots.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.average_plots.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.average_plots.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.average_plots.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.recent_plots.description
This course's plots (PCA demand, percent sections open), averaged across all of its sections from the most recent semester before the current semester. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.recent_plots.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.recent_plots.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.recent_plots.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.recent_plots.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/course_plots/{course_code}.get.responses.200.content.application/json.schema.properties.recent_plots.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/course_plots/{course_code}.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/review/course_plots/{course_code}.get.responses.404.description
Course with given course_code not found.

# paths./api/review/instructor/{instructor_id}.get.description
(GET `/api/review/instructor/{instructor_id}`)

Get all reviews for a given instructor, aggregated by course.

User authentication required.

# paths./api/review/instructor/{instructor_id}.get.parameters[].description
The integer id of the instructor you want reviews for. Note that you can get the relative path for any instructor including this id by using the `url` field of objects in the `instructors` list returned by Retrieve Autocomplete Data.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.num_sections_recent.description
The number of sections this instructor taught in his/her most recent semester teaching.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.num_sections.description
The number of sections this instructor has taught (that we have data for).

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.average_reviews.description
This instructor's average reviews across all of his/her taught sections from all semesters. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.average_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.average_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.average_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.recent_reviews.description
This instructor's average reviews across all of his/her taught sections from only his/her most recent semester teaching that has review data. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.recent_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.recent_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.recent_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.num_semesters.description
The number of semesters this instructor has taught (that we have data for).

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.description
Reviews for this instructor broken down by the courses he/she has taught. Note that each key in this subdictionary is the course full code (indicated by `COURSE_FULL_CODE`; this is not an actual key but a placeholder for potentially many keys).

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.description
This key `COURSE_FULL_CODE` is a placeholder for potentially many course full code keys. Each full code is the dash-joined department and most-recent (across all codes representing the topic) code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.full_code.description
The dash-joined department and most-recent (across all codes representing the topic) code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.description
This course's average reviews across all of its sections taught by this instructor from all semesters. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.description
This course's average reviews across all of its sections taught by this instructor from the most recent semester. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.latest_semester.description
The most recent semester this course was taught by this instructor (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.num_semesters.description
The number of semesters in which this course was taught by this instructor (that we have data for).

# paths./api/review/instructor/{instructor_id}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.name.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# paths./api/review/instructor/{instructor_id}.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/review/instructor/{instructor_id}.get.responses.404.description
Instructor with given instructor_id not found.

# paths./api/review/department/{department_code}.get.description
(GET `/api/review/department/{department_code}`)

Get reviews for all courses in a department.

User authentication required.

# paths./api/review/department/{department_code}.get.parameters[].description
The department code you want reviews for, e.g. `CIS` for the CIS department.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.code.description
The department code, e.g. `CIS` for the CIS department.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.name.description
The name of the department, e.g. 'Computer and Information Sci' for the CIS department.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.description
Reviews for this department broken down by its courses. Note that each key in this subdictionary is the course full code (indicated by `COURSE_FULL_CODE`; this is not an actual key but a placeholder for potentially many keys).

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.description
This key `COURSE_FULL_CODE` is a placeholder for potentially many course full code keys. Each full code is the dash-joined department and most-recent (across all codes representing the topic) code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.id.description
The dash-joined department and most-recent (across all codes representing the topic) code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.description
This course's average reviews across all of its sections from all semesters. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.average_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.description
This course's average reviews across all of its sections from the most recent semester. Note that if any of these subfields are missing or null, that means the subfield is not applicable or missing from our data (you should check for null values).

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.recent_reviews.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.latest_semester.description
The most recent semester this course was taught (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.num_semesters.description
The number of semesters this class has been taught (that we have data for).

# paths./api/review/department/{department_code}.get.responses.200.content.application/json.schema.properties.courses.properties.COURSE_FULL_CODE.properties.name.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# paths./api/review/department/{department_code}.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/review/department/{department_code}.get.responses.404.description
Department with the given department_code not found.

# paths./api/review/course/{course_code}/{instructor_id}.get.description
(GET `/api/review/course/{course_code}/{instructor_id}`)

Get the review history of an instructor teaching a course.

User authentication required.

# paths./api/review/course/{course_code}/{instructor_id}.get.parameters[].description
The dash-joined department and code of the course you want reviews for, e.g. `CIS-120` for CIS-120.

# paths./api/review/course/{course_code}/{instructor_id}.get.parameters[].description
The integer id of the instructor you want reviews for.

# paths./api/review/course/{course_code}/{instructor_id}.get.parameters[].description
Optionally specify the semester of the desired course (defaults to most recent course with the specified course code).

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.course_code.description
The dash-joined department and most-recent (across all codes representing the topic) code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.description
The sections of this course taught by this instructor.

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.course_code.description
The dash-joined department and course code of the section, `CIS-120` for CIS-120-001.

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.course_name.description
The title of the section's course, e.g. 'Programming Languages and Techniques I' for CIS-120-001.

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.activity.description
The activity of the section. Options: `['Undefined', 'Clinic', 'Clinical Rotation', 'Dissertation Abroad', 'Dissertation', 'Doctoral Program Exchange', 'Field Work', 'Hybrid', 'Independent Study', 'Lab', 'Lecture', 'Masters Thesis', 'Online', 'Practicum', 'Recitation', 'Seminar', 'Senior Thesis', 'Studio', None]`

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.semester.description
The semester this section was taught (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.forms_returned.description
The number of review responses collected for this section (or null if this section does not have review data).

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.forms_produced.description
The final enrollment of this section (or null if this section does not have review data).

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.ratings.properties.rSemesterCalc.description
The oldest semester included in these review aggregations (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. This field will not be missing.

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.ratings.properties.rSemesterCount.description
The number of semesters included in these review aggregations. This field will not be missing.

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.ratings.properties.rFinalEnrollment.description
Average Final Enrollment at the End of the Semester

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.ratings.properties.rNumOpenings.description
Average Number of Openings During Add/Drop

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.ratings.properties.rFilledInAdvReg.description
Average Percent of Sections Completely Filled During Advance Registration

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.200.content.application/json.schema.properties.sections.items.properties.comments.description
A textual description of the section, as well as common sentiment about it from reviews.

# paths./api/review/course/{course_code}/{instructor_id}.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/review/autocomplete.get.description
(GET `/api/review/autocomplete`)

Autocomplete entries for Courses, departments, instructors. All objects have title, description,
and url. This route does not have any path parameters or query parameters, it just dumps
all the information necessary for frontend-based autocomplete. It is also cached
to improve performance.

# paths./api/review/autocomplete.get.responses.200.content.application/json.schema.properties.courses.items.properties.title.description
The dash-joined department and code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/review/autocomplete.get.responses.200.content.application/json.schema.properties.courses.items.properties.desc.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# paths./api/review/autocomplete.get.responses.200.content.application/json.schema.properties.courses.items.properties.url.description
The relative route through which this course's reviews can be accessed (a prefix of `/api/review/` is assumed).

# paths./api/review/autocomplete.get.responses.200.content.application/json.schema.properties.departments.items.properties.title.description
The string department code, e.g. `CIS` for the CIS department.

# paths./api/review/autocomplete.get.responses.200.content.application/json.schema.properties.departments.items.properties.desc.description
The name of the department, e.g. 'Computer and Information Sci' for the CIS department.

# paths./api/review/autocomplete.get.responses.200.content.application/json.schema.properties.departments.items.properties.url.description
The relative route through which this department's reviews can be accessed (a prefix of `/api/review/` is assumed).

# paths./api/review/autocomplete.get.responses.200.content.application/json.schema.properties.instructors.items.properties.desc.description
A comma-separated string list of department codes to which this instructor belongs.

# paths./api/review/autocomplete.get.responses.200.content.application/json.schema.properties.instructors.items.properties.url.description
The relative route through which this instructor's reviews can be accessed (a prefix of `/api/review/` is assumed).

# paths./api/plan/{schedule_pk}/calendar/.get.description
(GET `/api/plan/{schedule_pk}/calendar/`)

Return a .ics file of the user's selected schedule

# paths./api/plan/{schedule_pk}/calendar/.get.parameters[].description
The PCP id of the schedule you want to export.

# paths./api/plan/schedules/.get.description
(GET `/api/plan/schedules/`)

Get a list of all the logged-in user's schedules for the current semester. Normally, the
response code is 200. Each object in the returned list is of the same form as the object
returned by Retrieve Schedule.

User authentication required.

# paths./api/plan/schedules/.get.responses.200.content.application/json.schema.items.properties.semester.description
The academic semester planned out by the schedule (of the form YYYYx where x is A
[for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/plan/schedules/.get.responses.200.content.application/json.schema.items.properties.name.description
The user's nick-name for the schedule. No two schedules can match in all of the fields
`[name, semester, person]`

# paths./api/plan/schedules/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/schedules/.post.description
(POST `/api/plan/schedules/`)

Use this route to create a schedule for the authenticated user.
This route will return a 201 if it succeeds (or a 200 if the POST specifies an id which already
is associated with a schedule, causing that schedule to be updated), with a JSON in the same
format as if you were to get the schedule you just posted (the 200 response schema for Retrieve
Schedule). If any of the given sections are invalid, a 404 is returned. If any two sections
in the `sections` list have differing semesters, a 400 is returned.

Note that your posted object can include either a `sections` field or a `meetings` field to
list all sections you would like to be in the schedule (mentioned above).
If both fields exist in the object, only `meetings` will be considered. In all cases,
the field in question will be renamed to `sections`, so that will be the field name whenever
you GET from the server. (Sorry for this confusing behavior, it is grandfathered in
from when the PCP frontend was referring to sections as meetings, before schedules were
stored on the backend.)

User authentication required.

# paths./api/plan/schedules/.post.requestBody.content.application/json.schema.properties.id.description
Optionally include an `id` to update the schedule
with the given id (if such a schedule exists),
or otherwise create a new schedule with that id.

# paths./api/plan/schedules/.post.requestBody.content.application/json.schema.properties.semester.description
The semester of the schedule (of the form YYYYx where x is
A [for spring], B [summer], or C [fall]), e.g. 2019C for fall 2019.
Can also be specified in Path format (YYYYxx, where xx is
10 [for spring], 20 [summer], or 30 [fall]), e.g. 201930 for fall 2019.
You can omit this field and the first semester found in the
sections/meetings list will be used instead (or if no semester
is specified in the request, the current semester open for registration
will be used).

# paths./api/plan/schedules/.post.requestBody.content.application/json.schema.properties.sections.description
The sections in the schedule (can also be called "meetings").

# paths./api/plan/schedules/.post.requestBody.content.application/json.schema.properties.sections.items.properties.id.description
A course code of the form DEPT-XXXX (e.g. CIS-1200), or a Path CRN

# paths./api/plan/schedules/.post.requestBody.content.application/json.schema.properties.sections.items.properties.semester.description
Optionally specify a section semester if you want the
backend to validate that all sections have the same
semester as the claimed schedule semester (taking the
first section semester as the schedule semester if none
is specified). Format is same as schedule semester.

# paths./api/plan/schedules/.post.requestBody.content.application/json.schema.properties.name.description
The user's nick-name for the schedule. No two schedules can match in all of the fields [name, semester, person]. Optional for PUT path registration.

# paths./api/plan/schedules/.post.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/schedules/.post.responses.200.description
Schedule successfully updated (a schedule with the specified id already existed).

# paths./api/plan/schedules/{id}/.get.description
(GET `/api/plan/schedules/{id}/`)

Get one of the logged-in user's schedules for the current semester, using the schedule's ID.
If a schedule with the specified ID exists, a 200 response code is returned, along with
the schedule object.
If the given id does not exist, a 404 is returned.

User authentication required.

# paths./api/plan/schedules/{id}/.get.parameters[].description
A unique integer value identifying this schedule.

# paths./api/plan/schedules/{id}/.get.responses.200.content.application/json.schema.properties.semester.description
The academic semester planned out by the schedule (of the form YYYYx where x is A
[for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/plan/schedules/{id}/.get.responses.200.content.application/json.schema.properties.name.description
The user's nick-name for the schedule. No two schedules can match in all of the fields
`[name, semester, person]`

# paths./api/plan/schedules/{id}/.get.responses.200.description
Successful retrieve (the specified schedule exists).

# paths./api/plan/schedules/{id}/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/schedules/{id}/.get.responses.404.description
No schedule with the specified id exists.

# paths./api/plan/schedules/{id}/.put.description
(PUT `/api/plan/schedules/{id}/`)

Send a put request to this route to update a specific schedule.
The `id` path parameter (an integer) specifies which schedule you want to update. [You can also
pass `path` for the `id` path parameter, in order to create/update a Path Registration schedule
for the user. But to do this, you must be authenticated via Platform's token auth for IPC,
e.g. from Penn Mobile - otherwise a 403 is returned.] If a schedule with
the specified id does not exist, a 404 is returned. In the body of the PUT, use the same format
as a POST request (see the Create Schedule docs).
This is an alternate way to update schedules (you can also just include the id field
in a schedule when you post and it will update that schedule if the id exists). Note that in a
put request the id field in the putted object is ignored; the id taken from the route
always takes precedence. If the request succeeds, it will return a 200 and a JSON in the same
format as if you were to get the schedule you just updated (in the same format as returned by
the GET /schedules/ route).

User authentication required.

# paths./api/plan/schedules/{id}/.put.parameters[].description
A unique integer value identifying this schedule.

# paths./api/plan/schedules/{id}/.put.requestBody.content.application/json.schema.properties.semester.description
The semester of the schedule (of the form YYYYx where x is
A [for spring], B [summer], or C [fall]), e.g. 2019C for fall 2019.
Can also be specified in Path format (YYYYxx, where xx is
10 [for spring], 20 [summer], or 30 [fall]), e.g. 201930 for fall 2019.
You can omit this field and the first semester found in the
sections/meetings list will be used instead (or if no semester
is specified in the request, the current semester open for registration
will be used).

# paths./api/plan/schedules/{id}/.put.requestBody.content.application/json.schema.properties.sections.description
The sections in the schedule (can also be called "meetings").

# paths./api/plan/schedules/{id}/.put.requestBody.content.application/json.schema.properties.sections.items.properties.id.description
A course code of the form DEPT-XXXX (e.g. CIS-1200), or a Path CRN

# paths./api/plan/schedules/{id}/.put.requestBody.content.application/json.schema.properties.sections.items.properties.semester.description
Optionally specify a section semester if you want the
backend to validate that all sections have the same
semester as the claimed schedule semester (taking the
first section semester as the schedule semester if none
is specified). Format is same as schedule semester.

# paths./api/plan/schedules/{id}/.put.requestBody.content.application/json.schema.properties.name.description
The user's nick-name for the schedule. No two schedules can match in all of the fields [name, semester, person]. Optional for PUT path registration.

# paths./api/plan/schedules/{id}/.put.responses.200.description
Successful update (the specified schedule was found and updated).

# paths./api/plan/schedules/{id}/.put.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/schedules/{id}/.put.responses.404.description
No schedule with the specified id exists.

# paths./api/plan/schedules/{id}/.delete.description
(DELETE `/api/plan/schedules/{id}/`)

Send a delete request to this route to delete a specific schedule. The `id` path parameter
(an integer) specifies which schedule you want to update. If a schedule with the specified
id does not exist, a 404 is returned. If the delete is successful, a 204 is returned.

User authentication required.

# paths./api/plan/schedules/{id}/.delete.parameters[].description
A unique integer value identifying this schedule.

# paths./api/plan/schedules/{id}/.delete.responses.204.description
Successful delete (the specified schedule was found and deleted).

# paths./api/plan/schedules/{id}/.delete.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/schedules/{id}/.delete.responses.404.description
No schedule with the specified id exists.

# paths./api/plan/primary-schedules/.get.description
(GET `/api/plan/primary-schedules/`)

Get the primary schedule for the current user as well as primary
schedules of the user's friends.

User authentication required.

# paths./api/plan/primary-schedules/.get.responses.200.content.application/json.schema.items.properties.user.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# paths./api/plan/primary-schedules/.get.responses.200.content.application/json.schema.items.properties.user.description
The user to which the primary schedule belongs.

# paths./api/plan/primary-schedules/.get.responses.200.content.application/json.schema.items.properties.schedule.properties.semester.description
The academic semester planned out by the schedule (of the form YYYYx where x is A
[for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/plan/primary-schedules/.get.responses.200.content.application/json.schema.items.properties.schedule.properties.name.description
The user's nick-name for the schedule. No two schedules can match in all of the fields
`[name, semester, person]`

# paths./api/plan/primary-schedules/.get.responses.200.description
Primary schedule (and friend's schedules) retrieved successfully.

# paths./api/plan/primary-schedules/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/primary-schedules/.post.description
(POST `/api/plan/primary-schedules/`)

Create/update/delete the primary schedule for the current user.

User authentication required.

# paths./api/plan/primary-schedules/.post.requestBody.content.application/json.schema.properties.schedule_id.description
The ID of the schedule you want to make primary (or null to unset).

# paths./api/plan/primary-schedules/.post.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/primary-schedules/{id}/.get.description
(GET `/api/plan/primary-schedules/{id}/`)

User authentication required.

# paths./api/plan/primary-schedules/{id}/.get.parameters[].description
A unique integer value identifying this primary schedule.

# paths./api/plan/primary-schedules/{id}/.get.responses.200.content.application/json.schema.properties.user.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# paths./api/plan/primary-schedules/{id}/.get.responses.200.content.application/json.schema.properties.user.description
The user to which the primary schedule belongs.

# paths./api/plan/primary-schedules/{id}/.get.responses.200.content.application/json.schema.properties.schedule.properties.semester.description
The academic semester planned out by the schedule (of the form YYYYx where x is A
[for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/plan/primary-schedules/{id}/.get.responses.200.content.application/json.schema.properties.schedule.properties.name.description
The user's nick-name for the schedule. No two schedules can match in all of the fields
`[name, semester, person]`

# paths./api/plan/primary-schedules/{id}/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/breaks/.get.description
(GET `/api/plan/breaks/`)

User authentication required.

# paths./api/plan/breaks/.get.responses.200.content.application/json.schema.items.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/plan/breaks/.get.responses.200.content.application/json.schema.items.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# paths./api/plan/breaks/.get.responses.200.content.application/json.schema.items.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# paths./api/plan/breaks/.get.responses.200.content.application/json.schema.items.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# paths./api/plan/breaks/.get.responses.200.content.application/json.schema.items.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/plan/breaks/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/breaks/.post.description
(POST `/api/plan/breaks/`)

User authentication required.

# paths./api/plan/breaks/.post.requestBody.content.application/json.schema.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/plan/breaks/.post.requestBody.content.application/json.schema.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# paths./api/plan/breaks/.post.requestBody.content.application/json.schema.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# paths./api/plan/breaks/.post.requestBody.content.application/json.schema.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# paths./api/plan/breaks/.post.requestBody.content.application/json.schema.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/plan/breaks/.post.responses.201.content.application/json.schema.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/plan/breaks/.post.responses.201.content.application/json.schema.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# paths./api/plan/breaks/.post.responses.201.content.application/json.schema.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# paths./api/plan/breaks/.post.responses.201.content.application/json.schema.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# paths./api/plan/breaks/.post.responses.201.content.application/json.schema.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/plan/breaks/.post.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/breaks/{id}/.get.description
(GET `/api/plan/breaks/{id}/`)

User authentication required.

# paths./api/plan/breaks/{id}/.get.responses.200.content.application/json.schema.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/plan/breaks/{id}/.get.responses.200.content.application/json.schema.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# paths./api/plan/breaks/{id}/.get.responses.200.content.application/json.schema.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# paths./api/plan/breaks/{id}/.get.responses.200.content.application/json.schema.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# paths./api/plan/breaks/{id}/.get.responses.200.content.application/json.schema.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/plan/breaks/{id}/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/breaks/{id}/.put.description
(PUT `/api/plan/breaks/{id}/`)

User authentication required.

# paths./api/plan/breaks/{id}/.put.requestBody.content.application/json.schema.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/plan/breaks/{id}/.put.requestBody.content.application/json.schema.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# paths./api/plan/breaks/{id}/.put.requestBody.content.application/json.schema.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# paths./api/plan/breaks/{id}/.put.requestBody.content.application/json.schema.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# paths./api/plan/breaks/{id}/.put.requestBody.content.application/json.schema.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/plan/breaks/{id}/.put.responses.200.content.application/json.schema.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/plan/breaks/{id}/.put.responses.200.content.application/json.schema.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# paths./api/plan/breaks/{id}/.put.responses.200.content.application/json.schema.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# paths./api/plan/breaks/{id}/.put.responses.200.content.application/json.schema.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# paths./api/plan/breaks/{id}/.put.responses.200.content.application/json.schema.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/plan/breaks/{id}/.put.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/breaks/{id}/.patch.description
(PATCH `/api/plan/breaks/{id}/`)

User authentication required.

# paths./api/plan/breaks/{id}/.patch.requestBody.content.application/json.schema.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/plan/breaks/{id}/.patch.requestBody.content.application/json.schema.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# paths./api/plan/breaks/{id}/.patch.requestBody.content.application/json.schema.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# paths./api/plan/breaks/{id}/.patch.requestBody.content.application/json.schema.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# paths./api/plan/breaks/{id}/.patch.requestBody.content.application/json.schema.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/plan/breaks/{id}/.patch.responses.200.content.application/json.schema.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/plan/breaks/{id}/.patch.responses.200.content.application/json.schema.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# paths./api/plan/breaks/{id}/.patch.responses.200.content.application/json.schema.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# paths./api/plan/breaks/{id}/.patch.responses.200.content.application/json.schema.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# paths./api/plan/breaks/{id}/.patch.responses.200.content.application/json.schema.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/plan/breaks/{id}/.patch.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/breaks/{id}/.delete.description
(DELETE `/api/plan/breaks/{id}/`)

User authentication required.

# paths./api/plan/breaks/{id}/.delete.responses.403.description
Access denied (missing or improper authentication).

# paths./api/alert/registrations/.get.description
(GET `/api/alert/registrations/`)

Returns all registrations which are not deleted or made obsolete by resubscription. Put
another way, this endpoint will return a superset of all active registrations: all
active registrations (meaning registrations which would trigger an alert to be sent if their
section were to open up), IN ADDITION TO all inactive registrations from the current semester
which are at the head of their resubscribe chains and not deleted. However, one extra
modification is made: if multiple registrations for the same section are included in the
above-specified set, then all but the most recent (latest `created_at` value) are removed from
the list. This ensures that at most 1 registration is returned for each section. Note that this
is still a superset of all active registrations. If a registration is active, its `created_at`
value will be greater than any other registrations for the same section (our code ensures no
registration can be created or resubscribed to when an active registration exists for the same
section). This extra modification is actually made to prevent the user from being able to
resubscribe to an older registration after creating a new one (which would cause the backend to
return a 409 error).

Each object in the returned list of registrations is of the same form as the object returned
by Retrieve Registration.

User authentication required.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.created_at.description
The datetime at which this registration was created.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.updated_at.description
The datetime at which this registration was last modified.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.section.description
The dash-separated full code of the section associated with this Registration.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.user.description
The Penn Labs Accounts username of the User who owns this Registration.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.cancelled.description
Defaults to False, changed to True if the registration has been cancelled. A cancelled
registration will not trigger any alerts to be sent even if the relevant section opens.
A cancelled section can be resubscribed to (unlike deleted alerts), and will show up
on the manage alerts page on the frontend (also unlike deleted alerts). Note that once
a registration is cancelled, it cannot be uncancelled (resubscribing creates a new
registration which is accessible via the resubscribed_to field, related name of
resubscribed_from).

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.deleted.description
Defaults to False, changed to True if the registration has been deleted. A deleted
registration will not trigger any alerts to be sent even if the relevant section opens.
A deleted section cannot be resubscribed to or undeleted, and will not show up on the
manage alerts page on the frontend. It is kept in the database for analytics purposes,
even though it serves no immediate functional purpose for its original user.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.auto_resubscribe.description
Defaults to False, in which case a registration will not be automatically resubscribed
after it triggers an alert to be sent (but the user can still resubscribe to a sent alert,
as long as it is not deleted). If set to True, the registration will be automatically
resubscribed to once it triggers an alert to be sent (this is useful in the case of
volatile sections which are opening and closing frequently, often before the user has
time to register).

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# paths./api/alert/registrations/.get.responses.200.content.application/json.schema.items.properties.section_status.description
The current status of the watched section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# paths./api/alert/registrations/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/alert/registrations/.post.description
(POST `/api/alert/registrations/`)

Use this route to create a PCA registration for a certain section.  A PCA registration
represents a "subscription" to receive alerts for that section.  The body of the request must
include a section field (with the dash-separated full code of the section) and optionally
can contain an auto_resubscribe field (defaults to false) which sets whether the registration
will automatically create a new registration once it triggers an alerts (i.e. whether it will
automatically resubscribe the user to receive alerts for that section). It can also optionally
contain a "close_notification" field, to enable close notifications on the registration.
Note that close notifications CANNOT be sent by text so you shouldn't allow the user to
enable close notifications for any registration unless they have an email set in their
User Profile or have push notifications enabled.  If you try to create a registration with
close_notification enabled and the user only has texts enabled, , a 406 will be returned
and the registration will not be created.
Note that if you include the "id" field in the body of your POST request, and that id
does not already exist, the id of the created registration will be set to the given value.
However, if the given id does exist, the request will instead be treated as a PUT request for
the registration (see the Update Registration docs for more info on how
PUT requests are handled).

This route returns a 201 if the registration is successfully created, a 400 if the input is
invalid (for instance if a null section is given), a 404 if the given section is not found in
the database, a 406 if the authenticated user does not have either a phone or an email set
in their profile (thus making it impossible for them to receive alerts), and a 409 if the
user is already currently registered to receive alerts for the given section.  If the request
is redirected to update (when the passed in id is already associated with a registration),
other response codes may be returned (see the Update Registration docs for more info). If
registration is not currently open on PCA, a 503 is returned.

<span style="color:red;">User authentication required</span>.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.id.description
The id of the registration (can optionally be used to customize the id of a new registration, or to update an existing registration).

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.created_at.description
The datetime at which this registration was created.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.updated_at.description
The datetime at which this registration was last modified.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.section.description
The dash-separated full code of the section associated with this Registration.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.user.description
The User that registered for this alert. This object will be none if registration occurred
before the PCA refresh of Spring 2020 (before the refresh user's were only identified by
their email and phone numbers, which are legacy fields in this model now). This object
might also be none if registration occurred through a 3rd part API such as Penn Course
Notify (now that Notify has fallen this is an unlikely event).

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.cancelled.description
Defaults to False, changed to True if the registration has been cancelled. A cancelled
registration will not trigger any alerts to be sent even if the relevant section opens.
A cancelled section can be resubscribed to (unlike deleted alerts), and will show up
on the manage alerts page on the frontend (also unlike deleted alerts). Note that once
a registration is cancelled, it cannot be uncancelled (resubscribing creates a new
registration which is accessible via the resubscribed_to field, related name of
resubscribed_from).

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.deleted.description
Defaults to False, changed to True if the registration has been deleted. A deleted
registration will not trigger any alerts to be sent even if the relevant section opens.
A deleted section cannot be resubscribed to or undeleted, and will not show up on the
manage alerts page on the frontend. It is kept in the database for analytics purposes,
even though it serves no immediate functional purpose for its original user.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.auto_resubscribe.description
Set this to true to turn on auto resubscribe (causing the registration to automatically
resubscribe once it sends out a notification).  Default is false if not specified.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# paths./api/alert/registrations/.post.requestBody.content.application/json.schema.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# paths./api/alert/registrations/.post.responses.403.description
Access denied (missing or improper authentication).

# paths./api/alert/registrations/.post.responses.406.description
No contact information (phone or email) set for user.

# paths./api/alert/registrations/.post.responses.409.description
Registration for given section already exists.

# paths./api/alert/registrations/{id}/.get.description
(GET `/api/alert/registrations/{id}/`)

Get one of the logged-in user's PCA registrations for the current semester, using
the registration's ID. Note that if a registration with the specified ID exists, but that
registration is not at the head of its resubscribe chain (i.e. there is a more recent
registration which was created by resubscribing to the specified registration), the
HEAD of the resubscribe chain will be returned. This means the same registration could be
returned from a GET request to 2 distinct IDs (if they are in the same resubscribe chain).
If a registration with the specified ID exists, a 200 response code is returned, along
with the head registration object. If no registration with the given id exists,
a 404 is returned.

User authentication required.

# paths./api/alert/registrations/{id}/.get.parameters[].description
A unique integer value identifying this registration.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.created_at.description
The datetime at which this registration was created.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.updated_at.description
The datetime at which this registration was last modified.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.section.description
The dash-separated full code of the section associated with this Registration.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.user.description
The Penn Labs Accounts username of the User who owns this Registration.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.cancelled.description
Defaults to False, changed to True if the registration has been cancelled. A cancelled
registration will not trigger any alerts to be sent even if the relevant section opens.
A cancelled section can be resubscribed to (unlike deleted alerts), and will show up
on the manage alerts page on the frontend (also unlike deleted alerts). Note that once
a registration is cancelled, it cannot be uncancelled (resubscribing creates a new
registration which is accessible via the resubscribed_to field, related name of
resubscribed_from).

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.deleted.description
Defaults to False, changed to True if the registration has been deleted. A deleted
registration will not trigger any alerts to be sent even if the relevant section opens.
A deleted section cannot be resubscribed to or undeleted, and will not show up on the
manage alerts page on the frontend. It is kept in the database for analytics purposes,
even though it serves no immediate functional purpose for its original user.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.auto_resubscribe.description
Defaults to False, in which case a registration will not be automatically resubscribed
after it triggers an alert to be sent (but the user can still resubscribe to a sent alert,
as long as it is not deleted). If set to True, the registration will be automatically
resubscribed to once it triggers an alert to be sent (this is useful in the case of
volatile sections which are opening and closing frequently, often before the user has
time to register).

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# paths./api/alert/registrations/{id}/.get.responses.200.content.application/json.schema.properties.section_status.description
The current status of the watched section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# paths./api/alert/registrations/{id}/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/alert/registrations/{id}/.put.description
(PUT `/api/alert/registrations/{id}/`)

Use this route to update existing PCA Registrations.  Note that the provided id does
not always strictly specify which Registration gets modified.  In fact, the actual Registration
that would get modified by a PUT request would be the head of the resubscribe chain of the
Registration with the specified id (so if you try to update an outdated Registration it will
instead update the most recent Registration).  The parameters which can be
included in the request body are `resubscribe`, `auto_resubscribe`, 'close_notification',
`cancelled`, and `deleted`. If you include multiple parameters, the order of precedence in
choosing what action to take is `resubscribe` > `deleted` > `cancelled` >
[`auto_resubscribe` and `close_notification`] (so if you include multiple
parameters only the action associated with the highest priority parameter will be executed,
except both auto_resubscribe and close_notification can be updated in the same request).
Note that close notifications CANNOT be sent by text so you shouldn't allow the user to
enable close notifications for any registration unless they have an email set in their
User Profile or have push notifications enabled.  If you try to update a registration to
enable close_notification and the user only has texts enabled, a 406 will be returned
and the registration will not be created.
Note that a registration will send an alert when the section it is watching opens, if and only
if it hasn't sent one before, it isn't cancelled, and it isn't deleted.  If a registration would
send an alert when the section it is watching opens, we call it "active".  Registrations which
have triggered an alert can be resubscribed to (which creates a new registration with the same
settings and adds that to the end of the original registration's resubscribe chain).  Triggered
registrations would show up in List Registrations (as long as they are at the head of
their resubscribe chain), even though they aren't active.  Cancelled registrations can also
be resubscribed to (in effect uncancelling), and also show up in List Registrations, despite
not being active.  A user might cancel an alert rather than delete it if they want to keep it
in their PCA manage console but don't want to receive alerts for it.  Deleted registrations
are not active, do not show up in List Registrations, and cannot be resubscribed to.  You can
think of deleted registrations as effectively nonexistent; they are only kept on the backend
for analytics purposes.  Note that while you can cancel a registration by setting the cancelled
parameter to true in your PUT request (and the same for delete/deleted), you cannot uncancel
or undelete (cancelled registrations can be resubscribed to and deleted registrations
are effectively nonexistent).

If the update is successful, a 200 is returned.  If there is some issue with the request,
a 400 is returned.  This could be caused by trying to update a registration from a different
semester, trying to resubscribe to a deleted registration, resubscribing to a registration
which is not cancelled or hasn't yet triggered a notification, cancelling a deleted or
triggered registration, trying to make changes to a deleted registration, or otherwise
breaking rules.  Look in the detail field of the response object for more detail on what
exactly went wrong if you encounter a 400.  If no registration with the given id is found,
a 404 is returned. If registration is not currently open on PCA, a 503 is returned.

<span style="color:red;">User authentication required</span>.

# paths./api/alert/registrations/{id}/.put.parameters[].description
A unique integer value identifying this registration.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.created_at.description
The datetime at which this registration was created.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.updated_at.description
The datetime at which this registration was last modified.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.section.description
The section that the user registered to be notified about.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.user.description
The User that registered for this alert. This object will be none if registration occurred
before the PCA refresh of Spring 2020 (before the refresh user's were only identified by
their email and phone numbers, which are legacy fields in this model now). This object
might also be none if registration occurred through a 3rd part API such as Penn Course
Notify (now that Notify has fallen this is an unlikely event).

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.cancelled.description
Set this to true to cancel to this registration (making it inactive while keeping it
in List Registration).

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.deleted.description
Set this to true to delete this registration (making it inactive and preventing it from
showing up in List Registrations).

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.auto_resubscribe.description
Set this to true to turn on auto resubscribe (causing the registration to automatically
resubscribe once it sends out a notification).

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# paths./api/alert/registrations/{id}/.put.requestBody.content.application/json.schema.properties.resubscribe.description
Set this to true to resubscribe to this registration (only works if the registration
has sent a notification and hasn't been deleted).

# paths./api/alert/registrations/{id}/.put.responses.200.description
Registration successfully updated (or no changes necessary).

# paths./api/alert/registrations/{id}/.put.responses.403.description
Access denied (missing or improper authentication).

# paths./api/alert/registrationhistory/.get.description
(GET `/api/alert/registrationhistory/`)

List all of the user's registrations for the current semester, regardless of whether
they are active, obsolete (not at the head of their resubscribe chains), or deleted. Note
that this is not appropriate to use for listing registrations and presenting them to the user;
for that you should use List Registrations (GET `/api/alert/registrations/`).

User authentication required.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.created_at.description
The datetime at which this registration was created.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.updated_at.description
The datetime at which this registration was last modified.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.section.description
The dash-separated full code of the section associated with this Registration.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.user.description
The Penn Labs Accounts username of the User who owns this Registration.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.cancelled.description
Defaults to False, changed to True if the registration has been cancelled. A cancelled
registration will not trigger any alerts to be sent even if the relevant section opens.
A cancelled section can be resubscribed to (unlike deleted alerts), and will show up
on the manage alerts page on the frontend (also unlike deleted alerts). Note that once
a registration is cancelled, it cannot be uncancelled (resubscribing creates a new
registration which is accessible via the resubscribed_to field, related name of
resubscribed_from).

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.deleted.description
Defaults to False, changed to True if the registration has been deleted. A deleted
registration will not trigger any alerts to be sent even if the relevant section opens.
A deleted section cannot be resubscribed to or undeleted, and will not show up on the
manage alerts page on the frontend. It is kept in the database for analytics purposes,
even though it serves no immediate functional purpose for its original user.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.auto_resubscribe.description
Defaults to False, in which case a registration will not be automatically resubscribed
after it triggers an alert to be sent (but the user can still resubscribe to a sent alert,
as long as it is not deleted). If set to True, the registration will be automatically
resubscribed to once it triggers an alert to be sent (this is useful in the case of
volatile sections which are opening and closing frequently, often before the user has
time to register).

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# paths./api/alert/registrationhistory/.get.responses.200.content.application/json.schema.items.properties.section_status.description
The current status of the watched section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# paths./api/alert/registrationhistory/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/alert/registrationhistory/{id}/.get.description
(GET `/api/alert/registrationhistory/{id}/`)

Get the detail of a specific registration from the current semester. All registrations are
accessible via this endpoint, regardless of whether they are active,
obsolete (not at the head of their resubscribe chains), or deleted. Unless you need to access
inactive and obsolete registrations, you should probably use Retrieve Registration
(GET `/api/alert/registrations/{id}/`) rather than this endpoint.

User authentication required.

# paths./api/alert/registrationhistory/{id}/.get.parameters[].description
A unique integer value identifying this registration.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.created_at.description
The datetime at which this registration was created.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.updated_at.description
The datetime at which this registration was last modified.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.section.description
The dash-separated full code of the section associated with this Registration.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.user.description
The Penn Labs Accounts username of the User who owns this Registration.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.cancelled.description
Defaults to False, changed to True if the registration has been cancelled. A cancelled
registration will not trigger any alerts to be sent even if the relevant section opens.
A cancelled section can be resubscribed to (unlike deleted alerts), and will show up
on the manage alerts page on the frontend (also unlike deleted alerts). Note that once
a registration is cancelled, it cannot be uncancelled (resubscribing creates a new
registration which is accessible via the resubscribed_to field, related name of
resubscribed_from).

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.deleted.description
Defaults to False, changed to True if the registration has been deleted. A deleted
registration will not trigger any alerts to be sent even if the relevant section opens.
A deleted section cannot be resubscribed to or undeleted, and will not show up on the
manage alerts page on the frontend. It is kept in the database for analytics purposes,
even though it serves no immediate functional purpose for its original user.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.auto_resubscribe.description
Defaults to False, in which case a registration will not be automatically resubscribed
after it triggers an alert to be sent (but the user can still resubscribe to a sent alert,
as long as it is not deleted). If set to True, the registration will be automatically
resubscribed to once it triggers an alert to be sent (this is useful in the case of
volatile sections which are opening and closing frequently, often before the user has
time to register).

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# paths./api/alert/registrationhistory/{id}/.get.responses.200.content.application/json.schema.properties.section_status.description
The current status of the watched section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# paths./api/alert/registrationhistory/{id}/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/alert/registrationhistory/{id}/.get.responses.404.description
Historic registration not found with given id.

# paths./api/degree/degreeplans.get.description
(GET `/api/degree/degreeplans`)

List, retrieve, create, destroy, and update a DegreePlan.

# paths./api/degree/degreeplans.get.responses.200.content.application/json.schema.items.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans.post.description
(POST `/api/degree/degreeplans`)

List, retrieve, create, destroy, and update a DegreePlan.

# paths./api/degree/degreeplans.post.requestBody.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans.post.requestBody.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans.post.responses.201.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans.post.responses.201.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}.get.description
(GET `/api/degree/degreeplans/{id}`)

List, retrieve, create, destroy, and update a DegreePlan.

# paths./api/degree/degreeplans/{id}.get.responses.200.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}.get.responses.200.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}.put.description
(PUT `/api/degree/degreeplans/{id}`)

List, retrieve, create, destroy, and update a DegreePlan.

# paths./api/degree/degreeplans/{id}.put.requestBody.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}.put.requestBody.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}.put.responses.200.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}.put.responses.200.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}.patch.description
(PATCH `/api/degree/degreeplans/{id}`)

List, retrieve, create, destroy, and update a DegreePlan.

# paths./api/degree/degreeplans/{id}.patch.requestBody.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}.patch.requestBody.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}.patch.responses.200.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}.patch.responses.200.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}.delete.description
(DELETE `/api/degree/degreeplans/{id}`)

List, retrieve, create, destroy, and update a DegreePlan.

# paths./api/degree/degrees.get.description
(GET `/api/degree/degrees`)

Retrieve a list of all Degree objects.

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.program.description
The program code for this degree, e.g., EU_BSE

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.degree.description
The degree code for this degree, e.g., BSE

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.major.description
The major code for this degree, e.g., BIOL

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.major_name.description
The name of the major for this degree, e.g., Africana Studies

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.concentration.description
The concentration code for this degree, e.g., BMAT

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.concentration_name.description
The name of the concentration for this degree, e.g., African American Studies

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.year.description
The effective year of this degree, e.g., 2023

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.credits.description
The minimum number of CUs required for this degree.

# paths./api/degree/degrees.get.responses.200.content.application/json.schema.items.properties.rules.description
The rules for this degree. Blank if this degree has no rules.

# paths./api/degree/degrees/{id}.get.description
(GET `/api/degree/degrees/{id}`)

Retrieve a list of all Degree objects.

# paths./api/degree/degrees/{id}.get.parameters[].description
A unique integer value identifying this degree.

# paths./api/degree/degrees/{id}.get.responses.200.content.application/json.schema.properties.program.description
The program code for this degree, e.g., EU_BSE

# paths./api/degree/degrees/{id}.get.responses.200.content.application/json.schema.properties.degree.description
The degree code for this degree, e.g., BSE

# paths./api/degree/degrees/{id}.get.responses.200.content.application/json.schema.properties.major.description
The major code for this degree, e.g., BIOL

# paths./api/degree/degrees/{id}.get.responses.200.content.application/json.schema.properties.major_name.description
The name of the major for this degree, e.g., Africana Studies

# paths./api/degree/degrees/{id}.get.responses.200.content.application/json.schema.properties.concentration.description
The concentration code for this degree, e.g., BMAT

# paths./api/degree/degrees/{id}.get.responses.200.content.application/json.schema.properties.concentration_name.description
The name of the concentration for this degree, e.g., African American Studies

# paths./api/degree/degrees/{id}.get.responses.200.content.application/json.schema.properties.year.description
The effective year of this degree, e.g., 2023

# paths./api/degree/degrees/{id}.get.responses.200.content.application/json.schema.properties.credits.description
The minimum number of CUs required for this degree.

# paths./api/degree/docked.get.description
(GET `/api/degree/docked`)

List, retrieve, create, destroy, and update docked courses

# paths./api/degree/docked.get.responses.200.content.application/json.schema.items.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/docked.post.description
(POST `/api/degree/docked`)

List, retrieve, create, destroy, and update docked courses

# paths./api/degree/docked.post.requestBody.content.application/json.schema.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/docked.post.responses.201.content.application/json.schema.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/docked/{full_code}.get.description
(GET `/api/degree/docked/{full_code}`)

List, retrieve, create, destroy, and update docked courses

# paths./api/degree/docked/{full_code}.get.parameters[].description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/docked/{full_code}.get.responses.200.content.application/json.schema.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/docked/{full_code}.delete.description
(DELETE `/api/degree/docked/{full_code}`)

List, retrieve, create, destroy, and update docked courses

# paths./api/degree/docked/{full_code}.delete.parameters[].description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.get.description
(GET `/api/degree/degreeplans/{degreeplan_pk}/fulfillments`)

List, retrieve, create, destroy, and update a Fulfillment.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.get.responses.200.content.application/json.schema.items.properties.degree_plan.description
The degree plan with which this fulfillment is associated

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.get.responses.200.content.application/json.schema.items.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.get.responses.200.content.application/json.schema.items.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019. Null if this fulfillment
does not yet have a semester.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.get.responses.200.content.application/json.schema.items.properties.unselected_rules.description
The rules this course fulfills that should be shown in the open-ended rule box
(as opposed to the expandable box). Blank if this course should not be included in
any open-ended rule boxes.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.get.responses.200.content.application/json.schema.items.properties.legal.description
True if course associated with this fulfillment isn't illegally double counted anywhere,
false otherwise.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.requestBody.content.application/json.schema.properties.degree_plan.description
The degree plan with which this fulfillment is associated

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.requestBody.content.application/json.schema.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.requestBody.content.application/json.schema.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019. Null if this fulfillment
does not yet have a semester.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.requestBody.content.application/json.schema.properties.unselected_rules.description
The rules this course fulfills that should be shown in the open-ended rule box
(as opposed to the expandable box). Blank if this course should not be included in
any open-ended rule boxes.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.requestBody.content.application/json.schema.properties.legal.description
True if course associated with this fulfillment isn't illegally double counted anywhere,
false otherwise.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.responses.201.content.application/json.schema.properties.degree_plan.description
The degree plan with which this fulfillment is associated

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.responses.201.content.application/json.schema.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.responses.201.content.application/json.schema.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019. Null if this fulfillment
does not yet have a semester.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.responses.201.content.application/json.schema.properties.unselected_rules.description
The rules this course fulfills that should be shown in the open-ended rule box
(as opposed to the expandable box). Blank if this course should not be included in
any open-ended rule boxes.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments.post.responses.201.content.application/json.schema.properties.legal.description
True if course associated with this fulfillment isn't illegally double counted anywhere,
false otherwise.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments/{full_code}.get.parameters[].description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments/{full_code}.get.responses.200.content.application/json.schema.properties.degree_plan.description
The degree plan with which this fulfillment is associated

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments/{full_code}.get.responses.200.content.application/json.schema.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments/{full_code}.get.responses.200.content.application/json.schema.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019. Null if this fulfillment
does not yet have a semester.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments/{full_code}.get.responses.200.content.application/json.schema.properties.unselected_rules.description
The rules this course fulfills that should be shown in the open-ended rule box
(as opposed to the expandable box). Blank if this course should not be included in
any open-ended rule boxes.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments/{full_code}.get.responses.200.content.application/json.schema.properties.legal.description
True if course associated with this fulfillment isn't illegally double counted anywhere,
false otherwise.

# paths./api/degree/degreeplans/{degreeplan_pk}/fulfillments/{full_code}.delete.parameters[].description
The dash-joined department and code of the course, e.g., `CIS-120`

# paths./api/degree/satisfied-rule-list/{degree_plan_id}/{full_code}/{ru.get.description
(GET `/api/degree/satisfied-rule-list/{degree_plan_id}/{full_code}/{rule_id}`)

Provided a degree plan and a course code, retrieve a sublist
of the degrees' rules that are satisfied by the course.

# paths./api/degree/satisfied-rule-list/{degree_plan_id}/{full_code}/{ru.get.parameters[].description
The full course code (e.g., 'CIS-1200')
                                    to check against requirements

# paths./api/degree/satisfied-rule-list/{degree_plan_id}/{full_code}/{ru.get.parameters[].description
The ID of a specific rule to check, or '-1'
                                to automatically determine the highest priority rule

# paths./api/degree/satisfied-rule-list/{degree_plan_id}/{full_code}/{ru.get.responses.200.description
Returns a list of degree requirements satisfied by the course,
                    including selected rules, newly selected rules, unselected rules that could
                    be satisfied, and whether the selections can be legally double counted.

# paths./api/base/{semester}/courses/.get.description
(GET `/api/base/{semester}/courses/`)

Retrieve a list of (all) courses for the provided semester.

# paths./api/base/{semester}/courses/.get.parameters[].description
The semester of the course (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. '2019C' for fall 2019. Alternatively, you can just pass 'current' for the current semester. Finally, you can pass 'all' to always return the most recent course for each full_code, no matter which semester it is from. The 'all' option can be significantly more expensive, so use only where needed. 

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.id.description
The full code of the course, in the form '{dept code}-{course code}'
dash-joined department and code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.title.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.description.description
The description of the course, e.g. 'A fast-paced introduction to the fundamental concepts
of programming... [etc.]' for CIS-120.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.course_quality.description
The average course quality rating for this section, on a scale of 0-4.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.instructor_quality.description
The average instructor quality for this section, on a scale of 0-4.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.difficulty.description
The average difficult rating for this section, on a scale of 0-4.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.work_required.description
The average work required for this section, on a scale of 0-4.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.recommendation_score.description
The recommendation score for this course if the user is logged in, or null if the
the user is not logged in.

# paths./api/base/{semester}/courses/.get.responses.200.content.application/json.schema.items.properties.credits.description
The number of credits this course takes. This is precomputed for efficiency.

# paths./api/base/{semester}/search/courses/.get.description
(GET `/api/base/{semester}/search/courses/`)

This route allows you to list courses by certain search terms and/or filters.
Without any GET parameters, this route simply returns all courses
for a given semester. There are a few filter query parameters which constitute ranges of
floating-point numbers. The values for these are <min>-<max> , with minimum excluded.
For example, looking for classes in the range of 0-2.5 in difficulty, you would add the
parameter difficulty=0-2.5. If you are a backend developer, you can find these filters in
backend/plan/filters.py/CourseSearchFilterBackend. If you are reading the frontend docs,
these filters are listed below in the query parameters list (with description starting with
"Filter").

# paths./api/base/{semester}/search/courses/.get.parameters[].description
The semester of the course (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. '2019C' for fall 2019. Alternatively, you can just pass 'current' for the current semester. Finally, you can pass 'all' to always return the most recent course for each full_code, no matter which semester it is from. The 'all' option can be significantly more expensive, so use only where needed. 

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Search query. Can be either a fragment of a course code, or any keyword/professor name.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter to courses that satisfy certain degree Rules. Accepts a string of comma-separated Rule ids. If multiple Rule ids are passed then filtered courses satisfy all the rules.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Can specify what kind of query to run. Course queries are faster, keyword queries look against professor name and course title.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Deprecated since 2022B. Filter courses by comma-separated pre ngss requirements, ANDed together. Use the [List Requirements](/api/documentation/#operation/List%20Pre-Ngss%20Requirements) endpoint to get requirement IDs.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
This query parameter accepts a logical expression of attribute codes separated by `*` (AND) or `|` (OR) connectives, optionally grouped into clauses by parentheses and arbitrarily nested (we avoid using `&` for the AND connective so the query string doesn't have to be escaped). You can negate an individual attribute code or a clause with the `~` operator (this will filter for courses that do NOT have that attribute or do not satisfy that clause). Binary operators are left-associative, and operator precedence is as follows: `~ > * > |`. Whitespace is ignored. A syntax error will cause a 400 response to be returned. Example: `(EUHS|EUSS)*(QP|QS)` would filter for courses that satisfy the EAS humanities or social science requirements and also have a standard grade type or a pass/fail grade type. Use the [List Attributes](/api/documentation/#operation/List%20Attributes) endpoint to get a list of valid attribute codes and descriptions.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter course units to be within the given range.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter course difficulty (average across all reviews) to be within the given range.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter course quality (average across all reviews) to be within the given range.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter instructor quality (average across all reviews) to be within the given range.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter meetings to be within the specified set of days. The set of days should be specified as a string containing some combination of the characters [M, T, W, R, F, S, U]. This filters courses by the following condition: include a course only if the specified day filter does not limit the set of section activities we can participate in for the course. Passing an empty string will return only asynchronous classes or classes with meeting days TBD.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter meeting times to be within the specified range. The start and end time of the filter should be dash-separated. Times should be specified as decimal numbers of the form `h+mm/100` where h is the hour `[0..23]` and mm is the minute `[0,60)`, in ET. You can omit either the start or end time to leave that side unbounded, e.g. '11.30-'. This filters courses by the following condition: include a course only if the specified time filter does not limit the set of section activities we can participate in for the course.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter meeting times to fit into the schedule with the specified integer id. You must be authenticated with the account owning the specified schedule, or this filter will be ignored. This filters courses by the following condition: include a course only if the specified schedule-fit filter does not limit the set of section activities we can participate in for the course.

# paths./api/base/{semester}/search/courses/.get.parameters[].description
Filter courses to only those that are open. A boolean of true should be included if you want to apply the filter. By default (ie when the `is_open` is not supplied, the filter is not applied. This filters courses by the following condition: include a course only if the specification that a section is open does not limit the set of section activities we can participate in for the course.In other words, filter to courses for which all activities have open sections.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.id.description
The full code of the course, in the form '{dept code}-{course code}'
dash-joined department and code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.title.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.description.description
The description of the course, e.g. 'A fast-paced introduction to the fundamental concepts
of programming... [etc.]' for CIS-120.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.course_quality.description
The average course quality rating for this section, on a scale of 0-4.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.instructor_quality.description
The average instructor quality for this section, on a scale of 0-4.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.difficulty.description
The average difficult rating for this section, on a scale of 0-4.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.work_required.description
The average work required for this section, on a scale of 0-4.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.recommendation_score.description
The recommendation score for this course if the user is logged in, or null if the
the user is not logged in.

# paths./api/base/{semester}/search/courses/.get.responses.200.content.application/json.schema.items.properties.credits.description
The number of credits this course takes. This is precomputed for efficiency.

# paths./api/base/{semester}/courses/{full_code}/.get.description
(GET `/api/base/{semester}/courses/{full_code}/`)

Retrieve a detailed look at a specific course. Includes all details necessary to display course
info, including requirements this class fulfills, and all sections.

# paths./api/base/{semester}/courses/{full_code}/.get.parameters[].description
The semester of the course (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. '2019C' for fall 2019. Alternatively, you can just pass 'current' for the current semester. Finally, you can pass 'all' to always return the most recent course for each full_code, no matter which semester it is from. The 'all' option can be significantly more expensive, so use only where needed. 

# paths./api/base/{semester}/courses/{full_code}/.get.parameters[].description
The dash-joined department and code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/base/{semester}/courses/{full_code}/.get.parameters[].description
Check that the desired course was offered under the specified
code in the specified semester.
Format is `course_code@semester`, e.g. `CIS-1210@2022A`.
404 will be returned if the course
does not exist, or was not offered in that semester.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.id.description
The full code of the course, in the form '{dept code}-{course code}'
dash-joined department and code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.title.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.description.description
The description of the course, e.g. 'A fast-paced introduction to the fundamental concepts
of programming... [etc.]' for CIS-120.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.syllabus_url.description
A URL for the syllabus of the course, if available.
Not available for courses offered in or before spring 2022.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.prerequisites.description
Text describing the prereqs for a course, e.g. 'CIS 120, 160' for CIS-121.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.course_quality.description
The average course quality rating for this section, on a scale of 0-4.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.instructor_quality.description
The average instructor quality for this section, on a scale of 0-4.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.difficulty.description
The average difficult rating for this section, on a scale of 0-4.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.work_required.description
The average work required for this section, on a scale of 0-4.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.credits.description
The number of credits this course takes. This is precomputed for efficiency.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.crosslistings.description
A list of the full codes (DEPT-###) of all crosslistings for this course
(not including this course).

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.pre_ngss_requirements.description
A list of the pre-NGSS (deprecated since 2022B) academic requirements
this course fulfills.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.attributes.description
A list of attributes this course has. Attributes are typically
used to mark courses which students in a program/major should
take.

# paths./api/base/{semester}/courses/{full_code}/.get.responses.200.content.application/json.schema.properties.restrictions.description
A list of NGSSRestrictions this course has. Restrictions provide information about
who can take a course.

# paths./api/base/{semester}/search/sections/.get.description
(GET `/api/base/{semester}/search/sections/`)

Retrieve a list of sections (less detailed than [PCx] Section, or SectionDetail on the
backend).  The sections are filtered by the search term (assumed to be a prefix of a
section's full code, with each chunk either space-delimited, dash-delimited, or not delimited).

# paths./api/base/{semester}/search/sections/.get.parameters[].description
The semester of the course (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. '2019C' for fall 2019. Alternatively, you can just pass 'current' for the current semester. Finally, you can pass 'all' to always return the most recent course for each full_code, no matter which semester it is from. The 'all' option can be significantly more expensive, so use only where needed. 

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.section_id.description
The dash-separated dept, full-code, and section-code, e.g. `CIS-120-001` for the
001 lecture section of CIS-120.

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.status.description
The registration status of the section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.activity.description
The section activity, e.g. `LEC` for CIS-120-001 (2020A). Options and meanings:

"" | "Undefined"
"CLN" | "Clinic"
"CRT" | "Clinical Rotation"
"DAB" | "Dissertation Abroad"
"DIS" | "Dissertation"
"DPC" | "Doctoral Program Exchange"
"FLD" | "Field Work"
"HYB" | "Hybrid"
"IND" | "Independent Study"
"LAB" | "Lab"
"LEC" | "Lecture"
"MST" | "Masters Thesis"
"ONL" | "Online"
"PRC" | "Practicum"
"REC" | "Recitation"
"SEM" | "Seminar"
"SRT" | "Senior Thesis"
"STU" | "Studio"

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.instructors.description
A list of the names of the instructors teaching this section.

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.course_code.description
The full code of the course this section belongs to, e.g. `CIS-120` for CIS-120-001.

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.course_title.description
The title of the course this section belongs to, e.g.
'Programming Languages and Techniques I' for CIS-120-001.

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/base/{semester}/search/sections/.get.responses.200.content.application/json.schema.items.properties.registration_volume.description
The number of active PCA registrations watching this section.

# paths./api/base/{semester}/sections/{full_code}/.get.description
(GET `/api/base/{semester}/sections/{full_code}/`)

Retrieve a detailed look at a specific course section.

# paths./api/base/{semester}/sections/{full_code}/.get.parameters[].description
The semester of the course (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. '2019C' for fall 2019. Alternatively, you can just pass 'current' for the current semester. Finally, you can pass 'all' to always return the most recent course for each full_code, no matter which semester it is from. The 'all' option can be significantly more expensive, so use only where needed. 

# paths./api/base/{semester}/sections/{full_code}/.get.parameters[].description
The full code of the section, in the form '{dept code}-{course code}-{section code}',
e.g. `CIS-120-001` for the 001 section of CIS-120.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.id.description
The dash-separated dept, full-code, and section-code, e.g. `CIS-120-001` for the
001 lecture section of CIS-120.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.status.description
The registration status of the section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.activity.description
The section activity, e.g. `LEC` for CIS-120-001 (2020A). Options and meanings:

"" | "Undefined"
"CLN" | "Clinic"
"CRT" | "Clinical Rotation"
"DAB" | "Dissertation Abroad"
"DIS" | "Dissertation"
"DPC" | "Doctoral Program Exchange"
"FLD" | "Field Work"
"HYB" | "Hybrid"
"IND" | "Independent Study"
"LAB" | "Lab"
"LEC" | "Lecture"
"MST" | "Masters Thesis"
"ONL" | "Online"
"PRC" | "Practicum"
"REC" | "Recitation"
"SEM" | "Seminar"
"SRT" | "Senior Thesis"
"STU" | "Studio"

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.credits.description
The number of credits this section is worth.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.capacity.description
The max allowed enrollment across all crosslistings of this section.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.instructors.description
A list of the names of the instructors teaching this section.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.course_quality.description
The average course quality rating for this section, on a scale of 0-4.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.instructor_quality.description
The average instructor quality for this section, on a scale of 0-4.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.difficulty.description
The average difficult rating for this section, on a scale of 0-4.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.work_required.description
The average work required for this section, on a scale of 0-4.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.associated_sections.description
A list of all sections associated with the Course which this section belongs to; e.g. for
CIS-120-001, all of the lecture and recitation sections for CIS-120 (including CIS-120-001)
in the same semester.

# paths./api/base/{semester}/sections/{full_code}/.get.responses.200.content.application/json.schema.properties.registration_volume.description
The number of active PCA registrations watching this section.

# paths./api/base/{semester}/pre-ngss-requirements/.get.description
(GET `/api/base/{semester}/pre-ngss-requirements/`)

Retrieve a list of all pre-NGSS (deprecated since 2022B) academic requirements
in the database for this semester.

# paths./api/base/{semester}/pre-ngss-requirements/.get.parameters[].description
The semester of the requirement (of the form YYYYx where x is A [for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019. We organize requirements by semester so that we don't get huge related sets which don't give particularly good info.

# paths./api/base/{semester}/pre-ngss-requirements/.get.responses.200.content.application/json.schema.items.properties.id.description
A string representation of the requirement, in the form '{code}@{school}'

# paths./api/base/{semester}/pre-ngss-requirements/.get.responses.200.content.application/json.schema.items.properties.code.description
The code identifying this requirement, e.g. `MFR` for 'Formal Reasoning Course',
an SAS requirement satisfied by CIS-120.

# paths./api/base/{semester}/pre-ngss-requirements/.get.responses.200.content.application/json.schema.items.properties.school.description
What school this requirement belongs to, e.g. `SAS` for the SAS 'Formal Reasoning Course' requirement satisfied by CIS-120. Options and meanings:

"SEAS" | "Engineering"
"WH" | "Wharton"
"SAS" | "College"

# paths./api/base/{semester}/pre-ngss-requirements/.get.responses.200.content.application/json.schema.items.properties.semester.description
The semester of the requirement (of the form YYYYx where x is A [for spring], B [summer],
or C [fall]), e.g. `2019C` for fall 2019. We organize requirements by semester so that we
don't get huge related sets which don't give particularly good info.

# paths./api/base/{semester}/pre-ngss-requirements/.get.responses.200.content.application/json.schema.items.properties.name.description
The name of the requirement, e.g. 'Formal Reasoning Course', an SAS requirement
satisfied by CIS-120.

# paths./api/base/attributes/.get.description
(GET `/api/base/attributes/`)

Retrieve a list of unique attributes (introduced post-NGSS)

# paths./api/base/attributes/.get.responses.200.content.application/json.schema.items.properties.code.description
A registration attribute code, for instance 'WUOM' for Wharton OIDD Operations track.

# paths./api/base/attributes/.get.responses.200.content.application/json.schema.items.properties.school.description
What school/program this attribute belongs to, e.g. `SAS` for `ASOC` restriction or `WH` for `WUOM` or `MODE` for `QP`. Options and meanings:

"SAS" | "School of Arts and Sciences"
"LPS" | "College of Liberal and Professional Studies"
"SEAS" | "Engineering"
"DSGN" | "Design"
"GSE" | "Graduate School of Education"
"LAW" | "Law School"
"MED" | "School of Medicine"
"MODE" | "Grade Mode"
"VET" | "School of Veterinary Medicine"
"NUR" | "Nursing"
"WH" | "Wharton"

# paths./api/base/attributes/.get.responses.200.content.application/json.schema.items.properties.description.description
The registration attribute description, e.g. 'Wharton OIDD Operation'
for the WUOM attribute.

# paths./api/base/restrictions/.get.description
(GET `/api/base/restrictions/`)

Retrieve a list of unique restrictions (introduced post-NGSS)

# paths./api/base/restrictions/.get.responses.200.content.application/json.schema.items.properties.restriction_type.description
What the restriction is based on (e.g., Campus).

# paths./api/base/restrictions/.get.responses.200.content.application/json.schema.items.properties.inclusive.description
Whether this is an include or exclude restriction. Corresponds to the `incl_excl_ind`
response field. `True` if include (ie, `incl_excl_ind` is "I") and `False`
if exclude ("E").

# paths./api/base/restrictions/.get.responses.200.content.application/json.schema.items.properties.description.description
The registration restriction description.

# paths./api/base/statusupdate/{full_code}/.get.description
(GET `/api/base/statusupdate/{full_code}/`)

Retrieve all Status Update objects from the current semester for a specific section.

# paths./api/base/statusupdate/{full_code}/.get.parameters[].description
The code of the section which this status update applies to, in the form '{dept code}-{course code}-{section code}', e.g. `CIS-120-001` for the 001 section of CIS-120.

# paths./api/base/statusupdate/{full_code}/.get.responses.200.content.application/json.schema.properties.section.description
The code of the section which this status update applies to, in the form
'{dept code}-{course code}-{section code}', e.g. `CIS-120-001` for the
001 section of CIS-120.

# paths./api/base/statusupdate/{full_code}/.get.responses.200.content.application/json.schema.properties.old_status.description
The old status code (from which the section changed). Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# paths./api/base/statusupdate/{full_code}/.get.responses.200.content.application/json.schema.properties.new_status.description
The new status code (to which the section changed). Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# paths./api/base/statusupdate/{full_code}/.get.responses.200.content.application/json.schema.properties.alert_sent.description
Was an alert was sent to a User as a result of this status update?

# paths./api/base/statusupdate/{full_code}/.get.responses.200.description
Status Updates for section listed successfully.

# paths./api/base/friendship/.get.description
(GET `/api/base/friendship/`)

Get a list of all friendships and friendship requests (sent and recieved) for the
specified user. Filter the list by status (accepted, sent) to distinguish between
friendships and friendship requests.

User authentication required.

# paths./api/base/friendship/.get.responses.403.description
Access denied (missing or improper authentication).

# paths./api/base/friendship/.post.description
(POST `/api/base/friendship/`)

Create a friendship between two users (sender and recipient). If a previous request does
not exist between the two friendships, then we create friendship request. If a previous request
exists (where the recipient is the sender) and the recipient of a request hits this route, then
we accept the request.

User authentication required.

# paths./api/base/friendship/.post.requestBody.content.application/json.schema.properties.pennkey.description
The Pennkey of the user you are sending a friend request to or handling a request from.

# paths./api/base/friendship/.post.responses.403.description
Access denied (missing or improper authentication).

# paths./api/base/friendship/.post.responses.404.description
Username was None/ Username did not exist.

# paths./api/base/friendship/.delete.description
(DELETE `/api/base/friendship/`)

Delete a friendship between two users (sender and recipient). If there exists only
a friendship request between two users, then we either delete the friendship request
if the sender hits the route, or we reject the request if the recipient hits this route.

User authentication required.

# paths./api/base/friendship/.delete.parameters[].description
The Pennkey of the user you are ending/rejecting your friendship/friend request with.

# paths./api/base/friendship/.delete.responses.403.description
Access denied (missing or improper authentication).

# paths./api/base/friendship/.delete.responses.404.description
Friendship does not exist or Username does not exist.

# paths./api/plan/recommendations/.post.description
(POST `/api/plan/recommendations/`)

This route will optionally take in current and past courses. In order to
make recommendations solely on the user's courses in past and current PCP schedules, simply
omit both the curr_courses and past_courses fields in your request.
Otherwise, in order to specify past and current courses,
include a "curr-courses" and/or "past_courses" attribute in the request that should each contain
an array of string course full codes of the form DEPT-XXX (e.g. CIS-120).
If successful, this route will return a list of recommended courses, with the same schema
as the List Courses route, starting with the most relevant course. The number of
recommended courses returned can be specified using the n_recommendations attribute in the
request body, but if this attribute is omitted, the default will be 5.
If n_recommendations is not an integer, or is <=0, a 400 will be returned.
If curr_courses contains repeated courses or invalid courses or non-current courses, a
400 will be returned.
If past_courses contains repeated courses or invalid courses, a 400 will be returned.
If curr_courses and past_courses contain overlapping courses, a 400 will be returned.

User authentication required.

# paths./api/plan/recommendations/.post.requestBody.content.application/json.schema.properties.curr_courses.description
An array of courses the user is currently planning to take, each specified by its string full code, of the form DEPT-XXXX, e.g. CIS-1200.

# paths./api/plan/recommendations/.post.requestBody.content.application/json.schema.properties.past_courses.description
An array of courses the user has previously taken, each specified by its string full code, of the form DEPT-XXXX, e.g. CIS-1200.

# paths./api/plan/recommendations/.post.requestBody.content.application/json.schema.properties.n_recommendations.description
The number of course recommendations you want returned. Defaults to 5.

# paths./api/plan/recommendations/.post.responses.403.description
Access denied (missing or improper authentication).

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.id.description
The full code of the course, in the form '{dept code}-{course code}'
dash-joined department and code of the course, e.g. `CIS-120` for CIS-120.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.title.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.description.description
The description of the course, e.g. 'A fast-paced introduction to the fundamental concepts
of programming... [etc.]' for CIS-120.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.course_quality.description
The average course quality rating for this section, on a scale of 0-4.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.instructor_quality.description
The average instructor quality for this section, on a scale of 0-4.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.difficulty.description
The average difficult rating for this section, on a scale of 0-4.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.work_required.description
The average work required for this section, on a scale of 0-4.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.recommendation_score.description
The recommendation score for this course if the user is logged in, or null if the
the user is not logged in.

# paths./api/plan/recommendations/.post.responses.200.content.application/json.schema.items.properties.credits.description
The number of credits this course takes. This is precomputed for efficiency.

# paths./api/plan/recommendations/.post.responses.400.description
Invalid curr_courses, past_courses, or n_recommendations (see response).

# paths./api/degree/degreeplans/{id}/copy.post.description
(POST `/api/degree/degreeplans/{id}/copy`)

Copy a degree plan.

# paths./api/degree/degreeplans/{id}/copy.post.requestBody.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}/copy.post.requestBody.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}/copy.post.responses.201.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}/copy.post.responses.201.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}/degrees.post.description
(POST `/api/degree/degreeplans/{id}/degrees`)

Add or remove degrees from a degree plan.

# paths./api/degree/degreeplans/{id}/degrees.post.requestBody.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}/degrees.post.requestBody.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}/degrees.post.responses.201.content.application/json.schema.properties.name.description
The user's nickname for the degree plan.

# paths./api/degree/degreeplans/{id}/degrees.post.responses.201.content.application/json.schema.properties.degrees.description
The degrees belonging to this degree plan

# paths./api/degree/degreeplans/{id}/degrees.delete.description
(DELETE `/api/degree/degreeplans/{id}/degrees`)

Add or remove degrees from a degree plan.

# paths./api/degree/onboard-from-transcript/{degree_plan_id}.post.description
(POST `/api/degree/onboard-from-transcript/{degree_plan_id}`)

Given courses taken and degrees pursuing, determines an optimized assignment
of courses to degree rules and creates relevant Fulfillment objects.

# components.schemas.User.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# components.schemas.User.properties.profile.properties.email.description
The email of the User. Defaults to null.

# components.schemas.User.properties.profile.properties.phone.description
The phone number of the user. Defaults to null.
The phone number will be stored in the E164 format, but any form parseable by the
[phonenumbers library](https://pypi.org/project/phonenumbers/)
will be accepted and converted to E164 format automatically upon saving.

# components.schemas.User.properties.profile.properties.push_notifications.description
Defaults to False, changed to True if the User enables mobile push notifications
for PCA, rather than text notifications.

# components.schemas.User.properties.profile.description
The user profile object, storing collected info about the user.

# components.schemas.Schedule.properties.semester.description
The academic semester planned out by the schedule (of the form YYYYx where x is A
[for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# components.schemas.Schedule.properties.name.description
The user's nick-name for the schedule. No two schedules can match in all of the fields
`[name, semester, person]`

# components.schemas.PrimarySchedule.properties.user.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# components.schemas.PrimarySchedule.properties.user.description
The user to which the primary schedule belongs.

# components.schemas.PrimarySchedule.properties.schedule.properties.semester.description
The academic semester planned out by the schedule (of the form YYYYx where x is A
[for spring], B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# components.schemas.PrimarySchedule.properties.schedule.properties.name.description
The user's nick-name for the schedule. No two schedules can match in all of the fields
`[name, semester, person]`

# components.schemas.Break.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# components.schemas.Break.properties.location_string.description
This represents the location that the user can input themselves.
Will use a building object from a drop down or have it validated
or something so it can interact with map.
Didn't want to run into issue of users creating arbitrary
Room objects, so just using a char field

# components.schemas.Break.properties.name.description
The user's name for the break. No two breaks can match in all of the fields
`[name, person]`

# components.schemas.Break.properties.checked.description
Whether or not the break has been checked by the user. This is used to
determine if the break should be displayed in the user's schedule.

# components.schemas.Break.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# components.schemas.Registration.properties.created_at.description
The datetime at which this registration was created.

# components.schemas.Registration.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# components.schemas.Registration.properties.updated_at.description
The datetime at which this registration was last modified.

# components.schemas.Registration.properties.section.description
The dash-separated full code of the section associated with this Registration.

# components.schemas.Registration.properties.user.description
The Penn Labs Accounts username of the User who owns this Registration.

# components.schemas.Registration.properties.cancelled.description
Defaults to False, changed to True if the registration has been cancelled. A cancelled
registration will not trigger any alerts to be sent even if the relevant section opens.
A cancelled section can be resubscribed to (unlike deleted alerts), and will show up
on the manage alerts page on the frontend (also unlike deleted alerts). Note that once
a registration is cancelled, it cannot be uncancelled (resubscribing creates a new
registration which is accessible via the resubscribed_to field, related name of
resubscribed_from).

# components.schemas.Registration.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# components.schemas.Registration.properties.deleted.description
Defaults to False, changed to True if the registration has been deleted. A deleted
registration will not trigger any alerts to be sent even if the relevant section opens.
A deleted section cannot be resubscribed to or undeleted, and will not show up on the
manage alerts page on the frontend. It is kept in the database for analytics purposes,
even though it serves no immediate functional purpose for its original user.

# components.schemas.Registration.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# components.schemas.Registration.properties.auto_resubscribe.description
Defaults to False, in which case a registration will not be automatically resubscribed
after it triggers an alert to be sent (but the user can still resubscribe to a sent alert,
as long as it is not deleted). If set to True, the registration will be automatically
resubscribed to once it triggers an alert to be sent (this is useful in the case of
volatile sections which are opening and closing frequently, often before the user has
time to register).

# components.schemas.Registration.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# components.schemas.Registration.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# components.schemas.Registration.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# components.schemas.Registration.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# components.schemas.Registration.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# components.schemas.Registration.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# components.schemas.Registration.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# components.schemas.Registration.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# components.schemas.Registration.properties.section_status.description
The current status of the watched section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# components.schemas.DegreePlanList.properties.name.description
The user's nickname for the degree plan.

# components.schemas.DegreePlanDetail.properties.name.description
The user's nickname for the degree plan.

# components.schemas.DegreePlanDetail.properties.degrees.description
The degrees belonging to this degree plan

# components.schemas.DegreeList.properties.program.description
The program code for this degree, e.g., EU_BSE

# components.schemas.DegreeList.properties.degree.description
The degree code for this degree, e.g., BSE

# components.schemas.DegreeList.properties.major.description
The major code for this degree, e.g., BIOL

# components.schemas.DegreeList.properties.major_name.description
The name of the major for this degree, e.g., Africana Studies

# components.schemas.DegreeList.properties.concentration.description
The concentration code for this degree, e.g., BMAT

# components.schemas.DegreeList.properties.concentration_name.description
The name of the concentration for this degree, e.g., African American Studies

# components.schemas.DegreeList.properties.year.description
The effective year of this degree, e.g., 2023

# components.schemas.DegreeList.properties.credits.description
The minimum number of CUs required for this degree.

# components.schemas.DegreeList.properties.rules.description
The rules for this degree. Blank if this degree has no rules.

# components.schemas.DegreeDetail.properties.program.description
The program code for this degree, e.g., EU_BSE

# components.schemas.DegreeDetail.properties.degree.description
The degree code for this degree, e.g., BSE

# components.schemas.DegreeDetail.properties.major.description
The major code for this degree, e.g., BIOL

# components.schemas.DegreeDetail.properties.major_name.description
The name of the major for this degree, e.g., Africana Studies

# components.schemas.DegreeDetail.properties.concentration.description
The concentration code for this degree, e.g., BMAT

# components.schemas.DegreeDetail.properties.concentration_name.description
The name of the concentration for this degree, e.g., African American Studies

# components.schemas.DegreeDetail.properties.year.description
The effective year of this degree, e.g., 2023

# components.schemas.DegreeDetail.properties.credits.description
The minimum number of CUs required for this degree.

# components.schemas.DockedCourse.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# components.schemas.Fulfillment.properties.degree_plan.description
The degree plan with which this fulfillment is associated

# components.schemas.Fulfillment.properties.full_code.description
The dash-joined department and code of the course, e.g., `CIS-120`

# components.schemas.Fulfillment.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019. Null if this fulfillment
does not yet have a semester.

# components.schemas.Fulfillment.properties.unselected_rules.description
The rules this course fulfills that should be shown in the open-ended rule box
(as opposed to the expandable box). Blank if this course should not be included in
any open-ended rule boxes.

# components.schemas.Fulfillment.properties.legal.description
True if course associated with this fulfillment isn't illegally double counted anywhere,
false otherwise.

# components.schemas.CourseList.properties.id.description
The full code of the course, in the form '{dept code}-{course code}'
dash-joined department and code of the course, e.g. `CIS-120` for CIS-120.

# components.schemas.CourseList.properties.title.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# components.schemas.CourseList.properties.description.description
The description of the course, e.g. 'A fast-paced introduction to the fundamental concepts
of programming... [etc.]' for CIS-120.

# components.schemas.CourseList.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# components.schemas.CourseList.properties.course_quality.description
The average course quality rating for this section, on a scale of 0-4.

# components.schemas.CourseList.properties.instructor_quality.description
The average instructor quality for this section, on a scale of 0-4.

# components.schemas.CourseList.properties.difficulty.description
The average difficult rating for this section, on a scale of 0-4.

# components.schemas.CourseList.properties.work_required.description
The average work required for this section, on a scale of 0-4.

# components.schemas.CourseList.properties.recommendation_score.description
The recommendation score for this course if the user is logged in, or null if the
the user is not logged in.

# components.schemas.CourseList.properties.credits.description
The number of credits this course takes. This is precomputed for efficiency.

# components.schemas.CourseDetail.properties.id.description
The full code of the course, in the form '{dept code}-{course code}'
dash-joined department and code of the course, e.g. `CIS-120` for CIS-120.

# components.schemas.CourseDetail.properties.title.description
The title of the course, e.g. 'Programming Languages and Techniques I' for CIS-120.

# components.schemas.CourseDetail.properties.description.description
The description of the course, e.g. 'A fast-paced introduction to the fundamental concepts
of programming... [etc.]' for CIS-120.

# components.schemas.CourseDetail.properties.syllabus_url.description
A URL for the syllabus of the course, if available.
Not available for courses offered in or before spring 2022.

# components.schemas.CourseDetail.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# components.schemas.CourseDetail.properties.prerequisites.description
Text describing the prereqs for a course, e.g. 'CIS 120, 160' for CIS-121.

# components.schemas.CourseDetail.properties.course_quality.description
The average course quality rating for this section, on a scale of 0-4.

# components.schemas.CourseDetail.properties.instructor_quality.description
The average instructor quality for this section, on a scale of 0-4.

# components.schemas.CourseDetail.properties.difficulty.description
The average difficult rating for this section, on a scale of 0-4.

# components.schemas.CourseDetail.properties.work_required.description
The average work required for this section, on a scale of 0-4.

# components.schemas.CourseDetail.properties.credits.description
The number of credits this course takes. This is precomputed for efficiency.

# components.schemas.CourseDetail.properties.crosslistings.description
A list of the full codes (DEPT-###) of all crosslistings for this course
(not including this course).

# components.schemas.CourseDetail.properties.pre_ngss_requirements.description
A list of the pre-NGSS (deprecated since 2022B) academic requirements
this course fulfills.

# components.schemas.CourseDetail.properties.attributes.description
A list of attributes this course has. Attributes are typically
used to mark courses which students in a program/major should
take.

# components.schemas.CourseDetail.properties.restrictions.description
A list of NGSSRestrictions this course has. Restrictions provide information about
who can take a course.

# components.schemas.MiniSection.properties.section_id.description
The dash-separated dept, full-code, and section-code, e.g. `CIS-120-001` for the
001 lecture section of CIS-120.

# components.schemas.MiniSection.properties.status.description
The registration status of the section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# components.schemas.MiniSection.properties.activity.description
The section activity, e.g. `LEC` for CIS-120-001 (2020A). Options and meanings:

"" | "Undefined"
"CLN" | "Clinic"
"CRT" | "Clinical Rotation"
"DAB" | "Dissertation Abroad"
"DIS" | "Dissertation"
"DPC" | "Doctoral Program Exchange"
"FLD" | "Field Work"
"HYB" | "Hybrid"
"IND" | "Independent Study"
"LAB" | "Lab"
"LEC" | "Lecture"
"MST" | "Masters Thesis"
"ONL" | "Online"
"PRC" | "Practicum"
"REC" | "Recitation"
"SEM" | "Seminar"
"SRT" | "Senior Thesis"
"STU" | "Studio"

# components.schemas.MiniSection.properties.meeting_times.description
A JSON-stringified list of meeting times of the form
`{days code} {start time} - {end time}`, e.g.
`["MWF 09:00 AM - 10:00 AM","F 11:00 AM - 12:00 PM","T 05:00 PM - 06:00 PM"]` for
PHYS-151-001 (2020A). Each letter of the days code is of the form M, T, W, R, F for each
day of the work week, respectively (and multiple days are combined with concatenation).
To access the Meeting objects for this section, the related field `meetings` can be used.

# components.schemas.MiniSection.properties.instructors.description
A list of the names of the instructors teaching this section.

# components.schemas.MiniSection.properties.course_code.description
The full code of the course this section belongs to, e.g. `CIS-120` for CIS-120-001.

# components.schemas.MiniSection.properties.course_title.description
The title of the course this section belongs to, e.g.
'Programming Languages and Techniques I' for CIS-120-001.

# components.schemas.MiniSection.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# components.schemas.MiniSection.properties.registration_volume.description
The number of active PCA registrations watching this section.

# components.schemas.SectionDetail.properties.id.description
The dash-separated dept, full-code, and section-code, e.g. `CIS-120-001` for the
001 lecture section of CIS-120.

# components.schemas.SectionDetail.properties.status.description
The registration status of the section. Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# components.schemas.SectionDetail.properties.activity.description
The section activity, e.g. `LEC` for CIS-120-001 (2020A). Options and meanings:

"" | "Undefined"
"CLN" | "Clinic"
"CRT" | "Clinical Rotation"
"DAB" | "Dissertation Abroad"
"DIS" | "Dissertation"
"DPC" | "Doctoral Program Exchange"
"FLD" | "Field Work"
"HYB" | "Hybrid"
"IND" | "Independent Study"
"LAB" | "Lab"
"LEC" | "Lecture"
"MST" | "Masters Thesis"
"ONL" | "Online"
"PRC" | "Practicum"
"REC" | "Recitation"
"SEM" | "Seminar"
"SRT" | "Senior Thesis"
"STU" | "Studio"

# components.schemas.SectionDetail.properties.credits.description
The number of credits this section is worth.

# components.schemas.SectionDetail.properties.capacity.description
The max allowed enrollment across all crosslistings of this section.

# components.schemas.SectionDetail.properties.semester.description
The semester of the course (of the form YYYYx where x is A [for spring],
B [summer], or C [fall]), e.g. `2019C` for fall 2019.

# components.schemas.SectionDetail.properties.meetings.description
A list of the meetings of this section (each meeting is a continuous span of time
during which a section would meet).

# components.schemas.SectionDetail.properties.instructors.description
A list of the names of the instructors teaching this section.

# components.schemas.SectionDetail.properties.course_quality.description
The average course quality rating for this section, on a scale of 0-4.

# components.schemas.SectionDetail.properties.instructor_quality.description
The average instructor quality for this section, on a scale of 0-4.

# components.schemas.SectionDetail.properties.difficulty.description
The average difficult rating for this section, on a scale of 0-4.

# components.schemas.SectionDetail.properties.work_required.description
The average work required for this section, on a scale of 0-4.

# components.schemas.SectionDetail.properties.associated_sections.description
A list of all sections associated with the Course which this section belongs to; e.g. for
CIS-120-001, all of the lecture and recitation sections for CIS-120 (including CIS-120-001)
in the same semester.

# components.schemas.SectionDetail.properties.registration_volume.description
The number of active PCA registrations watching this section.

# components.schemas.PreNGSSRequirementList.properties.id.description
A string representation of the requirement, in the form '{code}@{school}'

# components.schemas.PreNGSSRequirementList.properties.code.description
The code identifying this requirement, e.g. `MFR` for 'Formal Reasoning Course',
an SAS requirement satisfied by CIS-120.

# components.schemas.PreNGSSRequirementList.properties.school.description
What school this requirement belongs to, e.g. `SAS` for the SAS 'Formal Reasoning Course' requirement satisfied by CIS-120. Options and meanings:

"SEAS" | "Engineering"
"WH" | "Wharton"
"SAS" | "College"

# components.schemas.PreNGSSRequirementList.properties.semester.description
The semester of the requirement (of the form YYYYx where x is A [for spring], B [summer],
or C [fall]), e.g. `2019C` for fall 2019. We organize requirements by semester so that we
don't get huge related sets which don't give particularly good info.

# components.schemas.PreNGSSRequirementList.properties.name.description
The name of the requirement, e.g. 'Formal Reasoning Course', an SAS requirement
satisfied by CIS-120.

# components.schemas.AttributeList.properties.code.description
A registration attribute code, for instance 'WUOM' for Wharton OIDD Operations track.

# components.schemas.AttributeList.properties.school.description
What school/program this attribute belongs to, e.g. `SAS` for `ASOC` restriction or `WH` for `WUOM` or `MODE` for `QP`. Options and meanings:

"SAS" | "School of Arts and Sciences"
"LPS" | "College of Liberal and Professional Studies"
"SEAS" | "Engineering"
"DSGN" | "Design"
"GSE" | "Graduate School of Education"
"LAW" | "Law School"
"MED" | "School of Medicine"
"MODE" | "Grade Mode"
"VET" | "School of Veterinary Medicine"
"NUR" | "Nursing"
"WH" | "Wharton"

# components.schemas.AttributeList.properties.description.description
The registration attribute description, e.g. 'Wharton OIDD Operation'
for the WUOM attribute.

# components.schemas.NGSSRestrictionList.properties.restriction_type.description
What the restriction is based on (e.g., Campus).

# components.schemas.NGSSRestrictionList.properties.inclusive.description
Whether this is an include or exclude restriction. Corresponds to the `incl_excl_ind`
response field. `True` if include (ie, `incl_excl_ind` is "I") and `False`
if exclude ("E").

# components.schemas.NGSSRestrictionList.properties.description.description
The registration restriction description.

# components.schemas.StatusUpdate.properties.section.description
The code of the section which this status update applies to, in the form
'{dept code}-{course code}-{section code}', e.g. `CIS-120-001` for the
001 section of CIS-120.

# components.schemas.StatusUpdate.properties.old_status.description
The old status code (from which the section changed). Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# components.schemas.StatusUpdate.properties.new_status.description
The new status code (to which the section changed). Options and meanings:

"O" | "Open"
"C" | "Closed"
"X" | "Cancelled"
"" | "Unlisted"

# components.schemas.StatusUpdate.properties.alert_sent.description
Was an alert was sent to a User as a result of this status update?

# components.schemas.Friendship.properties.sender.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# components.schemas.Friendship.properties.recipient.properties.username.description
Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.

# components.schemas.RegistrationCreate.properties.id.description
The id of the registration (can optionally be used to customize the id of a new registration, or to update an existing registration).

# components.schemas.RegistrationCreate.properties.created_at.description
The datetime at which this registration was created.

# components.schemas.RegistrationCreate.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# components.schemas.RegistrationCreate.properties.updated_at.description
The datetime at which this registration was last modified.

# components.schemas.RegistrationCreate.properties.section.description
The dash-separated full code of the section associated with this Registration.

# components.schemas.RegistrationCreate.properties.user.description
The User that registered for this alert. This object will be none if registration occurred
before the PCA refresh of Spring 2020 (before the refresh user's were only identified by
their email and phone numbers, which are legacy fields in this model now). This object
might also be none if registration occurred through a 3rd part API such as Penn Course
Notify (now that Notify has fallen this is an unlikely event).

# components.schemas.RegistrationCreate.properties.cancelled.description
Defaults to False, changed to True if the registration has been cancelled. A cancelled
registration will not trigger any alerts to be sent even if the relevant section opens.
A cancelled section can be resubscribed to (unlike deleted alerts), and will show up
on the manage alerts page on the frontend (also unlike deleted alerts). Note that once
a registration is cancelled, it cannot be uncancelled (resubscribing creates a new
registration which is accessible via the resubscribed_to field, related name of
resubscribed_from).

# components.schemas.RegistrationCreate.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# components.schemas.RegistrationCreate.properties.deleted.description
Defaults to False, changed to True if the registration has been deleted. A deleted
registration will not trigger any alerts to be sent even if the relevant section opens.
A deleted section cannot be resubscribed to or undeleted, and will not show up on the
manage alerts page on the frontend. It is kept in the database for analytics purposes,
even though it serves no immediate functional purpose for its original user.

# components.schemas.RegistrationCreate.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# components.schemas.RegistrationCreate.properties.auto_resubscribe.description
Set this to true to turn on auto resubscribe (causing the registration to automatically
resubscribe once it sends out a notification).  Default is false if not specified.

# components.schemas.RegistrationCreate.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# components.schemas.RegistrationCreate.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# components.schemas.RegistrationCreate.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# components.schemas.RegistrationCreate.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# components.schemas.RegistrationCreate.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# components.schemas.RegistrationCreate.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# components.schemas.RegistrationCreate.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# components.schemas.RegistrationCreate.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# components.schemas.RegistrationUpdate.properties.created_at.description
The datetime at which this registration was created.

# components.schemas.RegistrationUpdate.properties.original_created_at.description
The datetime at which the tail of the resubscribe chain to which this registration belongs
was created.  In other words, the datetime at which the user created the original
registration for this section, before resubscribing some number of times
(0 or more) to reach this registration.

# components.schemas.RegistrationUpdate.properties.updated_at.description
The datetime at which this registration was last modified.

# components.schemas.RegistrationUpdate.properties.section.description
The section that the user registered to be notified about.

# components.schemas.RegistrationUpdate.properties.user.description
The User that registered for this alert. This object will be none if registration occurred
before the PCA refresh of Spring 2020 (before the refresh user's were only identified by
their email and phone numbers, which are legacy fields in this model now). This object
might also be none if registration occurred through a 3rd part API such as Penn Course
Notify (now that Notify has fallen this is an unlikely event).

# components.schemas.RegistrationUpdate.properties.cancelled.description
Set this to true to cancel to this registration (making it inactive while keeping it
in List Registration).

# components.schemas.RegistrationUpdate.properties.cancelled_at.description
When was the registration cancelled? Null if it hasn't been cancelled.

# components.schemas.RegistrationUpdate.properties.deleted.description
Set this to true to delete this registration (making it inactive and preventing it from
showing up in List Registrations).

# components.schemas.RegistrationUpdate.properties.deleted_at.description
When was the registration deleted? Null if it hasn't been deleted.

# components.schemas.RegistrationUpdate.properties.auto_resubscribe.description
Set this to true to turn on auto resubscribe (causing the registration to automatically
resubscribe once it sends out a notification).

# components.schemas.RegistrationUpdate.properties.notification_sent.description
True if an alert has been sent to the user, false otherwise.

# components.schemas.RegistrationUpdate.properties.notification_sent_at.description
When was an alert sent to the user as a result of this registration?
Null if an alert was not sent.

# components.schemas.RegistrationUpdate.properties.last_notification_sent_at.description
The last time the user was sent an opening notification for this registration's
section. This property is None (or null in JSON) if no notification has been sent to the
user for this registration's section.

This is used on the frontend to tell the user a last time an alert was sent for
the SECTION of a certain registration in the manage alerts page. Since the idea of
Registration objects and resubscribe chains is completely abstracted out of the User's
understanding, they expect alerts to work by section (so the "LAST NOTIFIED"
column should tell them the last time they were alerted about that section).

# components.schemas.RegistrationUpdate.properties.close_notification.description
Defaults to false.  If set to true, the user will receive
        a close notification (an alert when the section closes after an
        alert was sent for it opening).

# components.schemas.RegistrationUpdate.properties.close_notification_sent.description
True if a close notification has been sent to the user, false otherwise.

# components.schemas.RegistrationUpdate.properties.close_notification_sent_at.description
When was a close notification sent to the user as a result of this registration?
Null if a close notification was not sent.

# components.schemas.RegistrationUpdate.properties.is_active.description
True if the registration would send an alert when the watched section changes to open,
False otherwise. This is equivalent to
[not(notification_sent or deleted or cancelled) and semester is current].

# components.schemas.RegistrationUpdate.properties.is_waiting_for_close.description
True if the registration is waiting to send a close notification to the user
once the section closes.  False otherwise.

# components.schemas.RegistrationUpdate.properties.resubscribe.description
Set this to true to resubscribe to this registration (only works if the registration
has sent a notification and hasn't been deleted).

# tags[].description
These routes allow interfacing with the user's PCP Schedules for the current semester,
stored on the backend. Ever since we integrated Penn Labs Accounts into PCP so that users
can store their schedules across devices and browsers, we have stored users' schedules on
our backend (rather than local storage).

# tags[].description
These routes allow interaction with the User object of a Penn Labs Accounts user.
We do not document `/accounts/...` authentication routes here, as they are described
by the [Authentication](#section/Authentication) section, and the
[Penn Labs Account Engine](https://www.notion.so/pennlabs/The-Accounts-Engine-726ccf8875e244f4b8dbf8a8f2c97a87?pvs=4)
Notion page.

# tags[].description
These routes expose a user's registration history (including
inactive and obsolete registrations) for the current semester.  Inactive registrations are
registrations which would not trigger a notification to be sent if their section opened,
and obsolete registrations are registrations which are not at the head of their resubscribe
chain.

# tags[].description
As the main API endpoints for PCA, these routes allow interaction with the user's
PCA registrations.  An important concept which is referenced throughout the documentation
for these routes is that of the "resubscribe chain".  A resubscribe chain is a chain
of PCA registrations where the tail of the chain was an original registration created
through a POST request to `/api/alert/registrations/` specifying a new section (one that
the user wasn't already registered to receive alerts for).  Each next element in the chain
is a registration created by resubscribing to the previous registration (once that
registration had triggered an alert to be sent), either manually by the user or
automatically if auto_resubscribe was set to true.  Then, it follows that the head of the
resubscribe chain is the most relevant Registration for that user/section combo; if any
of the registrations in the chain are active, it would be the head.  And if the head
is active, none of the other registrations in the chain are active.

Note that a registration will send an alert when the section it is watching opens, if and
only if it hasn't sent one before, it isn't cancelled, and it isn't deleted.  If a
registration would send an alert when the section it is watching opens, we call it
"active".  See the Create Registration docs for an explanation of how to create a new
registration, and the Update Registration docs for an explanation of how you can modify
a registration after it is created.

In addition to sending alerts for when a class opens up, we have also implemented
an optionally user-enabled feature called "close notifications".
If a registration has close_notification enabled, it will act normally when the watched
section opens up for the first time (triggering an alert to be sent). However, once the
watched section closes, it will send another alert (the email alert will be in the same
chain as the original alert) to let the user know that the section has closed. Thus,
if a user sees a PCA notification on their phone during a class for instance, they won't
need to frantically open up their laptop and check PennInTouch to see if the class is still
open just to find that it is already closed.  To avoid spam and wasted money, we DO NOT
send any close notifications over text. So the user must have an email saved or use
push notifications in order to be able to enable close notifications on a registration.
Note that the close_notification setting carries over across resubscriptions, but can be
disabled at any time using Update Registration.

After the PCA backend refactor in 2019C/2020A, all PCA Registrations have a `user` field
pointing to the user's Penn Labs Accounts User object.  In other words, we implemented a
user/accounts system for PCA which required that
people log in to use the website. Thus, the contact information used in PCA alerts
is taken from the user's User Profile.  You can edit this contact information using
Update User or Partial Update User.  If push_notifications is set to True, then
a push notification will be sent when the user is alerted, but no text notifications will
be sent (as that would be a redundant alert to the user's phone). Otherwise, an email
or a text alert is sent if and only if contact information for that medium exists in
the user's profile.