{"openapi":"3.0.3","info":{"title":"ACLC Ormoc — Centralized API","version":"1.0.0","description":"REST API for managing ACLC Ormoc students, programs, and users. Log in via POST /api/auth/login, then authorize with the returned token (click **Authorize** and paste it). Browsers may also use the session cookie."},"servers":[{"url":"/api","description":"This server"}],"tags":[{"name":"Auth","description":"Login, session, and user accounts"},{"name":"Students","description":"Student records"},{"name":"Programs","description":"Course/program catalog"},{"name":"Subjects","description":"Subject catalog"},{"name":"Sections","description":"Class sections and their schedules"},{"name":"Settings","description":"App settings (delete PIN)"},{"name":"API Keys","description":"Long-lived keys for external apps (session-only management)"},{"name":"Audit","description":"Read-only activity log (admin only)"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"cookieAuth":{"type":"apiKey","in":"cookie","name":"aclc_token"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"An API key created under Settings → API Keys (data endpoints only)."}},"schemas":{"Student":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"student_no":{"type":"string","example":"2024-00001"},"first_name":{"type":"string","example":"Juan"},"middle_name":{"type":"string","nullable":true,"example":"Reyes"},"last_name":{"type":"string","example":"Dela Cruz"},"email":{"type":"string","nullable":true,"example":"juan.delacruz@aclc-ormoc.edu.ph"},"program":{"type":"string","example":"BS Information Technology"},"year_level":{"type":"integer","minimum":1,"maximum":6,"example":3},"section":{"type":"string","nullable":true,"example":"BSIT-3A"},"status":{"type":"string","enum":["enrolled","graduated","dropped","loa","transferred"]},"gender":{"type":"string","nullable":true},"birth_date":{"type":"string","format":"date","nullable":true},"contact_no":{"type":"string","nullable":true},"address":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"StudentInput":{"type":"object","required":["student_no","first_name","last_name","program","year_level"],"properties":{"student_no":{"type":"string","maxLength":20,"example":"2025-01234"},"first_name":{"type":"string","maxLength":100,"example":"Jose"},"middle_name":{"type":"string","maxLength":100},"last_name":{"type":"string","maxLength":100,"example":"Rizal"},"email":{"type":"string","format":"email"},"program":{"type":"string","example":"BS Information Technology"},"year_level":{"type":"integer","minimum":1,"maximum":6,"example":1},"section":{"type":"string","maxLength":50},"status":{"type":"string","enum":["enrolled","graduated","dropped","loa","transferred"],"default":"enrolled"},"gender":{"type":"string","maxLength":20},"birth_date":{"type":"string","format":"date","example":"2005-05-12"},"contact_no":{"type":"string","maxLength":30},"address":{"type":"string"}}},"Program":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","nullable":true,"example":"BSIT"},"name":{"type":"string","example":"BS Information Technology"},"active":{"type":"boolean","example":true},"student_count":{"type":"integer","example":3},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"User":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"full_name":{"type":"string"},"role":{"type":"string","enum":["admin","registrar","instructor","viewer"]},"must_change_password":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}},"Pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}},"Subject":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","example":"IT101"},"title":{"type":"string","example":"Introduction to Computing"},"units":{"type":"number","example":3},"description":{"type":"string","nullable":true},"active":{"type":"boolean"}}},"Section":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"BSIT-3A"},"program":{"type":"string","example":"BS Information Technology"},"year_level":{"type":"integer","example":3},"adviser":{"type":"string","nullable":true},"active":{"type":"boolean"},"student_count":{"type":"integer"},"schedule_count":{"type":"integer"}}},"Schedule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"section_id":{"type":"string","format":"uuid"},"subject_id":{"type":"string","format":"uuid"},"subject_code":{"type":"string"},"subject_title":{"type":"string"},"instructor_id":{"type":"string","format":"uuid","nullable":true},"instructor_name":{"type":"string","nullable":true},"day_of_week":{"type":"string","enum":["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]},"start_time":{"type":"string","example":"08:00"},"end_time":{"type":"string","example":"09:30"},"room":{"type":"string","nullable":true}}}},"responses":{"Unauthorized":{"description":"Not authenticated","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"BadRequest":{"description":"Validation or bad request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"NotFound":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"Conflict":{"description":"Conflict (duplicate or in-use)","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}},"Forbidden":{"description":"Delete PIN required or incorrect","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}}},"security":[{"bearerAuth":[]},{"cookieAuth":[]},{"apiKeyAuth":[]}],"paths":{"/auth/login":{"post":{"tags":["Auth"],"summary":"Log in","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","example":"admin@aclc-ormoc.edu.ph"},"password":{"type":"string","example":"admin123"}}}}}},"responses":{"200":{"description":"Logged in","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/User"},"token":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/auth/logout":{"post":{"tags":["Auth"],"summary":"Log out","security":[],"responses":{"200":{"description":"Logged out"}}}},"/auth/me":{"get":{"tags":["Auth"],"summary":"Current user","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/User"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/auth/change-password":{"post":{"tags":["Auth"],"summary":"Change your password","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["current_password","new_password"],"properties":{"current_password":{"type":"string"},"new_password":{"type":"string","minLength":8}}}}}},"responses":{"200":{"description":"Changed"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/auth/users":{"get":{"tags":["Auth"],"summary":"List users","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Auth"],"summary":"Create a user (admin only; must change password on first login)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","full_name","password"],"properties":{"email":{"type":"string","format":"email"},"full_name":{"type":"string"},"password":{"type":"string","minLength":8},"role":{"type":"string","enum":["admin","registrar","instructor","viewer"],"default":"viewer"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/User"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/auth/users/{id}":{"patch":{"tags":["Auth"],"summary":"Update a user's role or name (admin only)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["admin","registrar","instructor","viewer"]},"full_name":{"type":"string"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/User"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}},"delete":{"tags":["Auth"],"summary":"Delete a user (admin only)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Delete-Pin","in":"header","required":false,"description":"Required only when a delete PIN is configured in Settings.","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/BadRequest"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/auth/users/{id}/reset-password":{"post":{"tags":["Auth"],"summary":"Reset a user's password (admin only) — returns a one-time temp password","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Reset","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"temp_password":{"type":"string"}}}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/students":{"get":{"tags":["Students"],"summary":"List students","parameters":[{"name":"search","in":"query","schema":{"type":"string"},"description":"Name, student no., or email"},{"name":"program","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["enrolled","graduated","dropped","loa","transferred"]}},{"name":"year_level","in":"query","schema":{"type":"integer","minimum":1,"maximum":6}},{"name":"sort","in":"query","schema":{"type":"string"},"description":"e.g. last_name or -created_at"},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Student"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Students"],"summary":"Create a student","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StudentInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Student"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/students/stats":{"get":{"tags":["Students"],"summary":"Aggregate stats","responses":{"200":{"description":"Counts by status, program, and year level"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/students/{id}":{"get":{"tags":["Students"],"summary":"Get a student","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Student"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Students"],"summary":"Update a student","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StudentInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Student"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Students"],"summary":"Partially update a student","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StudentInput"}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Student"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"tags":["Students"],"summary":"Delete a student","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Delete-Pin","in":"header","required":false,"description":"Required only when a delete PIN is configured in Settings.","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/programs":{"get":{"tags":["Programs"],"summary":"List programs","parameters":[{"name":"search","in":"query","schema":{"type":"string"}},{"name":"active","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Program"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"tags":["Programs"],"summary":"Create a program","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"code":{"type":"string"},"active":{"type":"boolean"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Program"}}}}}},"409":{"$ref":"#/components/responses/Conflict"}}}},"/programs/{id}":{"get":{"tags":["Programs"],"summary":"Get a program","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Program"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Programs"],"summary":"Update a program (renaming cascades to students)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"code":{"type":"string"},"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Program"}}}}}},"409":{"$ref":"#/components/responses/Conflict"}}},"patch":{"tags":["Programs"],"summary":"Partially update a program","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"code":{"type":"string"},"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Program"}}}}}}}},"delete":{"tags":["Programs"],"summary":"Delete a program (blocked if in use)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Delete-Pin","in":"header","required":false,"description":"Required only when a delete PIN is configured in Settings.","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/subjects":{"get":{"tags":["Subjects"],"summary":"List subjects","parameters":[{"name":"search","in":"query","schema":{"type":"string"}},{"name":"active","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Subject"}}}}}}}}},"post":{"tags":["Subjects"],"summary":"Create a subject","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["code","title"],"properties":{"code":{"type":"string"},"title":{"type":"string"},"units":{"type":"number","default":3},"description":{"type":"string"},"active":{"type":"boolean"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Subject"}}}}}},"409":{"$ref":"#/components/responses/Conflict"}}}},"/subjects/{id}":{"get":{"tags":["Subjects"],"summary":"Get a subject","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Subjects"],"summary":"Update a subject","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Updated"}}},"patch":{"tags":["Subjects"],"summary":"Partially update a subject","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Updated"}}},"delete":{"tags":["Subjects"],"summary":"Delete a subject (blocked if scheduled)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Delete-Pin","in":"header","required":false,"description":"Required only when a delete PIN is configured in Settings.","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/sections":{"get":{"tags":["Sections"],"summary":"List sections (with student & schedule counts)","parameters":[{"name":"search","in":"query","schema":{"type":"string"}},{"name":"program","in":"query","schema":{"type":"string"}},{"name":"active","in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Section"}}}}}}}}},"post":{"tags":["Sections"],"summary":"Create a section","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","program","year_level"],"properties":{"name":{"type":"string"},"program":{"type":"string"},"year_level":{"type":"integer"},"adviser":{"type":"string"},"active":{"type":"boolean"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Section"}}}}}},"409":{"$ref":"#/components/responses/Conflict"}}}},"/sections/{id}":{"get":{"tags":["Sections"],"summary":"Get a section","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"},"404":{"$ref":"#/components/responses/NotFound"}}},"put":{"tags":["Sections"],"summary":"Update a section (renaming cascades to students)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Updated"}}},"patch":{"tags":["Sections"],"summary":"Partially update a section","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Updated"}}},"delete":{"tags":["Sections"],"summary":"Delete a section (blocked if it has students; schedules cascade)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Delete-Pin","in":"header","required":false,"description":"Required only when a delete PIN is configured in Settings.","schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/sections/{id}/schedules":{"get":{"tags":["Sections"],"summary":"List a section's schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Schedule"}}}}}}}}},"post":{"tags":["Sections"],"summary":"Add a class to a section's schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subject_id","day_of_week","start_time","end_time"],"properties":{"subject_id":{"type":"string","format":"uuid"},"instructor_id":{"type":"string","format":"uuid"},"day_of_week":{"type":"string","enum":["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]},"start_time":{"type":"string","example":"08:00"},"end_time":{"type":"string","example":"09:30"},"room":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Schedule"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/schedules/{id}":{"put":{"tags":["Sections"],"summary":"Update a schedule entry","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Updated"}}},"patch":{"tags":["Sections"],"summary":"Partially update a schedule entry","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Updated"}}},"delete":{"tags":["Sections"],"summary":"Remove a schedule entry","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/settings/delete-pin":{"get":{"tags":["Settings"],"summary":"Delete PIN status","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"enabled":{"type":"boolean"}}}}}}}}}},"put":{"tags":["Settings"],"summary":"Set or change the delete PIN","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["new_pin"],"properties":{"new_pin":{"type":"string","pattern":"^\\d{4,8}$"},"current_pin":{"type":"string"}}}}}},"responses":{"200":{"description":"Saved"},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/settings/delete-pin/disable":{"post":{"tags":["Settings"],"summary":"Disable the delete PIN","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["current_pin"],"properties":{"current_pin":{"type":"string"}}}}}},"responses":{"200":{"description":"Disabled"},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/keys":{"get":{"tags":["API Keys"],"summary":"List API keys (masked)","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"OK"},"403":{"$ref":"#/components/responses/Forbidden"}}},"post":{"tags":["API Keys"],"summary":"Create an API key (raw key returned once)","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Student portal"}}}}}},"responses":{"201":{"description":"Created — response includes the one-time `key`"},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/keys/{id}":{"delete":{"tags":["API Keys"],"summary":"Revoke an API key","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Revoked"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/audit":{"get":{"tags":["Audit"],"summary":"List audit-log entries (admin only)","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"parameters":[{"name":"entity","in":"query","schema":{"type":"string","enum":["student","program","subject","section","schedule","user","api_key","setting","auth"]}},{"name":"action","in":"query","schema":{"type":"string","enum":["create","update","delete","login","password_change","password_reset"]}},{"name":"search","in":"query","schema":{"type":"string"},"description":"Matches actor or record label"},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":30,"maximum":100}}],"responses":{"200":{"description":"OK"},"403":{"$ref":"#/components/responses/Forbidden"}}}}}}