openapi: 3.0.3 info: title: Administrator API - Al Rahma Sunday School version: 1.0.0 description: > REST API for administrator functionality. These endpoints mirror the admin view features but return JSON responses for API consumers. All endpoints require JWT authentication using a Bearer token, unless otherwise noted. Standard response format: ```json { "status": "success|error", "message": "string", "data": {} } ``` servers: - url: https://alrahmaisgl.org/api/v1 security: - BearerAuth: [] tags: - name: Admin Dashboard description: Summary metrics for admins - name: Absence description: Admin absence/time-off self-service - name: Search description: Tokenized search across users, students, parents, staff and emergency contacts - name: Enrollment description: Enrollment/withdrawal data and status updates - name: Profiles description: Aggregate student and parent profiles for administrator views paths: /administrator/dashboard: get: tags: [Admin Dashboard] summary: Get dashboard metrics security: - BearerAuth: [] responses: 200: description: Metrics retrieved content: application/json: schema: $ref: '#/components/schemas/AdminDashboardResponse' 401: description: Unauthorized /administrator/absence: get: tags: [Absence] summary: Get admin absence info and allowed dates security: - BearerAuth: [] responses: 200: description: Absence info content: application/json: schema: $ref: '#/components/schemas/AbsenceInfoResponse' post: tags: [Absence] summary: Submit absence days for current admin security: - BearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SubmitAbsenceRequest' responses: 200: description: Absence saved content: application/json: schema: $ref: '#/components/schemas/SubmitAbsenceResponse' 422: description: Validation error /administrator/search: get: tags: [Search] summary: Tokenized search across entities description: > Splits the query into tokens and matches them across multiple columns; phone-like tokens also match common US formats. security: - BearerAuth: [] parameters: - name: q in: query required: true schema: { type: string, example: "ahmed 4105551234" } responses: 200: description: Search results content: application/json: schema: $ref: '#/components/schemas/SearchResponse' /administrator/enrollment-withdrawal/data: get: tags: [Enrollment] summary: Data for the Enrollment/Withdrawal admin page security: - BearerAuth: [] parameters: - name: schoolYear in: query schema: { type: string, example: "2024-2025" } responses: 200: description: Data payload for UI content: application/json: schema: $ref: '#/components/schemas/EnrollmentWithdrawalDataResponse' /administrator/enrollment-withdrawal/update: post: tags: [Enrollment] summary: Batch update enrollment statuses description: > Updates students' enrollment statuses and computes refunds when applicable. security: - BearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateEnrollmentStatusesRequest' responses: 200: description: Update results content: application/json: schema: $ref: '#/components/schemas/UpdateEnrollmentStatusesResponse' 422: description: Validation error /administrator/students: get: tags: [Profiles] summary: Aggregated student profiles security: - BearerAuth: [] responses: 200: description: Student profiles content: application/json: schema: $ref: '#/components/schemas/StudentProfilesResponse' /administrator/parents: get: tags: [Profiles] summary: Parent profiles with recent invoice balances security: - BearerAuth: [] responses: 200: description: Parent profiles content: application/json: schema: $ref: '#/components/schemas/ParentProfilesResponse' components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: > Include your token in the Authorization header. Example: ``` Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6... ``` schemas: BasicSuccess: type: object properties: status: { type: string, example: "success" } message: { type: string } data: { nullable: true } AdminDashboardResponse: type: object properties: status: { type: string, example: "success" } message: { type: string } data: type: object properties: counts: type: object properties: students: { type: integer, example: 240 } teachers: { type: integer, example: 36 } teacherAssistants: { type: integer, example: 12 } admins: { type: integer, example: 5 } parents: { type: integer, example: 180 } recentActivities: type: array items: type: object properties: login_time: { type: string, format: date-time } email: { type: string, format: email } meta: type: object properties: schoolYear: { type: string, example: "2024-2025" } semester: { type: string, example: "Fall" } AbsenceInfoResponse: type: object properties: status: { type: string, example: "success" } message: { type: string } data: type: object properties: admin_name: { type: string } semester: { type: string } school_year: { type: string } existing: type: array items: type: object properties: id: { type: integer } user_id: { type: integer } date: { type: string, format: date } status: { type: string, enum: [present, absent, late] } reason: { type: string, nullable: true } semester: { type: string } school_year: { type: string } available_dates: type: array items: { type: string, format: date } SubmitAbsenceRequest: type: object required: [dates, reason] properties: dates: type: array items: { type: string, format: date } example: ["2025-09-14", "2025-10-05"] reason_type: type: string example: vacation reason: type: string example: Visiting family SubmitAbsenceResponse: type: object properties: status: { type: string, example: "success" } message: { type: string } data: type: object properties: saved: { type: integer, example: 2 } invalid: type: array items: { type: string, format: date } saved_dates: type: array items: { type: string, format: date } SearchResponse: type: object properties: status: { type: string, example: "success" } message: { type: string } data: type: object properties: users: type: array items: { type: object, additionalProperties: true } students: type: array items: { type: object, additionalProperties: true } parents: type: array items: { type: object, additionalProperties: true } staff: type: array items: { type: object, additionalProperties: true } emergency_contacts: type: array items: { type: object, additionalProperties: true } total: { type: integer } EnrollmentWithdrawalDataResponse: type: object properties: status: { type: string, example: "success" } message: { type: string } data: type: object properties: students: type: array items: type: object additionalProperties: true properties: id: { type: integer } student_id: { type: integer } parent_id: { type: integer } parent_label: { type: string } enrollment_status: { type: string } class_section: { type: string } is_new: { type: integer, example: 0 } new_student: { type: string, example: "No" } registration_date_order: { type: string, example: "2025-09-01" } classes: type: array items: type: object properties: id: { type: integer } class_section_id: { type: integer } class_section_name: { type: string } school_year: { type: string, nullable: true } semester: { type: string, nullable: true } semester: { type: string } school_year: { type: string } schoolYears: type: array items: { type: string } UpdateEnrollmentStatusesRequest: type: object required: [enrollment_status] properties: enrollment_status: type: object additionalProperties: type: string enum: [ "admission under review", "payment pending", "enrolled", "withdraw under review", "refund pending", "withdrawn", "denied", "waitlist" ] example: "101": "payment pending" "102": "enrolled" UpdateEnrollmentStatusesResponse: type: object properties: status: { type: string, example: "success" } message: { type: string } data: type: object properties: errors: type: array items: { type: string } groupsByParentStatus: type: object additionalProperties: type: object additionalProperties: type: array items: type: object properties: student_id: { type: integer } student_name: { type: string } StudentProfilesResponse: type: object properties: status: { type: string, example: "success" } message: { type: string } data: type: object properties: students: type: array items: type: object additionalProperties: true properties: id: { type: integer } firstname: { type: string } lastname: { type: string } parent_firstname: { type: string } parent_lastname: { type: string } parent_email: { type: string, format: email } parent_phone: { type: string } emergency_name: { type: string, nullable: true } emergency_relationship: { type: string, nullable: true } emergency_phone: { type: string, nullable: true } allergies: { type: string, nullable: true } medical_conditions: { type: string, nullable: true } class_section_name: { type: string } ParentProfilesResponse: type: object properties: status: { type: string, example: "success" } message: { type: string } data: type: object properties: parents: type: array items: type: object properties: id: { type: integer } school_id: { type: string } firstname: { type: string } lastname: { type: string } email: { type: string, format: email } cellphone: { type: string } gender: { type: string, nullable: true } created_at: { type: string, format: date-time } school_year: { type: string } paid_amount: { type: number } balance: { type: number }