{"openapi":"3.0.3","info":{"title":"Kisima Champions API","version":"1.0.0","description":"Backend API documentation for Kisima Champions Digital System"},"servers":[{"url":"https://api.karuracc.dev","description":"Production API (dedicated host, routes served at root)"},{"url":"https://staging.karuracc.dev/api","description":"Staging API (behind /api prefix; Traefik strips /api)"},{"url":"http://localhost:3001","description":"Local development server"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT token from login endpoint. Use \"Bearer <jwt_token>\" format."}},"schemas":{"ErrorResponse":{"type":"object","properties":{"error":{"type":"string"},"error_code":{"type":"string"},"message":{"type":"string"}}},"StaffProfile":{"type":"object","properties":{"id":{"type":"string"},"auth_user_id":{"type":"string"},"full_name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"role":{"type":"string","enum":["volunteer","coordinator","admin"]},"assigned_classroom_id":{"type":"string","nullable":true},"is_active":{"type":"boolean"}}},"Child":{"type":"object","properties":{"id":{"type":"string"},"full_name":{"type":"string"},"date_of_birth":{"type":"string","format":"date"},"family_id":{"type":"string"}}},"Family":{"type":"object","properties":{"id":{"type":"string"},"family_name":{"type":"string"},"primary_contact":{"type":"string"},"phone":{"type":"string"}}},"Classroom":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"capacity":{"type":"integer"},"location":{"type":"string","nullable":true}}},"ServiceSession":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":"string","format":"date-time"},"description":{"type":"string","nullable":true}}},"Attendance":{"type":"object","properties":{"id":{"type":"string"},"child_id":{"type":"string"},"session_id":{"type":"string"},"check_in_time":{"type":"string","format":"date-time"},"check_out_time":{"type":"string","format":"date-time","nullable":true}}}}},"tags":[{"name":"Health","description":"Health check endpoint"},{"name":"Auth","description":"Authentication endpoints (login/logout)"},{"name":"Children","description":"Children management endpoints"},{"name":"Families","description":"Family management endpoints"},{"name":"Attendance","description":"Attendance check-in/check-out endpoints"},{"name":"Sessions","description":"Service session management endpoints"},{"name":"Classrooms","description":"Classroom management endpoints"},{"name":"Emergency","description":"Emergency broadcast endpoints"},{"name":"Reports","description":"Report generation endpoints"}],"paths":{"/health":{"get":{"tags":["Health"],"summary":"Health check","description":"Returns service status and environment information. No authentication required.","responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"environment":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}}}}}}},"/auth/login":{"post":{"tags":["Auth"],"summary":"Staff login","description":"Authenticate as a volunteer, coordinator, or admin. Returns JWT token and profile.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"type":"object","properties":{"jwt_token":{"type":"string"},"profile":{"$ref":"#/components/schemas/StaffProfile"}}}}}},"400":{"description":"Missing email or password","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Staff profile not found, inactive, or insufficient role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/logout":{"post":{"tags":["Auth"],"summary":"Staff logout","description":"Sign out the current authenticated user.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Logout successful","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Unauthorized or logout failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/children":{"get":{"tags":["Children"],"summary":"List all children","description":"Returns all children in the system.","responses":{"200":{"description":"All children returned","content":{"application/json":{"schema":{"type":"object","properties":{"children":{"type":"array","items":{"$ref":"#/components/schemas/Child"}}}}}}}}}},"/children/search":{"get":{"tags":["Children"],"summary":"Search children by name","description":"Searches children records using a case-insensitive partial name match.","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string"},"description":"Name or partial name to search for"}],"responses":{"200":{"description":"List of matching children","content":{"application/json":{"schema":{"type":"object","properties":{"children":{"type":"array","items":{"$ref":"#/components/schemas/Child"}}}}}}},"400":{"description":"Missing name query parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/families":{"get":{"tags":["Families"],"summary":"List all families","description":"Returns all families in the system.","responses":{"200":{"description":"All families returned","content":{"application/json":{"schema":{"type":"object","properties":{"families":{"type":"array","items":{"$ref":"#/components/schemas/Family"}}}}}}}}}},"/families/children":{"get":{"tags":["Families"],"summary":"List all children (via families endpoint)","description":"Returns all children in the system.","responses":{"200":{"description":"All children returned","content":{"application/json":{"schema":{"type":"object","properties":{"children":{"type":"array","items":{"$ref":"#/components/schemas/Child"}}}}}}}}}},"/families/volunteers":{"get":{"tags":["Families"],"summary":"List all volunteers","description":"Returns all volunteer staff in the system.","responses":{"200":{"description":"All volunteers returned","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StaffProfile"}}}}}}}}}},"/attendance":{"post":{"tags":["Attendance"],"summary":"Check-in a child","description":"Record check-in time for a child. Requires volunteer role or higher.","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["child_id","session_id"],"properties":{"child_id":{"type":"string"},"session_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Check-in recorded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Attendance"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (volunteer role required)"}}}},"/attendance/{id}/verify-pin":{"post":{"tags":["Attendance"],"summary":"Verify a checkout PIN","description":"Verify the security PIN issued at check-in before allowing checkout. On success the PIN is marked as used. Requires volunteer role or higher.","security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Attendance record ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pin"],"properties":{"pin":{"type":"string","description":"The 4-character PIN issued at check-in"}}}}}},"responses":{"200":{"description":"PIN verified","content":{"application/json":{"schema":{"type":"object","properties":{"verified":{"type":"boolean"},"attendance_id":{"type":"string"}}}}}},"400":{"description":"Missing PIN","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (volunteer role required)"},"404":{"description":"Attendance record not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Child already checked out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"PIN not found, expired, or incorrect","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/attendance/{id}/checkout":{"post":{"tags":["Attendance"],"summary":"Check-out a child","description":"Record check-out time for a child. Requires volunteer role or higher.","security":[{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Attendance record ID"}],"responses":{"200":{"description":"Check-out recorded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Attendance"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (volunteer role required)"}}}},"/attendance/sync":{"post":{"tags":["Attendance"],"summary":"Sync attendance data","description":"Synchronize bulk attendance records. Requires volunteer role or higher.","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Attendance"}}}}},"responses":{"200":{"description":"Attendance synced","content":{"application/json":{"schema":{"type":"object","properties":{"synced":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (volunteer role required)"}}}},"/attendance/all":{"get":{"tags":["Attendance"],"summary":"Get all attendance records","description":"Returns all attendance records in the system.","responses":{"200":{"description":"All attendance records","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Attendance"}}}}}}}},"/sessions":{"get":{"tags":["Sessions"],"summary":"List all service sessions","description":"Returns all service sessions ordered by start time.","responses":{"200":{"description":"All sessions returned","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceSession"}}}}}}}},"/sessions/{id}":{"get":{"tags":["Sessions"],"summary":"Get a specific session","description":"Returns details for a specific service session.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Session ID"}],"responses":{"200":{"description":"Session details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceSession"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/classrooms":{"get":{"tags":["Classrooms"],"summary":"List all classrooms","description":"Returns all classrooms in the system.","responses":{"200":{"description":"All classrooms returned","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Classroom"}}}}}}}},"/classrooms/{id}":{"get":{"tags":["Classrooms"],"summary":"Get a specific classroom","description":"Returns details for a specific classroom.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Classroom ID"}],"responses":{"200":{"description":"Classroom details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Classroom"}}}},"404":{"description":"Classroom not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/emergency-broadcasts":{"get":{"tags":["Emergency"],"summary":"List emergency broadcasts","description":"Returns all emergency broadcasts.","responses":{"200":{"description":"Broadcasts retrieved","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}}}}},"/reports":{"get":{"tags":["Reports"],"summary":"List reports","description":"Returns available reports.","responses":{"200":{"description":"Reports retrieved","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}}}}}}}