API Reference
REST JSON APIs via api-gateway. Base URL: https://{host}/api/v1. Auth: Authorization: Bearer {jwt}.
Conventions
- JSON request/response; dates ISO-8601; money as decimal strings
"150000.00" - Pagination:
?page=0&size=20→{ content, totalElements, totalPages } - Errors:
{ "code": "CLAIM_DUPLICATE", "message": "...", "field": "transactionId" } - Idempotency:
Idempotency-Keyheader on POST approve/payment
Auth
POST /auth/login { email|phone, password } → { accessToken, refreshToken }
POST /auth/refresh { refreshToken }
POST /auth/parent/register { phone, otp, password } -- invite flow
GET /auth/me → user + roles + campuses
Students (student-service)
POST /students -- create student + guardians
GET /students/{id}
GET /students?campusId=&classId=&q=
PUT /students/{id}
POST /students/{id}/enroll
GET /students/{id}/guardians
POST /students/{id}/photo -- multipart → file-service
Fees & payment claims (fee-service)
GET /portal/fee-accounts/{studentId}
GET /portal/invoices?studentId=
POST /portal/payment-claims
GET /portal/payment-claims
GET /portal/payment-claims/{id}
PUT /portal/payment-claims/{id} -- only NEEDS_INFO
DELETE /portal/payment-claims/{id} -- cancel PENDING
GET /admin/payment-claims?status=&campusId=
POST /admin/payment-claims/{id}/start-review
POST /admin/payment-claims/{id}/needs-info { message }
POST /admin/payment-claims/{id}/approve { amount, invoiceIds[] }
POST /admin/payment-claims/{id}/reject { reason }
POST /admin/payments -- direct bursar entry
POST /admin/invoices/generate?termId=&classId=
GET /admin/defaulters?campusId=&termId=
POST /admin/payments/{id}/void { reason }
Health records (health-service)
GET /portal/health/{studentId}
PUT /portal/health/{studentId}
POST /portal/health/{studentId}/confirm
POST /portal/health/{studentId}/documents
GET /admin/health/students?campusId=&status=
GET /admin/health/students/{studentId} # HEALTH_RECORDS_VIEWER only
POST /admin/health/students/{studentId}/nurse-note
POST /admin/health/students/{studentId}/request-reconfirmation
GET /admin/health/audit
See student health records requirements.
Portal documents (notice-service)
GET /portal/children
GET /portal/documents?studentId=&type=
GET /portal/documents/{id}/download
GET /portal/homework?studentId=
POST /admin/documents -- upload metadata + fileId
POST /admin/documents/{id}/publish { audienceType, audienceRef }
Organization
GET /org/campuses
GET /org/terms/current?campusId=
GET /org/classes?campusId=&yearId=
Sample: submit payment claim
POST /api/v1/portal/payment-claims
{
"studentId": "uuid",
"invoiceId": "uuid",
"amount": "380000.00",
"paymentMethod": "MTN_MOMO",
"transactionId": "34829103847",
"payerPhone": "+256770123456",
"paymentDate": "2026-06-10",
"notes": "Term 2 day scholar fees",
"proofFileId": "uuid-or-null"
}
→ 201
{
"id": "uuid",
"status": "PENDING_VERIFICATION",
"submittedAt": "2026-06-10T14:22:00Z"
}
Sample: bursar approve
POST /api/v1/admin/payment-claims/{id}/approve
{
"amount": "380000.00",
"invoiceIds": ["uuid"]
}
→ 200
{
"claimStatus": "APPROVED",
"paymentId": "uuid",
"receiptNumber": "RCP-2026-004821",
"receiptFileId": "uuid"
}
Webhooks (notification-service)
POST /notifications/webhooks/africastalking/delivery
POST /notifications/webhooks/africastalking/inbound -- future
OpenAPI 3 specs will live in each service repo at /src/main/resources/openapi.yaml — generate via springdoc-openapi at build time.