Skip to content

Reporting API ​

Base URL: /api/v1/reporting

Institutional reporting including IPEDS compliance reports, student reports, and grade reports.

Endpoints Overview ​

IPEDS Reports ​

MethodEndpointDescription
GET/ipeds/available_surveysList available IPEDS surveys
GET/ipeds/data_qualityGet IPEDS data quality report
GET/ipeds/filter_optionsTerms, award years and cohort years the surveys can be run for
GET/ipeds/fall_enrollmentGet fall enrollment report
GET/ipeds/completionsGet completions report
GET/ipeds/graduation_ratesGet graduation rates report

All Students Report ​

MethodEndpointDescription
GET/all-students/filter_optionsGet available filter options
GET/all-students/summaryGet student summary statistics
GET/all-students/studentsGet filtered student list
GET/all-students/unique_countGet unique student count

All Grades Report ​

MethodEndpointDescription
GET/all-grades/filter_optionsGet available filter options
GET/all-grades/summaryGet grade summary statistics
GET/all-grades/enrollmentsGet filtered grade/enrollment list
GET/all-grades/unique_countGet unique enrollment count

Grade Summary ​

MethodEndpointDescription
GET/grade-summary/filter_optionsList filter options (periods with grades, active programs)
GET/grade-summary/enrollmentsGet grade summary by enrollment

Midterm Grades ​

MethodEndpointDescription
GET/midterm-grades/filter_optionsStarted terms (newest first), grade letters (best first) and majors, within the caller's scope
GET/midterm-grades/enrollmentsOne row per enrollment with its midterm grade

IPEDS Reports ​

IPEDS (Integrated Postsecondary Education Data System) reports provide federally required institutional data.

They read the vw_ipeds_* views that migration 290 creates; a database without them answers 503 with a message naming the migration. Every IPEDS route is wrapped in requireUnrestricted: a REPORTS.IPEDS grant below ALL is refused. How each dimension is derived is in the admin guide.

The three survey endpoints share two query parameters:

ParameterDescription
summarytrue reads the _summary view (grouped counts) instead of one row per student
formatcsv streams a download instead of JSON

The JSON response is { "success": true, "count": n, "data": [...] } plus the filter echoed back.

Available Surveys ​

GET /api/v1/reporting/ipeds/available_surveys

List all available IPEDS survey components and their reporting status.

Example Request ​

bash
curl -X GET http://localhost:8000/api/v1/reporting/ipeds/available_surveys \
  -b cookies.txt

Data Quality ​

GET /api/v1/reporting/ipeds/data_quality

Counts the gaps in the inputs the IPEDS views read. Each issue is { field, table, missing_count, severity, description }, and only checks with a non-zero count are returned: unknown residency and missing admit status among recent students (HIGH), open degree programs with students but no CIP code (CRITICAL), recent term enrollments with neither a load nor attempted credits (MEDIUM), and students missing gender (MEDIUM). A check that fails to run is logged and omitted rather than reported as passing.


Filter Options ​

GET /api/v1/reporting/ipeds/filter_options

What each survey can be run for, read from the data: terms (every term with enrollments, newest first, each with term_code, term_name, start_date and is_fall), default_term (the most recent fall term that has started), award_years (from vw_ipeds_completions) and cohort_years (from the federal FED- cohorts' names).

Example Request ​

bash
curl -X GET http://localhost:8000/api/v1/reporting/ipeds/data_quality \
  -b cookies.txt

Fall Enrollment ​

GET /api/v1/reporting/ipeds/fall_enrollment

Get the IPEDS Fall Enrollment survey data: one row per student enrolled in the term, or with summary=true the headcount by level, student type, full-time status, gender and race/ethnicity. Filter with term_code; any term may be passed, not only a fall one.

Example Request ​

bash
curl -X GET http://localhost:8000/api/v1/reporting/ipeds/fall_enrollment \
  -b cookies.txt

Completions ​

GET /api/v1/reporting/ipeds/completions

Get the IPEDS Completions survey data: one row per conferred award, or with summary=true the count by award year, CIP code, award level, gender and race/ethnicity. Filter with year, the IPEDS award year (July 1 to June 30, named by the year it ends in).

Example Request ​

bash
curl -X GET http://localhost:8000/api/v1/reporting/ipeds/completions \
  -b cookies.txt

Graduation Rates ​

GET /api/v1/reporting/ipeds/graduation_rates

Get the IPEDS Graduation Rates survey data: one row per member of a federal (FED-) cohort, with graduated_100_time, graduated_150_time and transferred_out (always null -- no transfer-out data exists), or with summary=true the cohort size and graduate counts. Filter with cohort_year.

Example Request ​

bash
curl -X GET http://localhost:8000/api/v1/reporting/ipeds/graduation_rates \
  -b cookies.txt

All Students Report ​

A configurable report that provides a comprehensive view of all student records with filtering and summary statistics.

Filter Options ​

GET /api/v1/reporting/all-students/filter_options

Get available filter options for the all students report. Returns lists of terms, statuses, campuses, programs, and other filterable fields.

Example Request ​

bash
curl -X GET http://localhost:8000/api/v1/reporting/all-students/filter_options \
  -b cookies.txt

Summary ​

GET /api/v1/reporting/all-students/summary

The pivot table: one row per major (or minor), one column per academic year (or term), each cell a COUNT(DISTINCT student_id).

Majors and minors fan out — a student is counted under every one they held during the period (migration 105) — so the cells in a column sum well above the number of students in it. That is why the totals are separate counts rather than sums: row.total, column_totals[] and grand_total are each their own COUNT(DISTINCT student_id), computed as extra GROUPING SETS in the same query as the cells (migration 173). Do not add cells up.

Query Parameters ​

ParameterTypeDescription
group_bystringyear (default) or term — what the columns are
row_typestringmajor (default) or minor — what the rows are
academic_yearsstringComma-separated academic_year_id list
termsstringComma-separated term_id list. Only applied when group_by=term; the by-year views carry no term_id
campusesstringComma-separated campus_id list
majorsstringComma-separated major_id list; applied only when row_type=major
minorsstringComma-separated minor_id list; applied only when row_type=minor
include_totalsboolfalse omits the three total grouping sets

Unrecognised group_by / row_type values fall back to year / major; the response echoes the pair that actually ran.

Response ​

json
{
  "success": true,
  "scope": "ALL",
  "group_by": "year",
  "row_type": "major",
  "columns": [{ "id": 2921, "code": "2024-2025", "name": "2024-2025" }],
  "rows": [{
    "id": 10845, "code": "ND.PHAR", "name": "Pre-Pharmacy",
    "cells": [{ "column_id": 2921, "column_code": "2024-2025", "count": 6 }],
    "total": 7
  }],
  "column_totals": [{ "column_id": 2921, "column_code": "2024-2025", "count": 1376 }],
  "grand_total": 2037,
  "include_totals": true
}

Example Request ​

bash
curl -X GET "http://localhost:8000/api/v1/reporting/all-students/summary?group_by=year&row_type=major&academic_years=2921,2980"   -b cookies.txt

Students ​

GET /api/v1/reporting/all-students/students

The drill-down behind one number in the pivot: the students it counted, one row each. count equals the pivot number the parameters describe — a cell, a row total, a column total or the grand total — provided the same period and program sets are passed.

Query Parameters ​

Every filter takes a plural (set) form and a singular form; the plural wins when both are present. A cell drill-down passes one of each; a row total passes every displayed period; a column total passes the report's program filter; the grand total passes both.

ParameterTypeDescription
academic_year_idsstringComma-separated academic_year_id list
term_idsstringComma-separated term_id list
campus_idsstringComma-separated campus_id list
major_idsstringComma-separated major_id list; 0 is the "No Declared Major" bucket
minor_idsstringComma-separated minor_id list; 0 is the "No Declared Minor" bucket
academic_year_id, term_id, campus_id, major_id, minor_idintegerSingular equivalents
fieldsstringComma-separated column list; honoured by format=csv
formatstringcsv streams a download instead of JSON

Passing a term set scopes the point-in-time window to terms; otherwise a year set scopes it to academic years. Passing neither leaves the window unbounded, which counts a major's whole history and will not match any pivot number.

Returned fields ​

student_number, first_name, last_name, preferred_first_name, preferred_email, primary_email, date_of_birth, gender_display, ethnicity_display, religion_display, country_of_birth, citizenship_country, races, major_codes, major_names, minor_codes, minor_names, all_major_codes, all_major_names, all_minor_codes, all_minor_names, majors_minors_combined, academic_status, class_standing, start_term, and -- for a caller holding REPORTS.ALL_STUDENTS.GPA -- overall_gpa, plus term_gpa when exactly one term is requested (migration 275) — echoed as available_fields. Without that node the GPA fields are never selected, so they are absent from both the JSON and the CSV, and cannot be sorted on.

academic_status is the latest status on file, or on a single-term request the status as of the term's end date. GPA and class standing are read from the cached per-level figures, for the academic level carrying the most attempted credits in the requested periods (falling back to the all-levels figures on the student row). start_term is Colleague's declared start term (STA_START_TERM) for that same level, as the term name; it sorts by the term's start date. It is not the first term the student enrolled in. person_id also comes back, for linking to the person record; it is not an exportable column.

major_codes / major_names / minor_codes / minor_names list what the student held during the periods requested, so they agree with the row that was clicked. The all_* fields are instead the student's currently held programs (end_date IS NULL) — which is how a double major stays visible when you have drilled into only one of them — with the primary major first. majors_minors_combined pairs the two current code lists as majors / minors.

These last five reproduce vw_student_all_majors, vw_student_all_minors and vw_student_races in the handler rather than reading them through vw_student_report_detail. Joining that view made Postgres compute all three aggregates for every student in the institution to answer a few hundred rows, at 13.6M planner cost, which exhausted the postgres container's /dev/shm on production and failed the request with SQLSTATE 53100. The duplication is held to the views by internal/domain/reporting/parity_live_test.go.

Example Request ​

bash
# the Pre-Pharmacy row total across two academic years
curl -X GET "http://localhost:8000/api/v1/reporting/all-students/students?academic_year_ids=2921,2980&major_ids=10845"   -b cookies.txt

Unique Count ​

GET /api/v1/reporting/all-students/unique_count

A single COUNT(DISTINCT student_id) for one filter combination. The report no longer uses it — /summary returns every total it needs — but it remains for ad hoc counting.

Query Parameters ​

Takes the plural forms only: academic_year_ids, term_ids, campus_ids, major_ids, minor_ids (comma-separated ids; 0 is the "No Declared" bucket). Singular spellings are ignored here.

Example Request ​

bash
curl -X GET "http://localhost:8000/api/v1/reporting/all-students/unique_count?academic_year_ids=2921,2980"   -b cookies.txt

All Grades Report ​

A configurable report that provides a view of all grade and enrollment records with filtering and summary statistics.

Filter Options ​

GET /api/v1/reporting/all-grades/filter_options

Get available filter options for the all grades report. Returns lists of terms, courses, sections, grade values, and other filterable fields.

Example Request ​

bash
curl -X GET http://localhost:8000/api/v1/reporting/all-grades/filter_options \
  -b cookies.txt

Summary ​

GET /api/v1/reporting/all-grades/summary

Get summary statistics for grades matching the current filters. Includes grade distribution, average GPA, and counts by course or section.

Query Parameters ​

Accepts the same filter parameters as the enrollments endpoint.

Example Request ​

bash
curl -X GET "http://localhost:8000/api/v1/reporting/all-grades/summary?term_id=8" \
  -b cookies.txt

Enrollments ​

GET /api/v1/reporting/all-grades/enrollments

Get a filtered and paginated list of enrollment/grade records for the report.

Query Parameters ​

ParameterTypeDescription
term_idintegerFilter by term
course_idintegerFilter by course
section_idintegerFilter by section
grade_idintegerFilter by grade
searchstringSearch in student name, course code
orderingstringSort field
pageintegerPage number
page_sizeintegerResults per page

Example Request ​

bash
curl -X GET "http://localhost:8000/api/v1/reporting/all-grades/enrollments?term_id=8&page=1&page_size=25" \
  -b cookies.txt

Unique Count ​

GET /api/v1/reporting/all-grades/unique_count

Get the count of unique enrollment records matching the current filters.

Query Parameters ​

Accepts the same filter parameters as the enrollments endpoint.

Example Request ​

bash
curl -X GET "http://localhost:8000/api/v1/reporting/all-grades/unique_count?term_id=8" \
  -b cookies.txt

What these reports count ​

Both grade reports read records.vw_grade_enrollment_base, which holds the enrollments that are part of a student's academic record. Three kinds are never in it:

  • Dropped enrollments (DROPPED).
  • Cancelled enrollments (CANCELLED) — Colleague's STC_CURRENT_STATUS = 'C'. These were imported as COMPLETED until migration 243 and appeared as ungraded rows in both reports.
  • Enrollments carrying Colleague grade X, whose legend is "Used for classes deleted". The same fact, recorded on the grade instead of the status.

They remain visible in the student record at GET /registration/enrollments/by_student; they are excluded from reporting, not deleted.

Withdrawn enrollments are the one case you can choose. They are excluded by default — which is what these reports have always done — and include_withdrawn=true puts them back. The flag must be passed identically to a pivot and to its drill-down, or a cell will not match the list behind it.

ParameterTypeDescription
include_withdrawnbooleantrue to count WITHDRAWN enrollments. Default false. Accepted by /all-grades/summary, /all-grades/enrollments, /all-grades/unique_count, /grade-summary/enrollments and /grading/grade-summary

Grade Summary ​

The pivot itself is served by the grading domain at GET /api/v1/grading/grade-summary (group_by=term|year, term_ids=, academic_year_ids=). The two endpoints here back its pickers and its drill-down.

Filter Options ​

GET /api/v1/reporting/grade-summary/filter_options

Every picker on the report in one unpaginated response. The report used to build these from the paginated /academic list endpoints, which return 20 rows in ascending order by default -- so the year picker offered the 20 oldest academic years (the 1950s) and the major picker 20 of 441.

academic_years and terms are restricted to periods that actually carry grades, using the same predicate as /academic/terms/latest_active; majors and minors to programs that have not ended. Under a UNIT-scoped grant in the students lens, the program lists narrow to the caller's own programs.

ParameterTypeDescription
unit_viewstringcourses (default) or students; only meaningful for UNIT-scoped grants

Returns { success, scope, unit_view, academic_years, terms, majors, minors }, where each option is {id, code, name?} and a term also carries academic_year_id.

Enrollments by Grade ​

GET /api/v1/reporting/grade-summary/enrollments

The drill-down behind a clicked number: the enrollments making up one cell, one row total, one column total, or the grand total.

Query Parameters ​

ParameterTypeDescription
term_idsstringComma-separated term ids -- the set of periods the number spans
academic_year_idsstringComma-separated academic year ids, for a year-grouped pivot
term_idintegerSingle-term form, accepted for one-cell links
academic_year_idintegerSingle-year form
letter_gradestringFilter to one grade; omit for every grade
major_idintegerFilter by declared major (0 = no declared major)
minor_idintegerFilter by currently-held minor
include_withdrawnbooleantrue to include WITHDRAWN enrollments; default false. Must match the pivot
fieldsstringComma-separated columns to return
formatstringcsv to download instead of JSON

Pass the plural forms for a total that spans several periods. Omitting the period entirely means every period in the database, which is rarely what a total covers.

Example Request ​

bash
curl -X GET "http://localhost:8000/api/v1/reporting/grade-summary/enrollments?term_ids=8,9&letter_grade=A" \
  -b cookies.txt



Midterm Grades ​

Midterm grades by term, for registrars, deans, advisors and faculty (migration 292). Gated on REPORTS.MIDTERM_GRADES, and unlike every other report it honours personal scopes: ALL, UNIT (with the same unit_view=courses|students lens as All Grades), ADVISEES (the caller's current advisees) and OWN_SECTIONS (sections the caller teaches). Its population matches All Grades: dropped and cancelled enrollments never, withdrawn ones only with include_withdrawn=true.

Enrollments ​

GET /api/v1/reporting/midterm-grades/enrollments

Query Parameters ​

ParameterTypeDescription
term_idstringComma-separated term ids
gradesstringComma-separated letter grades to include (the screen presets C- and below). Letters match across grading scales
include_ungradedbooleanAlso list enrollments with no midterm grade. With no grades, lists every enrollment; with neither, every enrollment that has a midterm grade
include_withdrawnbooleanInclude withdrawn enrollments
major_ids / major_idstringFilter by major
course_id, teacher_idintegerFilter by course or instructor
page, page_size, with_count, orderingPaging and sort, as for the other drill-downs
formatstringcsv streams every matching row

Returned fields ​

enrollment_id, student_id, student_number, first_name, last_name, preferred_email, major_codes, major_names, course_code, course_title, section_code, term_code, term_name, teacher_name, midterm_grade, midterm_grade_date, midterm_grade_source (SIS or ODS), final_grade, enrollment_status_code. person_id also comes back for linking, but is not an exportable column. The response carries the applied scope.


Complete endpoint reference ​

Every route this domain registers, with the permission node that gates it. Generated from the route table, so it is complete by construction — the sections above explain behaviour, this one guarantees nothing is missing.

Paths are relative to /api/v1/reporting. A node in italics is an exemption rather than a grant: selfservice acts only on the caller's own record, public needs no session at all, and custom carries its own wrapper.

MethodEndpointPermission nodeDescription
GET/all-grades/enrollmentsREPORTS.ALL_GRADESList enrollments
GET/all-grades/filter_optionsREPORTS.ALL_GRADESList filter options
GET/all-grades/summaryREPORTS.ALL_GRADESGet summary
GET/all-grades/unique_countREPORTS.ALL_GRADESGet unique count
GET/all-students/filter_optionsREPORTS.ALL_STUDENTSList filter options
GET/all-students/studentsREPORTS.ALL_STUDENTSList students
GET/all-students/summaryREPORTS.ALL_STUDENTSGet summary
GET/all-students/unique_countREPORTS.ALL_STUDENTSGet unique count
GET/grade-summary/enrollmentsREPORTS.GRADE_SUMMARYList enrollments
GET/grade-summary/filter_optionsREPORTS.GRADE_SUMMARYList filter options
GET/ipeds/available_surveysREPORTS.IPEDSList available surveys
GET/ipeds/completionsREPORTS.IPEDSList completions
GET/ipeds/data_qualityREPORTS.IPEDSGet data quality
GET/ipeds/fall_enrollmentREPORTS.IPEDSGet fall enrollment
GET/ipeds/filter_optionsREPORTS.IPEDSList IPEDS terms, award years and cohort years
GET/ipeds/graduation_ratesREPORTS.IPEDSList graduation rates
GET/midterm-grades/enrollmentsREPORTS.MIDTERM_GRADESList midterm grades
GET/midterm-grades/filter_optionsREPORTS.MIDTERM_GRADESList midterm report filter options

Student Information System Documentation