{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"CourseGrid Public API","version":"v1","description":"Read-only. No API key, no account, no cost. Every response is a JSON object with a top-level `data` (or `error`) field plus a `meta` envelope carrying the API version, an import-freshness verdict, and this disclaimer:\n\nCourseGrid is independent and not affiliated with, endorsed by, or sponsored by San Diego State University or the California State University system. Data may be outdated; confirm on the official SDSU portal before registering. CourseGrid performs no enrollment actions.\n\nResponses are cached and rate-limited; a 429 carries `X-RateLimit-*` and `Retry-After` headers. CORS is open for GET and OPTIONS from any origin."},"servers":[{"url":"https://coursegrid.io/","description":"Production"}],"paths":{"/api/v1/terms":{"get":{"operationId":"listTerms","summary":"List terms","description":"Every term with at least one section on file, newest first.","responses":{"200":{"description":"Terms on file.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","description":"SDSU's internal term code, e.g. '2267'."},"label":{"type":"string","description":"Human-readable term name, e.g. 'Fall 2026'."},"startsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"endsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"sectionCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"isDefault":{"type":"boolean","description":"True for the term GET /api/v1/courses/{slug} uses when ?term= is omitted."}},"required":["code","label","startsAt","endsAt","sectionCount","isDefault"],"additionalProperties":false}},"meta":{"type":"object","properties":{"version":{"type":"string"},"freshness":{"type":"object","properties":{"verdict":{"type":"string","enum":["fresh","aging","stale","never-run"]},"lastImportAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["verdict","lastImportAt"],"additionalProperties":false},"docs":{"type":"string","description":"Absolute URL to /docs/api."},"source":{"type":"string"},"disclaimer":{"type":"string"}},"required":["version","freshness","docs","source","disclaimer"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"examples":{"default":{"value":{"data":[{"code":"2267","label":"Fall 2026","startsAt":"2026-08-24T00:00:00.000Z","endsAt":"2026-12-12T00:00:00.000Z","sectionCount":6002,"isDefault":true}],"meta":{"version":"v1","freshness":{"verdict":"fresh","lastImportAt":"2026-08-25T09:03:00.000Z"},"docs":"https://coursegrid.io/docs/api","source":"San Diego State University public class search","disclaimer":"CourseGrid is independent and not affiliated with, endorsed by, or sponsored by San Diego State University or the California State University system. Data may be outdated; confirm on the official SDSU portal before registering. CourseGrid performs no enrollment actions."}}}}}}},"429":{"description":"Rate limit exceeded. Retry after the window named in Retry-After.","headers":{"Retry-After":{"description":"Seconds until the rate limit window resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"500":{"description":"An internal error occurred.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/api/v1/courses":{"get":{"operationId":"listCourses","summary":"Search courses","description":"Courses matching the given filters, paginated. Without `subject`, `q` searches across title/subject/number, or all courses in `term` if no other filters are given.","parameters":[{"name":"subject","in":"query","required":false,"description":"Subject code, e.g. 'CS'. Case-insensitive.","schema":{"type":"string","maxLength":10,"pattern":"^[A-Za-z ]*$"}},{"name":"term","in":"query","required":false,"description":"Term code to filter section counts by. Defaults to the current default term.","schema":{"default":"2267","type":"string","minLength":1,"maxLength":50,"pattern":"^[A-Z0-9_]+$"}},{"name":"q","in":"query","required":false,"description":"Free-text search across course title, subject, and number.","schema":{"type":"string","maxLength":200}},{"name":"number","in":"query","required":false,"description":"Course number, or a number prefix (e.g. '4' matches 400-level courses).","schema":{"type":"string","maxLength":20,"pattern":"^[0-9A-Za-z-]*$"}},{"name":"page","in":"query","required":false,"description":"1-indexed page number. Default 1.","schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","in":"query","required":false,"description":"Results per page, 1-200. Default 50.","schema":{"default":50,"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"A page of matching courses.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The canonical course slug, e.g. 'CS-460'."},"subject":{"type":"string"},"number":{"type":"string"},"code":{"type":"string","description":"'{subject} {number}', e.g. 'CS 460'."},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"units":{"anyOf":[{"type":"string"},{"type":"null"}]},"prerequisites":{"anyOf":[{"type":"object","properties":{"text":{"type":"string"},"confidence":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["text","confidence"],"additionalProperties":false},{"type":"null"}],"description":"Raw prerequisite text as published, plus a parse-confidence hint."},"requirements":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["code","name"],"additionalProperties":false},"description":"General-education / degree requirements this course satisfies, deduped by code."},"url":{"type":"string","description":"Absolute URL to this course's page on coursegrid.io."},"sectionCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sections":{"description":"Only present on GET /api/v1/courses/{slug} -- the list endpoint returns counts only.","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"classNumber":{"anyOf":[{"type":"string"},{"type":"null"}]},"sectionCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"Raw status enum, e.g. 'OPEN', 'CLOSED', 'WAITLIST'."},"statusLabel":{"type":"string"},"modality":{"type":"string","description":"Raw modality enum, e.g. 'IN_PERSON', 'ONLINE', 'HYBRID'."},"modalityLabel":{"type":"string"},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"capacity":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Null when never captured -- common for waitlisted sections. Never a guess."},"enrolled":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"waitlist":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"openSeats":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"capacity - enrolled. Null whenever either input is null, never a wrong number."},"meetings":{"type":"array","items":{"type":"object","properties":{"days":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Raw meeting-days code, e.g. 'MW' or 'TR' ('R' = Thursday)."},"daysLabel":{"type":"string","description":"Human-readable days, e.g. 'Mon, Wed'."},"startMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Start time in minutes past midnight."},"endMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"startTime":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start time as a label, e.g. '9:00 AM'."},"endTime":{"anyOf":[{"type":"string"},{"type":"null"}]},"building":{"anyOf":[{"type":"string"},{"type":"null"}]},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"location":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["days","daysLabel","startMin","endMin","startTime","endTime","building","room","location"],"additionalProperties":false}},"instructors":{"type":"array","items":{"type":"string"}}},"required":["id","classNumber","sectionCode","status","statusLabel","modality","modalityLabel","room","capacity","enrolled","waitlist","openSeats","meetings","instructors"],"additionalProperties":false}},"availableTerms":{"description":"Only present on GET /api/v1/courses/{slug}, and only when SDSU offers this course in more than one term on file.","type":"array","items":{"type":"string"}}},"required":["id","subject","number","code","title","units","prerequisites","requirements","url","sectionCount"],"additionalProperties":false}},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"pageSize":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"hasMore":{"type":"boolean"},"meta":{"type":"object","properties":{"version":{"type":"string"},"freshness":{"type":"object","properties":{"verdict":{"type":"string","enum":["fresh","aging","stale","never-run"]},"lastImportAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["verdict","lastImportAt"],"additionalProperties":false},"docs":{"type":"string","description":"Absolute URL to /docs/api."},"source":{"type":"string"},"disclaimer":{"type":"string"}},"required":["version","freshness","docs","source","disclaimer"],"additionalProperties":false}},"required":["data","page","pageSize","total","hasMore","meta"],"additionalProperties":false},"examples":{"default":{"value":{"data":[{"id":"CS-460","subject":"CS","number":"460","code":"CS 460","title":"Software Engineering","units":"3","prerequisites":{"text":"CS 310 with a grade of C or better","confidence":"high"},"requirements":[],"url":"https://coursegrid.io/course/CS-460","sectionCount":3}],"page":1,"pageSize":50,"total":1,"hasMore":false,"meta":{"version":"v1","freshness":{"verdict":"fresh","lastImportAt":"2026-08-25T09:03:00.000Z"},"docs":"https://coursegrid.io/docs/api","source":"San Diego State University public class search","disclaimer":"CourseGrid is independent and not affiliated with, endorsed by, or sponsored by San Diego State University or the California State University system. Data may be outdated; confirm on the official SDSU portal before registering. CourseGrid performs no enrollment actions."}}}}}}},"400":{"description":"A query parameter failed validation.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false},"examples":{"default":{"value":{"error":{"code":"invalid_parameter","message":"Invalid 'pageSize': Too big: expected number to be <=200","details":{"field":"pageSize"}}}}}}}},"429":{"description":"Rate limit exceeded. Retry after the window named in Retry-After.","headers":{"Retry-After":{"description":"Seconds until the rate limit window resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"500":{"description":"An internal error occurred.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/api/v1/courses/{slug}":{"get":{"operationId":"getCourse","summary":"Get one course","description":"One course and its sections for the given term (defaults to the newest term with sections on file).","parameters":[{"name":"slug","in":"path","required":true,"description":"The canonical course slug: subject and number joined with a dash, e.g. 'CS-460' or 'E-E-101'. A non-canonical spelling (e.g. 'cs460') 308-redirects to the canonical URL rather than 404ing.","schema":{"type":"string","pattern":"^[A-Z0-9-]+$"}},{"name":"term","in":"query","required":false,"description":"Term code. Defaults to the newest term with sections on file.","schema":{"type":"string","minLength":1,"maxLength":50,"pattern":"^[A-Z0-9_]+$"}}],"responses":{"200":{"description":"The course and its sections.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"The canonical course slug, e.g. 'CS-460'."},"subject":{"type":"string"},"number":{"type":"string"},"code":{"type":"string","description":"'{subject} {number}', e.g. 'CS 460'."},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"units":{"anyOf":[{"type":"string"},{"type":"null"}]},"prerequisites":{"anyOf":[{"type":"object","properties":{"text":{"type":"string"},"confidence":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["text","confidence"],"additionalProperties":false},{"type":"null"}],"description":"Raw prerequisite text as published, plus a parse-confidence hint."},"requirements":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["code","name"],"additionalProperties":false},"description":"General-education / degree requirements this course satisfies, deduped by code."},"url":{"type":"string","description":"Absolute URL to this course's page on coursegrid.io."},"sectionCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sections":{"description":"Only present on GET /api/v1/courses/{slug} -- the list endpoint returns counts only.","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"classNumber":{"anyOf":[{"type":"string"},{"type":"null"}]},"sectionCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"Raw status enum, e.g. 'OPEN', 'CLOSED', 'WAITLIST'."},"statusLabel":{"type":"string"},"modality":{"type":"string","description":"Raw modality enum, e.g. 'IN_PERSON', 'ONLINE', 'HYBRID'."},"modalityLabel":{"type":"string"},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"capacity":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Null when never captured -- common for waitlisted sections. Never a guess."},"enrolled":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"waitlist":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"openSeats":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"capacity - enrolled. Null whenever either input is null, never a wrong number."},"meetings":{"type":"array","items":{"type":"object","properties":{"days":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Raw meeting-days code, e.g. 'MW' or 'TR' ('R' = Thursday)."},"daysLabel":{"type":"string","description":"Human-readable days, e.g. 'Mon, Wed'."},"startMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Start time in minutes past midnight."},"endMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"startTime":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start time as a label, e.g. '9:00 AM'."},"endTime":{"anyOf":[{"type":"string"},{"type":"null"}]},"building":{"anyOf":[{"type":"string"},{"type":"null"}]},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"location":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["days","daysLabel","startMin","endMin","startTime","endTime","building","room","location"],"additionalProperties":false}},"instructors":{"type":"array","items":{"type":"string"}}},"required":["id","classNumber","sectionCode","status","statusLabel","modality","modalityLabel","room","capacity","enrolled","waitlist","openSeats","meetings","instructors"],"additionalProperties":false}},"availableTerms":{"description":"Only present on GET /api/v1/courses/{slug}, and only when SDSU offers this course in more than one term on file.","type":"array","items":{"type":"string"}}},"required":["id","subject","number","code","title","units","prerequisites","requirements","url","sectionCount"],"additionalProperties":false},"meta":{"type":"object","properties":{"version":{"type":"string"},"freshness":{"type":"object","properties":{"verdict":{"type":"string","enum":["fresh","aging","stale","never-run"]},"lastImportAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["verdict","lastImportAt"],"additionalProperties":false},"docs":{"type":"string","description":"Absolute URL to /docs/api."},"source":{"type":"string"},"disclaimer":{"type":"string"}},"required":["version","freshness","docs","source","disclaimer"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false},"examples":{"default":{"value":{"data":{"id":"CS-460","subject":"CS","number":"460","code":"CS 460","title":"Software Engineering","units":"3","prerequisites":{"text":"CS 310 with a grade of C or better","confidence":"high"},"requirements":[],"url":"https://coursegrid.io/course/CS-460","sectionCount":3,"sections":[{"id":"sec-1","classNumber":"12345","sectionCode":"01","status":"OPEN","statusLabel":"Open","modality":"IN_PERSON","modalityLabel":"In person","room":"PG 242","capacity":35,"enrolled":28,"waitlist":0,"openSeats":7,"meetings":[{"days":"MW","daysLabel":"Mon, Wed","startMin":540,"endMin":590,"startTime":"9:00 AM","endTime":"9:50 AM","building":"PSFA","room":"310","location":"PSFA 310"}],"instructors":["A. Nguyen"]}]},"meta":{"version":"v1","freshness":{"verdict":"fresh","lastImportAt":"2026-08-25T09:03:00.000Z"},"docs":"https://coursegrid.io/docs/api","source":"San Diego State University public class search","disclaimer":"CourseGrid is independent and not affiliated with, endorsed by, or sponsored by San Diego State University or the California State University system. Data may be outdated; confirm on the official SDSU portal before registering. CourseGrid performs no enrollment actions."}}}}}}},"308":{"description":"The slug was not in canonical form; retry the request at the URL in Location.","headers":{"Location":{"description":"The canonical /api/v1/courses/{slug} URL.","schema":{"type":"string"}}}},"400":{"description":"A query parameter failed validation.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false},"examples":{"default":{"value":{"error":{"code":"invalid_parameter","message":"Invalid 'pageSize': Too big: expected number to be <=200","details":{"field":"pageSize"}}}}}}}},"404":{"description":"No course exists for this slug.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false},"examples":{"default":{"value":{"error":{"code":"not_found","message":"No course found for 'CS-9999'","details":{"code":"CS-9999"}}}}}}}},"429":{"description":"Rate limit exceeded. Retry after the window named in Retry-After.","headers":{"Retry-After":{"description":"Seconds until the rate limit window resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}},"500":{"description":"An internal error occurred.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/api/v1/openapi.json":{"get":{"operationId":"getOpenApiDocument","summary":"This document","description":"The OpenAPI 3.1 document describing every endpoint under /api/v1.","responses":{"200":{"description":"The OpenAPI 3.1 document.","content":{"application/json":{"schema":{"type":"object"}}}},"429":{"description":"Rate limit exceeded. Retry after the window named in Retry-After.","headers":{"Retry-After":{"description":"Seconds until the rate limit window resets.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}}},"components":{"schemas":{"Meeting":{"type":"object","properties":{"days":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Raw meeting-days code, e.g. 'MW' or 'TR' ('R' = Thursday)."},"daysLabel":{"type":"string","description":"Human-readable days, e.g. 'Mon, Wed'."},"startMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Start time in minutes past midnight."},"endMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"startTime":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start time as a label, e.g. '9:00 AM'."},"endTime":{"anyOf":[{"type":"string"},{"type":"null"}]},"building":{"anyOf":[{"type":"string"},{"type":"null"}]},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"location":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["days","daysLabel","startMin","endMin","startTime","endTime","building","room","location"],"additionalProperties":false},"Section":{"type":"object","properties":{"id":{"type":"string"},"classNumber":{"anyOf":[{"type":"string"},{"type":"null"}]},"sectionCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"Raw status enum, e.g. 'OPEN', 'CLOSED', 'WAITLIST'."},"statusLabel":{"type":"string"},"modality":{"type":"string","description":"Raw modality enum, e.g. 'IN_PERSON', 'ONLINE', 'HYBRID'."},"modalityLabel":{"type":"string"},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"capacity":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Null when never captured -- common for waitlisted sections. Never a guess."},"enrolled":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"waitlist":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"openSeats":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"capacity - enrolled. Null whenever either input is null, never a wrong number."},"meetings":{"type":"array","items":{"type":"object","properties":{"days":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Raw meeting-days code, e.g. 'MW' or 'TR' ('R' = Thursday)."},"daysLabel":{"type":"string","description":"Human-readable days, e.g. 'Mon, Wed'."},"startMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Start time in minutes past midnight."},"endMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"startTime":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start time as a label, e.g. '9:00 AM'."},"endTime":{"anyOf":[{"type":"string"},{"type":"null"}]},"building":{"anyOf":[{"type":"string"},{"type":"null"}]},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"location":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["days","daysLabel","startMin","endMin","startTime","endTime","building","room","location"],"additionalProperties":false}},"instructors":{"type":"array","items":{"type":"string"}}},"required":["id","classNumber","sectionCode","status","statusLabel","modality","modalityLabel","room","capacity","enrolled","waitlist","openSeats","meetings","instructors"],"additionalProperties":false},"Course":{"type":"object","properties":{"id":{"type":"string","description":"The canonical course slug, e.g. 'CS-460'."},"subject":{"type":"string"},"number":{"type":"string"},"code":{"type":"string","description":"'{subject} {number}', e.g. 'CS 460'."},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"units":{"anyOf":[{"type":"string"},{"type":"null"}]},"prerequisites":{"anyOf":[{"type":"object","properties":{"text":{"type":"string"},"confidence":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["text","confidence"],"additionalProperties":false},{"type":"null"}],"description":"Raw prerequisite text as published, plus a parse-confidence hint."},"requirements":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["code","name"],"additionalProperties":false},"description":"General-education / degree requirements this course satisfies, deduped by code."},"url":{"type":"string","description":"Absolute URL to this course's page on coursegrid.io."},"sectionCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sections":{"description":"Only present on GET /api/v1/courses/{slug} -- the list endpoint returns counts only.","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"classNumber":{"anyOf":[{"type":"string"},{"type":"null"}]},"sectionCode":{"anyOf":[{"type":"string"},{"type":"null"}]},"status":{"type":"string","description":"Raw status enum, e.g. 'OPEN', 'CLOSED', 'WAITLIST'."},"statusLabel":{"type":"string"},"modality":{"type":"string","description":"Raw modality enum, e.g. 'IN_PERSON', 'ONLINE', 'HYBRID'."},"modalityLabel":{"type":"string"},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"capacity":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Null when never captured -- common for waitlisted sections. Never a guess."},"enrolled":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"waitlist":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"openSeats":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"capacity - enrolled. Null whenever either input is null, never a wrong number."},"meetings":{"type":"array","items":{"type":"object","properties":{"days":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Raw meeting-days code, e.g. 'MW' or 'TR' ('R' = Thursday)."},"daysLabel":{"type":"string","description":"Human-readable days, e.g. 'Mon, Wed'."},"startMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Start time in minutes past midnight."},"endMin":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"startTime":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Start time as a label, e.g. '9:00 AM'."},"endTime":{"anyOf":[{"type":"string"},{"type":"null"}]},"building":{"anyOf":[{"type":"string"},{"type":"null"}]},"room":{"anyOf":[{"type":"string"},{"type":"null"}]},"location":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["days","daysLabel","startMin","endMin","startTime","endTime","building","room","location"],"additionalProperties":false}},"instructors":{"type":"array","items":{"type":"string"}}},"required":["id","classNumber","sectionCode","status","statusLabel","modality","modalityLabel","room","capacity","enrolled","waitlist","openSeats","meetings","instructors"],"additionalProperties":false}},"availableTerms":{"description":"Only present on GET /api/v1/courses/{slug}, and only when SDSU offers this course in more than one term on file.","type":"array","items":{"type":"string"}}},"required":["id","subject","number","code","title","units","prerequisites","requirements","url","sectionCount"],"additionalProperties":false},"Term":{"type":"object","properties":{"code":{"type":"string","description":"SDSU's internal term code, e.g. '2267'."},"label":{"type":"string","description":"Human-readable term name, e.g. 'Fall 2026'."},"startsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"endsAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]},"sectionCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"isDefault":{"type":"boolean","description":"True for the term GET /api/v1/courses/{slug} uses when ?term= is omitted."}},"required":["code","label","startsAt","endsAt","sectionCount","isDefault"],"additionalProperties":false},"Meta":{"type":"object","properties":{"version":{"type":"string"},"freshness":{"type":"object","properties":{"verdict":{"type":"string","enum":["fresh","aging","stale","never-run"]},"lastImportAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},{"type":"null"}]}},"required":["verdict","lastImportAt"],"additionalProperties":false},"docs":{"type":"string","description":"Absolute URL to /docs/api."},"source":{"type":"string"},"disclaimer":{"type":"string"}},"required":["version","freshness","docs","source","disclaimer"],"additionalProperties":false},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["invalid_parameter","not_found","rate_limited","internal_error"]},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}