Staff SDK Reference¶
Auto-generated by
scripts/generate-sdk-docs.pyon 2026-04-27. Do not edit manually — regenerate withpython3 scripts/generate-sdk-docs.py(ornpm run syncfromui-clients/sdk/to also refresh the underlying OpenAPI specs).
import { attendanceStaff, canteenStaff, academicReport, invoice, school, wallet, audit } from '@smartsapp/sdk/staff';
Student Attendance (attendanceStaff)¶
Student Pickup Persons¶
updatePickupPersonAssignment()¶
Update authorisation settings for a student-pickup-person assignment
PUT /api/attendance/students/{studentId}/pickup-persons/{pickupPersonId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
studentId |
string (uuid) |
path | Yes | |
pickupPersonId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateStudentPickupPersonRequest
| Field | Type | Required | Description |
|---|---|---|---|
authorisationMode |
"GENERAL" | "DAY_SPECIFIC" |
Yes | Authorisation mode |
permissionType |
"DROPOFF_ONLY" | "PICKUP_ONLY" | "BOTH" |
Yes | Permission type |
monday |
boolean |
No | Authorised on Monday |
tuesday |
boolean |
No | Authorised on Tuesday |
wednesday |
boolean |
No | Authorised on Wednesday |
thursday |
boolean |
No | Authorised on Thursday |
friday |
boolean |
No | Authorised on Friday |
Response: StudentPickupPersonResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Assignment ID | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonId |
string (uuid) |
ID of the pickup person | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Full name of the pickup person | "John Doe" |
pickupPersonPhone |
string |
Phone number of the pickup person | "+233501234567" |
relationship |
string |
Relationship to the student | "Uncle" |
authorisationMode |
"GENERAL" | "DAY_SPECIFIC" |
How pickup authorisation is verified: PIN, QR_CODE, FACE_ID | "GENERAL" |
permissionType |
"DROPOFF_ONLY" | "PICKUP_ONLY" | "BOTH" |
Permission scope: ALWAYS, SCHEDULED | "DROPOFF_ONLY" |
monday |
boolean |
Whether pickup is allowed on Mondays | |
tuesday |
boolean |
Whether pickup is allowed on Tuesdays | |
wednesday |
boolean |
Whether pickup is allowed on Wednesdays | |
thursday |
boolean |
Whether pickup is allowed on Thursdays | |
friday |
boolean |
Whether pickup is allowed on Fridays | |
createdAt |
string (date-time) |
When the assignment was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the assignment was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zUpdateStudentPickupPersonRequest } from '@smartsapp/sdk/staff';
import type { UpdateStudentPickupPersonRequest, StudentPickupPersonResponse } from '@smartsapp/sdk/staff';
const input: UpdateStudentPickupPersonRequest = {
authorisationMode: "GENERAL",
permissionType: "DROPOFF_ONLY",
monday: "...",
tuesday: "..."
};
const parsed = zUpdateStudentPickupPersonRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: studentPickupPerson, error } = await attendanceStaff.updatePickupPersonAssignment({
body: input,
path: { studentId: "...", pickupPersonId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// studentPickupPerson is typed as StudentPickupPersonResponse
removePickupPersonAssignment()¶
Remove a pickup person from a student
DELETE /api/attendance/students/{studentId}/pickup-persons/{pickupPersonId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
studentId |
string (uuid) |
path | Yes | |
pickupPersonId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (200)
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
const { data, error } = await attendanceStaff.removePickupPersonAssignment({
path: { studentId: "...", pickupPersonId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listStudentPickupPersons()¶
List all pickup persons assigned to a student
GET /api/attendance/students/{studentId}/pickup-persons
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
studentId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: StudentPickupPersonResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Assignment ID | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonId |
string (uuid) |
ID of the pickup person | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Full name of the pickup person | "John Doe" |
pickupPersonPhone |
string |
Phone number of the pickup person | "+233501234567" |
relationship |
string |
Relationship to the student | "Uncle" |
authorisationMode |
"GENERAL" | "DAY_SPECIFIC" |
How pickup authorisation is verified: PIN, QR_CODE, FACE_ID | "GENERAL" |
permissionType |
"DROPOFF_ONLY" | "PICKUP_ONLY" | "BOTH" |
Permission scope: ALWAYS, SCHEDULED | "DROPOFF_ONLY" |
monday |
boolean |
Whether pickup is allowed on Mondays | |
tuesday |
boolean |
Whether pickup is allowed on Tuesdays | |
wednesday |
boolean |
Whether pickup is allowed on Wednesdays | |
thursday |
boolean |
Whether pickup is allowed on Thursdays | |
friday |
boolean |
Whether pickup is allowed on Fridays | |
createdAt |
string (date-time) |
When the assignment was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the assignment was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
const { data, error } = await attendanceStaff.listStudentPickupPersons({
path: { studentId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as StudentPickupPersonResponse[]
assignPickupPerson()¶
Assign a pickup person to a student
POST /api/attendance/students/{studentId}/pickup-persons
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
studentId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: AssignPickupPersonRequest
| Field | Type | Required | Description |
|---|---|---|---|
pickupPersonId |
string (uuid) |
Yes | ID of the pickup person to assign |
authorisationMode |
"GENERAL" | "DAY_SPECIFIC" |
Yes | Authorisation mode |
permissionType |
"DROPOFF_ONLY" | "PICKUP_ONLY" | "BOTH" |
Yes | Permission type |
monday |
boolean |
No | Authorised on Monday (only for DAY_SPECIFIC) |
tuesday |
boolean |
No | Authorised on Tuesday (only for DAY_SPECIFIC) |
wednesday |
boolean |
No | Authorised on Wednesday (only for DAY_SPECIFIC) |
thursday |
boolean |
No | Authorised on Thursday (only for DAY_SPECIFIC) |
friday |
boolean |
No | Authorised on Friday (only for DAY_SPECIFIC) |
Response: StudentPickupPersonResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Assignment ID | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonId |
string (uuid) |
ID of the pickup person | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Full name of the pickup person | "John Doe" |
pickupPersonPhone |
string |
Phone number of the pickup person | "+233501234567" |
relationship |
string |
Relationship to the student | "Uncle" |
authorisationMode |
"GENERAL" | "DAY_SPECIFIC" |
How pickup authorisation is verified: PIN, QR_CODE, FACE_ID | "GENERAL" |
permissionType |
"DROPOFF_ONLY" | "PICKUP_ONLY" | "BOTH" |
Permission scope: ALWAYS, SCHEDULED | "DROPOFF_ONLY" |
monday |
boolean |
Whether pickup is allowed on Mondays | |
tuesday |
boolean |
Whether pickup is allowed on Tuesdays | |
wednesday |
boolean |
Whether pickup is allowed on Wednesdays | |
thursday |
boolean |
Whether pickup is allowed on Thursdays | |
friday |
boolean |
Whether pickup is allowed on Fridays | |
createdAt |
string (date-time) |
When the assignment was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the assignment was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zAssignPickupPersonRequest } from '@smartsapp/sdk/staff';
import type { AssignPickupPersonRequest, StudentPickupPersonResponse } from '@smartsapp/sdk/staff';
const input: AssignPickupPersonRequest = {
pickupPersonId: "550e8400-...",
authorisationMode: "GENERAL",
permissionType: "BOTH",
monday: "..."
};
const parsed = zAssignPickupPersonRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: studentPickupPerson, error } = await attendanceStaff.assignPickupPerson({
body: input,
path: { studentId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// studentPickupPerson is typed as StudentPickupPersonResponse
Settings¶
getAttendanceSettings()¶
Get attendance settings for a school
GET /api/attendance/settings
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
schoolId |
string (uuid) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AttendanceSettingResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance setting ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school these settings belong to | "550e8400-e29b-41d4-a716-446655440000" |
parentSelfCheckInEnabled |
boolean |
Whether parents can self-check-in their children | |
attendanceMode |
"SCAN" | "MANUAL" | "BOTH" |
Attendance tracking mode: MANUAL, AUTOMATIC | "SCAN" |
selfCheckInStartTime |
string |
Earliest time parents may self-check-in | "07:00:00" |
selfCheckInEndTime |
string |
Latest time parents may self-check-in | "09:00:00" |
createdAt |
string (date-time) |
When the settings were created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the settings were last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
import type { AttendanceSettingResponse } from '@smartsapp/sdk/staff';
const { data: attendanceSetting, error } = await attendanceStaff.getAttendanceSettings({
query: { schoolId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// attendanceSetting is typed as AttendanceSettingResponse
updateAttendanceSettings()¶
Update attendance settings for a school
PUT /api/attendance/settings
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
schoolId |
string (uuid) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateAttendanceSettingRequest
| Field | Type | Required | Description |
|---|---|---|---|
parentSelfCheckInEnabled |
boolean |
No | Enable parent self-check-in via the Parent App |
attendanceMode |
"SCAN" | "MANUAL" | "BOTH" |
Yes | Attendance mode |
selfCheckInStartTime |
string |
No | Start time for parent self-check-in window |
selfCheckInEndTime |
string |
No | End time for parent self-check-in window |
Response: AttendanceSettingResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance setting ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school these settings belong to | "550e8400-e29b-41d4-a716-446655440000" |
parentSelfCheckInEnabled |
boolean |
Whether parents can self-check-in their children | |
attendanceMode |
"SCAN" | "MANUAL" | "BOTH" |
Attendance tracking mode: MANUAL, AUTOMATIC | "SCAN" |
selfCheckInStartTime |
string |
Earliest time parents may self-check-in | "07:00:00" |
selfCheckInEndTime |
string |
Latest time parents may self-check-in | "09:00:00" |
createdAt |
string (date-time) |
When the settings were created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the settings were last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zUpdateAttendanceSettingRequest } from '@smartsapp/sdk/staff';
import type { UpdateAttendanceSettingRequest, AttendanceSettingResponse } from '@smartsapp/sdk/staff';
const input: UpdateAttendanceSettingRequest = {
parentSelfCheckInEnabled: "...",
attendanceMode: "BOTH",
selfCheckInStartTime: "07:00",
selfCheckInEndTime: "09:00"
};
const parsed = zUpdateAttendanceSettingRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: attendanceSetting, error } = await attendanceStaff.updateAttendanceSettings({
body: input,
query: { schoolId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// attendanceSetting is typed as AttendanceSettingResponse
Section Schedules¶
getSectionSchedule()¶
Get the attendance schedule for a section
GET /api/attendance/section-schedules/{sectionId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
sectionId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: SectionScheduleResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Section schedule ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section | "550e8400-e29b-41d4-a716-446655440000" |
startTime |
string |
Scheduled start time for the section | "07:30:00" |
endTime |
string |
Scheduled end time for the section | "15:00:00" |
lateThresholdMinutes |
integer (int32) |
Minutes after start time before a student is marked late | 15 |
pickupLateThresholdMinutes |
integer (int32) |
Minutes after end time before a pickup is considered late | 30 |
earlyDepartureThresholdMinutes |
integer (int32) |
Minutes before end time that counts as early departure | 60 |
createdAt |
string (date-time) |
When the schedule was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the schedule was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
import type { SectionScheduleResponse } from '@smartsapp/sdk/staff';
const { data: sectionSchedule, error } = await attendanceStaff.getSectionSchedule({
path: { sectionId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// sectionSchedule is typed as SectionScheduleResponse
upsertSectionSchedule()¶
Create or update the attendance schedule for a section
PUT /api/attendance/section-schedules/{sectionId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
sectionId |
string (uuid) |
path | Yes | |
schoolId |
string (uuid) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateSectionScheduleRequest
| Field | Type | Required | Description |
|---|---|---|---|
startTime |
string |
Yes | Section start time |
endTime |
string |
Yes | Section end time |
lateThresholdMinutes |
integer (int32) |
Yes | Minutes after start time to classify as late |
pickupLateThresholdMinutes |
integer (int32) |
Yes | Minutes after end time to classify pickup as late |
earlyDepartureThresholdMinutes |
integer (int32) |
Yes | Minutes before end time to classify as early departure |
Response: SectionScheduleResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Section schedule ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section | "550e8400-e29b-41d4-a716-446655440000" |
startTime |
string |
Scheduled start time for the section | "07:30:00" |
endTime |
string |
Scheduled end time for the section | "15:00:00" |
lateThresholdMinutes |
integer (int32) |
Minutes after start time before a student is marked late | 15 |
pickupLateThresholdMinutes |
integer (int32) |
Minutes after end time before a pickup is considered late | 30 |
earlyDepartureThresholdMinutes |
integer (int32) |
Minutes before end time that counts as early departure | 60 |
createdAt |
string (date-time) |
When the schedule was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the schedule was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zUpdateSectionScheduleRequest } from '@smartsapp/sdk/staff';
import type { UpdateSectionScheduleRequest, SectionScheduleResponse } from '@smartsapp/sdk/staff';
const input: UpdateSectionScheduleRequest = {
startTime: "08:00",
endTime: "15:30",
lateThresholdMinutes: 15,
pickupLateThresholdMinutes: 30
};
const parsed = zUpdateSectionScheduleRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: sectionSchedule, error } = await attendanceStaff.upsertSectionSchedule({
body: input,
path: { sectionId: "..." },
query: { schoolId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// sectionSchedule is typed as SectionScheduleResponse
listSectionSchedules()¶
List all section schedules for a school
GET /api/attendance/section-schedules
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
schoolId |
string (uuid) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: SectionScheduleResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Section schedule ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section | "550e8400-e29b-41d4-a716-446655440000" |
startTime |
string |
Scheduled start time for the section | "07:30:00" |
endTime |
string |
Scheduled end time for the section | "15:00:00" |
lateThresholdMinutes |
integer (int32) |
Minutes after start time before a student is marked late | 15 |
pickupLateThresholdMinutes |
integer (int32) |
Minutes after end time before a pickup is considered late | 30 |
earlyDepartureThresholdMinutes |
integer (int32) |
Minutes before end time that counts as early departure | 60 |
createdAt |
string (date-time) |
When the schedule was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the schedule was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
const { data, error } = await attendanceStaff.listSectionSchedules({
query: { schoolId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as SectionScheduleResponse[]
Records¶
markStudentExcused()¶
Mark a student as excused for a date
PUT /api/attendance/records/mark-excused
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: MarkExcusedRequest
| Field | Type | Required | Description |
|---|---|---|---|
studentId |
string (uuid) |
Yes | ID of the student |
date |
string (date) |
Yes | Date to mark as excused |
reason |
string |
No | Reason for the absence |
Response: AttendanceRecordResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance record ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the classroom | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date of the attendance record | "2026-01-15" |
checkInTime |
string (date-time) |
When the student was checked in | "2026-01-15T07:45:00Z" |
checkInPerformedById |
string (uuid) |
ID of the user who performed the check-in | "550e8400-e29b-41d4-a716-446655440000" |
checkInPerformedByName |
string |
Name of the user who performed the check-in | "Jane Smith" |
checkInMethod |
"SCAN" | "MANUAL" |
Method used for check-in: MANUAL, QR_CODE, NFC | "SCAN" |
checkOutTime |
string (date-time) |
When the student was checked out | "2026-01-15T15:30:00Z" |
checkOutPerformedById |
string (uuid) |
ID of the user who performed the check-out | "550e8400-e29b-41d4-a716-446655440000" |
checkOutPerformedByName |
string |
Name of the user who performed the check-out | "Jane Smith" |
checkOutMethod |
"SCAN" | "MANUAL" |
Method used for check-out: MANUAL, QR_CODE, NFC | "SCAN" |
dropoffPersonId |
string (uuid) |
ID of the person who dropped off the student | "550e8400-e29b-41d4-a716-446655440000" |
dropoffPersonName |
string |
Name of the person who dropped off the student | "John Doe" |
pickupPersonId |
string (uuid) |
ID of the person who picked up the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Name of the person who picked up the student | "John Doe" |
arrivalClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's arrival: ON_TIME, LATE | "EARLY" |
departureClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's departure: ON_TIME, EARLY | "EARLY" |
status |
"PRESENT" | "ABSENT" | "LATE" | "EXCUSED" |
Attendance status: PRESENT, ABSENT, EXCUSED | "PRESENT" |
excuseReason |
string |
Reason for excused absence | "Doctor appointment" |
isUnaccompanied |
boolean |
Whether the student arrived or departed without an accompanying adult | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zMarkExcusedRequest } from '@smartsapp/sdk/staff';
import type { MarkExcusedRequest, AttendanceRecordResponse } from '@smartsapp/sdk/staff';
const input: MarkExcusedRequest = {
studentId: "550e8400-...",
date: "...",
reason: "Medical appointment"
};
const parsed = zMarkExcusedRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: attendanceRecord, error } = await attendanceStaff.markStudentExcused({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// attendanceRecord is typed as AttendanceRecordResponse
markStudentAbsent()¶
Mark a student as absent for a date
PUT /api/attendance/records/mark-absent
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: MarkAbsentRequest
| Field | Type | Required | Description |
|---|---|---|---|
studentId |
string (uuid) |
Yes | ID of the student |
date |
string (date) |
Yes | Date to mark as absent |
Response: AttendanceRecordResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance record ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the classroom | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date of the attendance record | "2026-01-15" |
checkInTime |
string (date-time) |
When the student was checked in | "2026-01-15T07:45:00Z" |
checkInPerformedById |
string (uuid) |
ID of the user who performed the check-in | "550e8400-e29b-41d4-a716-446655440000" |
checkInPerformedByName |
string |
Name of the user who performed the check-in | "Jane Smith" |
checkInMethod |
"SCAN" | "MANUAL" |
Method used for check-in: MANUAL, QR_CODE, NFC | "SCAN" |
checkOutTime |
string (date-time) |
When the student was checked out | "2026-01-15T15:30:00Z" |
checkOutPerformedById |
string (uuid) |
ID of the user who performed the check-out | "550e8400-e29b-41d4-a716-446655440000" |
checkOutPerformedByName |
string |
Name of the user who performed the check-out | "Jane Smith" |
checkOutMethod |
"SCAN" | "MANUAL" |
Method used for check-out: MANUAL, QR_CODE, NFC | "SCAN" |
dropoffPersonId |
string (uuid) |
ID of the person who dropped off the student | "550e8400-e29b-41d4-a716-446655440000" |
dropoffPersonName |
string |
Name of the person who dropped off the student | "John Doe" |
pickupPersonId |
string (uuid) |
ID of the person who picked up the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Name of the person who picked up the student | "John Doe" |
arrivalClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's arrival: ON_TIME, LATE | "EARLY" |
departureClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's departure: ON_TIME, EARLY | "EARLY" |
status |
"PRESENT" | "ABSENT" | "LATE" | "EXCUSED" |
Attendance status: PRESENT, ABSENT, EXCUSED | "PRESENT" |
excuseReason |
string |
Reason for excused absence | "Doctor appointment" |
isUnaccompanied |
boolean |
Whether the student arrived or departed without an accompanying adult | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zMarkAbsentRequest } from '@smartsapp/sdk/staff';
import type { MarkAbsentRequest, AttendanceRecordResponse } from '@smartsapp/sdk/staff';
const input: MarkAbsentRequest = {
studentId: "550e8400-...",
date: "..."
};
const parsed = zMarkAbsentRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: attendanceRecord, error } = await attendanceStaff.markStudentAbsent({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// attendanceRecord is typed as AttendanceRecordResponse
massCheckInStudents()¶
Mass check-in all students in a class
POST /api/attendance/records/mass-check-in
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: MassCheckInRequest
| Field | Type | Required | Description |
|---|---|---|---|
classroomId |
string (uuid) |
Yes | ID of the classroom |
performedById |
string (uuid) |
Yes | ID of the admin performing the mass check-in |
performedByName |
string |
Yes | Name of the admin performing the mass check-in |
Response: AttendanceRecordResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance record ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the classroom | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date of the attendance record | "2026-01-15" |
checkInTime |
string (date-time) |
When the student was checked in | "2026-01-15T07:45:00Z" |
checkInPerformedById |
string (uuid) |
ID of the user who performed the check-in | "550e8400-e29b-41d4-a716-446655440000" |
checkInPerformedByName |
string |
Name of the user who performed the check-in | "Jane Smith" |
checkInMethod |
"SCAN" | "MANUAL" |
Method used for check-in: MANUAL, QR_CODE, NFC | "SCAN" |
checkOutTime |
string (date-time) |
When the student was checked out | "2026-01-15T15:30:00Z" |
checkOutPerformedById |
string (uuid) |
ID of the user who performed the check-out | "550e8400-e29b-41d4-a716-446655440000" |
checkOutPerformedByName |
string |
Name of the user who performed the check-out | "Jane Smith" |
checkOutMethod |
"SCAN" | "MANUAL" |
Method used for check-out: MANUAL, QR_CODE, NFC | "SCAN" |
dropoffPersonId |
string (uuid) |
ID of the person who dropped off the student | "550e8400-e29b-41d4-a716-446655440000" |
dropoffPersonName |
string |
Name of the person who dropped off the student | "John Doe" |
pickupPersonId |
string (uuid) |
ID of the person who picked up the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Name of the person who picked up the student | "John Doe" |
arrivalClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's arrival: ON_TIME, LATE | "EARLY" |
departureClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's departure: ON_TIME, EARLY | "EARLY" |
status |
"PRESENT" | "ABSENT" | "LATE" | "EXCUSED" |
Attendance status: PRESENT, ABSENT, EXCUSED | "PRESENT" |
excuseReason |
string |
Reason for excused absence | "Doctor appointment" |
isUnaccompanied |
boolean |
Whether the student arrived or departed without an accompanying adult | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zMassCheckInRequest } from '@smartsapp/sdk/staff';
import type { MassCheckInRequest } from '@smartsapp/sdk/staff';
const input: MassCheckInRequest = {
classroomId: "550e8400-...",
performedById: "550e8400-...",
performedByName: "..."
};
const parsed = zMassCheckInRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data, error } = await attendanceStaff.massCheckInStudents({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as AttendanceRecordResponse[]
checkOutStudent()¶
Check out a student
POST /api/attendance/records/check-out
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CheckOutRequest
| Field | Type | Required | Description |
|---|---|---|---|
studentId |
string (uuid) |
Yes | ID of the student |
performedById |
string (uuid) |
Yes | ID of the person performing the check-out |
performedByName |
string |
Yes | Name of the person performing the check-out |
method |
"SCAN" | "MANUAL" |
Yes | Check-out method |
pickupPersonId |
string (uuid) |
No | ID of the pickup person collecting the student |
pickupPersonName |
string |
No | Name of the pickup person (used when person is not in the system) |
Response: AttendanceRecordResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance record ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the classroom | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date of the attendance record | "2026-01-15" |
checkInTime |
string (date-time) |
When the student was checked in | "2026-01-15T07:45:00Z" |
checkInPerformedById |
string (uuid) |
ID of the user who performed the check-in | "550e8400-e29b-41d4-a716-446655440000" |
checkInPerformedByName |
string |
Name of the user who performed the check-in | "Jane Smith" |
checkInMethod |
"SCAN" | "MANUAL" |
Method used for check-in: MANUAL, QR_CODE, NFC | "SCAN" |
checkOutTime |
string (date-time) |
When the student was checked out | "2026-01-15T15:30:00Z" |
checkOutPerformedById |
string (uuid) |
ID of the user who performed the check-out | "550e8400-e29b-41d4-a716-446655440000" |
checkOutPerformedByName |
string |
Name of the user who performed the check-out | "Jane Smith" |
checkOutMethod |
"SCAN" | "MANUAL" |
Method used for check-out: MANUAL, QR_CODE, NFC | "SCAN" |
dropoffPersonId |
string (uuid) |
ID of the person who dropped off the student | "550e8400-e29b-41d4-a716-446655440000" |
dropoffPersonName |
string |
Name of the person who dropped off the student | "John Doe" |
pickupPersonId |
string (uuid) |
ID of the person who picked up the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Name of the person who picked up the student | "John Doe" |
arrivalClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's arrival: ON_TIME, LATE | "EARLY" |
departureClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's departure: ON_TIME, EARLY | "EARLY" |
status |
"PRESENT" | "ABSENT" | "LATE" | "EXCUSED" |
Attendance status: PRESENT, ABSENT, EXCUSED | "PRESENT" |
excuseReason |
string |
Reason for excused absence | "Doctor appointment" |
isUnaccompanied |
boolean |
Whether the student arrived or departed without an accompanying adult | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zCheckOutRequest } from '@smartsapp/sdk/staff';
import type { CheckOutRequest, AttendanceRecordResponse } from '@smartsapp/sdk/staff';
const input: CheckOutRequest = {
studentId: "550e8400-...",
performedById: "550e8400-...",
performedByName: "...",
method: "SCAN"
};
const parsed = zCheckOutRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: attendanceRecord, error } = await attendanceStaff.checkOutStudent({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// attendanceRecord is typed as AttendanceRecordResponse
checkInStudent()¶
Check in a student
POST /api/attendance/records/check-in
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CheckInRequest
| Field | Type | Required | Description |
|---|---|---|---|
studentId |
string (uuid) |
Yes | ID of the student |
performedById |
string (uuid) |
Yes | ID of the person performing the check-in (staff or parent) |
performedByName |
string |
Yes | Name of the person performing the check-in |
method |
"SCAN" | "MANUAL" |
Yes | Check-in method |
dropoffPersonId |
string (uuid) |
No | ID of the pickup/dropoff person accompanying the student (nullable for unaccompanied) |
dropoffPersonName |
string |
No | Name of the dropoff person (used when person is not in the system) |
Response: AttendanceRecordResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance record ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the classroom | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date of the attendance record | "2026-01-15" |
checkInTime |
string (date-time) |
When the student was checked in | "2026-01-15T07:45:00Z" |
checkInPerformedById |
string (uuid) |
ID of the user who performed the check-in | "550e8400-e29b-41d4-a716-446655440000" |
checkInPerformedByName |
string |
Name of the user who performed the check-in | "Jane Smith" |
checkInMethod |
"SCAN" | "MANUAL" |
Method used for check-in: MANUAL, QR_CODE, NFC | "SCAN" |
checkOutTime |
string (date-time) |
When the student was checked out | "2026-01-15T15:30:00Z" |
checkOutPerformedById |
string (uuid) |
ID of the user who performed the check-out | "550e8400-e29b-41d4-a716-446655440000" |
checkOutPerformedByName |
string |
Name of the user who performed the check-out | "Jane Smith" |
checkOutMethod |
"SCAN" | "MANUAL" |
Method used for check-out: MANUAL, QR_CODE, NFC | "SCAN" |
dropoffPersonId |
string (uuid) |
ID of the person who dropped off the student | "550e8400-e29b-41d4-a716-446655440000" |
dropoffPersonName |
string |
Name of the person who dropped off the student | "John Doe" |
pickupPersonId |
string (uuid) |
ID of the person who picked up the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Name of the person who picked up the student | "John Doe" |
arrivalClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's arrival: ON_TIME, LATE | "EARLY" |
departureClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's departure: ON_TIME, EARLY | "EARLY" |
status |
"PRESENT" | "ABSENT" | "LATE" | "EXCUSED" |
Attendance status: PRESENT, ABSENT, EXCUSED | "PRESENT" |
excuseReason |
string |
Reason for excused absence | "Doctor appointment" |
isUnaccompanied |
boolean |
Whether the student arrived or departed without an accompanying adult | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zCheckInRequest } from '@smartsapp/sdk/staff';
import type { CheckInRequest, AttendanceRecordResponse } from '@smartsapp/sdk/staff';
const input: CheckInRequest = {
studentId: "550e8400-e29b-41d4-a716-446655440000",
performedById: "550e8400-e29b-41d4-a716-446655440001",
performedByName: "Mrs. Adjei",
method: "MANUAL"
};
const parsed = zCheckInRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: attendanceRecord, error } = await attendanceStaff.checkInStudent({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// attendanceRecord is typed as AttendanceRecordResponse
getAttendanceRecord()¶
Get an attendance record by ID
GET /api/attendance/records/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AttendanceRecordResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance record ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the classroom | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date of the attendance record | "2026-01-15" |
checkInTime |
string (date-time) |
When the student was checked in | "2026-01-15T07:45:00Z" |
checkInPerformedById |
string (uuid) |
ID of the user who performed the check-in | "550e8400-e29b-41d4-a716-446655440000" |
checkInPerformedByName |
string |
Name of the user who performed the check-in | "Jane Smith" |
checkInMethod |
"SCAN" | "MANUAL" |
Method used for check-in: MANUAL, QR_CODE, NFC | "SCAN" |
checkOutTime |
string (date-time) |
When the student was checked out | "2026-01-15T15:30:00Z" |
checkOutPerformedById |
string (uuid) |
ID of the user who performed the check-out | "550e8400-e29b-41d4-a716-446655440000" |
checkOutPerformedByName |
string |
Name of the user who performed the check-out | "Jane Smith" |
checkOutMethod |
"SCAN" | "MANUAL" |
Method used for check-out: MANUAL, QR_CODE, NFC | "SCAN" |
dropoffPersonId |
string (uuid) |
ID of the person who dropped off the student | "550e8400-e29b-41d4-a716-446655440000" |
dropoffPersonName |
string |
Name of the person who dropped off the student | "John Doe" |
pickupPersonId |
string (uuid) |
ID of the person who picked up the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Name of the person who picked up the student | "John Doe" |
arrivalClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's arrival: ON_TIME, LATE | "EARLY" |
departureClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's departure: ON_TIME, EARLY | "EARLY" |
status |
"PRESENT" | "ABSENT" | "LATE" | "EXCUSED" |
Attendance status: PRESENT, ABSENT, EXCUSED | "PRESENT" |
excuseReason |
string |
Reason for excused absence | "Doctor appointment" |
isUnaccompanied |
boolean |
Whether the student arrived or departed without an accompanying adult | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
import type { AttendanceRecordResponse } from '@smartsapp/sdk/staff';
const { data: attendanceRecord, error } = await attendanceStaff.getAttendanceRecord({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// attendanceRecord is typed as AttendanceRecordResponse
listAttendanceByClass()¶
List attendance records for a class on a date
GET /api/attendance/records/by-class
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
classroomId |
string (uuid) |
query | Yes | |
date |
string (date) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AttendanceRecordResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Attendance record ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the classroom | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date of the attendance record | "2026-01-15" |
checkInTime |
string (date-time) |
When the student was checked in | "2026-01-15T07:45:00Z" |
checkInPerformedById |
string (uuid) |
ID of the user who performed the check-in | "550e8400-e29b-41d4-a716-446655440000" |
checkInPerformedByName |
string |
Name of the user who performed the check-in | "Jane Smith" |
checkInMethod |
"SCAN" | "MANUAL" |
Method used for check-in: MANUAL, QR_CODE, NFC | "SCAN" |
checkOutTime |
string (date-time) |
When the student was checked out | "2026-01-15T15:30:00Z" |
checkOutPerformedById |
string (uuid) |
ID of the user who performed the check-out | "550e8400-e29b-41d4-a716-446655440000" |
checkOutPerformedByName |
string |
Name of the user who performed the check-out | "Jane Smith" |
checkOutMethod |
"SCAN" | "MANUAL" |
Method used for check-out: MANUAL, QR_CODE, NFC | "SCAN" |
dropoffPersonId |
string (uuid) |
ID of the person who dropped off the student | "550e8400-e29b-41d4-a716-446655440000" |
dropoffPersonName |
string |
Name of the person who dropped off the student | "John Doe" |
pickupPersonId |
string (uuid) |
ID of the person who picked up the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Name of the person who picked up the student | "John Doe" |
arrivalClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's arrival: ON_TIME, LATE | "EARLY" |
departureClassification |
"EARLY" | "ON_TIME" | "LATE" |
Classification of the student's departure: ON_TIME, EARLY | "EARLY" |
status |
"PRESENT" | "ABSENT" | "LATE" | "EXCUSED" |
Attendance status: PRESENT, ABSENT, EXCUSED | "PRESENT" |
excuseReason |
string |
Reason for excused absence | "Doctor appointment" |
isUnaccompanied |
boolean |
Whether the student arrived or departed without an accompanying adult | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
const { data, error } = await attendanceStaff.listAttendanceByClass({
query: { classroomId: "...", date: "2026-01-01" }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as AttendanceRecordResponse[]
Pickup Persons¶
getPickupPerson()¶
Get a pickup person by ID
GET /api/attendance/pickup-persons/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PickupPersonResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Pickup person ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
fullName |
string |
Full name of the pickup person | "John Doe" |
phoneNumber |
string |
Phone number of the pickup person | "+233501234567" |
relationship |
string |
Relationship to the student | "Uncle" |
photoUrl |
string |
URL of the pickup person's photo | "https://storage.example.com/photos/abc.jpg" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
import type { PickupPersonResponse } from '@smartsapp/sdk/staff';
const { data: pickupPerson, error } = await attendanceStaff.getPickupPerson({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// pickupPerson is typed as PickupPersonResponse
updatePickupPerson()¶
Update a pickup person
PUT /api/attendance/pickup-persons/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdatePickupPersonRequest
| Field | Type | Required | Description |
|---|---|---|---|
fullName |
string |
No | Full name of the pickup person |
relationship |
string |
No | Relationship to the student |
photoUrl |
string |
No | URL of the person's photo |
Response: PickupPersonResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Pickup person ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
fullName |
string |
Full name of the pickup person | "John Doe" |
phoneNumber |
string |
Phone number of the pickup person | "+233501234567" |
relationship |
string |
Relationship to the student | "Uncle" |
photoUrl |
string |
URL of the pickup person's photo | "https://storage.example.com/photos/abc.jpg" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zUpdatePickupPersonRequest } from '@smartsapp/sdk/staff';
import type { UpdatePickupPersonRequest, PickupPersonResponse } from '@smartsapp/sdk/staff';
const input: UpdatePickupPersonRequest = {
fullName: "...",
relationship: "...",
photoUrl: "..."
};
const parsed = zUpdatePickupPersonRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: pickupPerson, error } = await attendanceStaff.updatePickupPerson({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// pickupPerson is typed as PickupPersonResponse
listPickupPersons()¶
List pickup persons for a school
GET /api/attendance/pickup-persons
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
schoolId |
string (uuid) |
query | Yes | |
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponsePickupPersonResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
PickupPersonResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
PickupPersonResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Pickup person ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
fullName |
string |
Full name of the pickup person | "John Doe" |
phoneNumber |
string |
Phone number of the pickup person | "+233501234567" |
relationship |
string |
Relationship to the student | "Uncle" |
photoUrl |
string |
URL of the pickup person's photo | "https://storage.example.com/photos/abc.jpg" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
import type { PagedResponsePickupPersonResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await attendanceStaff.listPickupPersons({
query: { schoolId: "...", page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const pickupPersons = result.content; // PickupPersonResponse[]
const { page, totalPages, totalElements, last } = result;
createPickupPerson()¶
Create or find a pickup person (deduplicated by phone number)
POST /api/attendance/pickup-persons
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
schoolId |
string (uuid) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreatePickupPersonRequest
| Field | Type | Required | Description |
|---|---|---|---|
fullName |
string |
Yes | Full name of the pickup person |
phoneNumber |
string |
Yes | Phone number (unique identifier) |
relationship |
string |
Yes | Relationship to the student |
photoUrl |
string |
No | URL of the person's photo |
Response: PickupPersonResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Pickup person ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
fullName |
string |
Full name of the pickup person | "John Doe" |
phoneNumber |
string |
Phone number of the pickup person | "+233501234567" |
relationship |
string |
Relationship to the student | "Uncle" |
photoUrl |
string |
URL of the pickup person's photo | "https://storage.example.com/photos/abc.jpg" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff, zCreatePickupPersonRequest } from '@smartsapp/sdk/staff';
import type { CreatePickupPersonRequest, PickupPersonResponse } from '@smartsapp/sdk/staff';
const input: CreatePickupPersonRequest = {
fullName: "Ama Mensah",
phoneNumber: "+233241234567",
relationship: "Grandmother",
photoUrl: "..."
};
const parsed = zCreatePickupPersonRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: pickupPerson, error } = await attendanceStaff.createPickupPerson({
body: input,
query: { schoolId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// pickupPerson is typed as PickupPersonResponse
reverseLookupPickupPerson()¶
Reverse lookup: list all students assigned to a pickup person
GET /api/attendance/pickup-persons/{id}/students
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: StudentPickupPersonResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Assignment ID | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string (uuid) |
ID of the student | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonId |
string (uuid) |
ID of the pickup person | "550e8400-e29b-41d4-a716-446655440000" |
pickupPersonName |
string |
Full name of the pickup person | "John Doe" |
pickupPersonPhone |
string |
Phone number of the pickup person | "+233501234567" |
relationship |
string |
Relationship to the student | "Uncle" |
authorisationMode |
"GENERAL" | "DAY_SPECIFIC" |
How pickup authorisation is verified: PIN, QR_CODE, FACE_ID | "GENERAL" |
permissionType |
"DROPOFF_ONLY" | "PICKUP_ONLY" | "BOTH" |
Permission scope: ALWAYS, SCHEDULED | "DROPOFF_ONLY" |
monday |
boolean |
Whether pickup is allowed on Mondays | |
tuesday |
boolean |
Whether pickup is allowed on Tuesdays | |
wednesday |
boolean |
Whether pickup is allowed on Wednesdays | |
thursday |
boolean |
Whether pickup is allowed on Thursdays | |
friday |
boolean |
Whether pickup is allowed on Fridays | |
createdAt |
string (date-time) |
When the assignment was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the assignment was last updated | "2026-01-15T10:30:00Z" |
Example:
import { attendanceStaff } from '@smartsapp/sdk/staff';
const { data, error } = await attendanceStaff.reverseLookupPickupPerson({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as StudentPickupPersonResponse[]
Canteen (canteenStaff)¶
Users¶
getCanteenUser()¶
Get a canteen user by ID
GET /api/canteen/users/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: CanteenUserResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Canteen user ID | "550e8400-e29b-41d4-a716-446655440000" |
userId |
string (uuid) |
ID of the platform user account | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the assigned catering service | "550e8400-e29b-41d4-a716-446655440000" |
role |
"CANTEEN_ADMIN" | "CANTEEN_MANAGER" | "POS_OPERATOR" |
Role within the canteen: ADMIN, OPERATOR, VIEWER | "CANTEEN_ADMIN" |
active |
boolean |
Whether the canteen user account is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { CanteenUserResponse } from '@smartsapp/sdk/staff';
const { data: canteenUser, error } = await canteenStaff.getCanteenUser({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// canteenUser is typed as CanteenUserResponse
updateCanteenUser()¶
Update a canteen user
PUT /api/canteen/users/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateCanteenUserRequest
| Field | Type | Required | Description |
|---|---|---|---|
cateringServiceId |
string (uuid) |
No | ID of the catering service |
role |
"CANTEEN_ADMIN" | "CANTEEN_MANAGER" | "POS_OPERATOR" |
No | Role of the canteen user |
active |
boolean |
No | Whether the canteen user is active |
Response: CanteenUserResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Canteen user ID | "550e8400-e29b-41d4-a716-446655440000" |
userId |
string (uuid) |
ID of the platform user account | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the assigned catering service | "550e8400-e29b-41d4-a716-446655440000" |
role |
"CANTEEN_ADMIN" | "CANTEEN_MANAGER" | "POS_OPERATOR" |
Role within the canteen: ADMIN, OPERATOR, VIEWER | "CANTEEN_ADMIN" |
active |
boolean |
Whether the canteen user account is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateCanteenUserRequest } from '@smartsapp/sdk/staff';
import type { UpdateCanteenUserRequest, CanteenUserResponse } from '@smartsapp/sdk/staff';
const input: UpdateCanteenUserRequest = {
cateringServiceId: "550e8400-e29b-41d4-a716-446655440001",
role: "MANAGER",
active: true
};
const parsed = zUpdateCanteenUserRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: canteenUser, error } = await canteenStaff.updateCanteenUser({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// canteenUser is typed as CanteenUserResponse
deleteCanteenUser()¶
Delete a canteen user
DELETE /api/canteen/users/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteCanteenUser({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listCanteenUsers()¶
List canteen users with pagination
GET /api/canteen/users
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseCanteenUserResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
CanteenUserResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
CanteenUserResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Canteen user ID | "550e8400-e29b-41d4-a716-446655440000" |
userId |
string (uuid) |
ID of the platform user account | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the assigned catering service | "550e8400-e29b-41d4-a716-446655440000" |
role |
"CANTEEN_ADMIN" | "CANTEEN_MANAGER" | "POS_OPERATOR" |
Role within the canteen: ADMIN, OPERATOR, VIEWER | "CANTEEN_ADMIN" |
active |
boolean |
Whether the canteen user account is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { PagedResponseCanteenUserResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await canteenStaff.listCanteenUsers({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const canteenUsers = result.content; // CanteenUserResponse[]
const { page, totalPages, totalElements, last } = result;
createCanteenUser()¶
Create a new canteen user
POST /api/canteen/users
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateCanteenUserRequest
| Field | Type | Required | Description |
|---|---|---|---|
userId |
string (uuid) |
Yes | ID of the user |
cateringServiceId |
string (uuid) |
Yes | ID of the catering service |
role |
"CANTEEN_ADMIN" | "CANTEEN_MANAGER" | "POS_OPERATOR" |
Yes | Role of the canteen user |
Response: CanteenUserResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Canteen user ID | "550e8400-e29b-41d4-a716-446655440000" |
userId |
string (uuid) |
ID of the platform user account | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the assigned catering service | "550e8400-e29b-41d4-a716-446655440000" |
role |
"CANTEEN_ADMIN" | "CANTEEN_MANAGER" | "POS_OPERATOR" |
Role within the canteen: ADMIN, OPERATOR, VIEWER | "CANTEEN_ADMIN" |
active |
boolean |
Whether the canteen user account is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateCanteenUserRequest } from '@smartsapp/sdk/staff';
import type { CreateCanteenUserRequest, CanteenUserResponse } from '@smartsapp/sdk/staff';
const input: CreateCanteenUserRequest = {
userId: "550e8400-e29b-41d4-a716-446655440000",
cateringServiceId: "550e8400-e29b-41d4-a716-446655440001",
role: "MANAGER"
};
const parsed = zCreateCanteenUserRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: canteenUser, error } = await canteenStaff.createCanteenUser({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// canteenUser is typed as CanteenUserResponse
Settings¶
updateCanteenSettings()¶
Update canteen settings
PUT /api/canteen/settings/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateCanteenSettingRequest
| Field | Type | Required | Description |
|---|---|---|---|
redemptionMode |
"AUTO_REDEEM" | "AUTO_REDEEM_PRESENT" | "SCAN_TO_REDEEM" |
Yes | Redemption mode for the canteen |
Response: CanteenSettingResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Setting ID | "550e8400-e29b-41d4-a716-446655440000" |
redemptionMode |
"AUTO_REDEEM" | "AUTO_REDEEM_PRESENT" | "SCAN_TO_REDEEM" |
How orders are redeemed: ORDER_LEVEL, ITEM_LEVEL | "AUTO_REDEEM" |
createdAt |
string (date-time) |
When the settings were created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the settings were last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateCanteenSettingRequest } from '@smartsapp/sdk/staff';
import type { UpdateCanteenSettingRequest, CanteenSettingResponse } from '@smartsapp/sdk/staff';
const input: UpdateCanteenSettingRequest = {
redemptionMode: "QR_CODE"
};
const parsed = zUpdateCanteenSettingRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: canteenSetting, error } = await canteenStaff.updateCanteenSettings({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// canteenSetting is typed as CanteenSettingResponse
getCanteenSettings()¶
Get canteen settings
GET /api/canteen/settings
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: CanteenSettingResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Setting ID | "550e8400-e29b-41d4-a716-446655440000" |
redemptionMode |
"AUTO_REDEEM" | "AUTO_REDEEM_PRESENT" | "SCAN_TO_REDEEM" |
How orders are redeemed: ORDER_LEVEL, ITEM_LEVEL | "AUTO_REDEEM" |
createdAt |
string (date-time) |
When the settings were created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the settings were last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { CanteenSettingResponse } from '@smartsapp/sdk/staff';
const { data: canteenSetting, error } = await canteenStaff.getCanteenSettings();
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// canteenSetting is typed as CanteenSettingResponse
Orders¶
redeemOrder()¶
Redeem an entire order (mark all items as served)
PUT /api/canteen/orders/{id}/redeem
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: OrderResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order ID | "550e8400-e29b-41d4-a716-446655440000" |
orderNumber |
string |
Human-readable order number | "ORD-20260115-001" |
studentId |
string (uuid) |
ID of the student the order is for | "550e8400-e29b-41d4-a716-446655440000" |
mealTicketId |
string (uuid) |
ID of the meal ticket used for payment | "550e8400-e29b-41d4-a716-446655440000" |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Type of order: WALK_IN or PRE_ORDER | "TICKET" |
totalPrice |
number |
Total price of the order | 25.0 |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
How the order was paid: CASH, MEAL_TICKET, MOBILE_MONEY | "SIKA_ID" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status: DRAFT, CONFIRMED, SERVED, CANCELLED | "DRAFT" |
scheduledDate |
string (date) |
Date the order is scheduled for | "2026-01-15" |
createdBy |
string (uuid) |
ID of the user who created the order | "550e8400-e29b-41d4-a716-446655440000" |
redeemedAt |
string (date-time) |
When the order was redeemed/served | "2026-01-15T12:30:00Z" |
cancelledAt |
string (date-time) |
When the order was cancelled | "2026-01-15T10:00:00Z" |
cancelledBy |
string (uuid) |
ID of the user who cancelled the order | "550e8400-e29b-41d4-a716-446655440000" |
createdAt |
string (date-time) |
When the order was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the order was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { OrderResponse } from '@smartsapp/sdk/staff';
const { data: order, error } = await canteenStaff.redeemOrder({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// order is typed as OrderResponse
serveOrderItem()¶
Mark a single item in an order as served
PUT /api/canteen/orders/{id}/items/{orderItemId}/serve
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
orderItemId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: OrderDetailResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order ID | "550e8400-e29b-41d4-a716-446655440000" |
orderNumber |
string |
Human-readable order number | "ORD-20260115-001" |
student |
StudentSummary |
Student summary for order context | |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Type of order: WALK_IN or PRE_ORDER | "TICKET" |
totalPrice |
number |
Total price of the order | 25.0 |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
How the order was paid: CASH, MEAL_TICKET, MOBILE_MONEY | "SIKA_ID" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status: DRAFT, CONFIRMED, SERVED, CANCELLED | "DRAFT" |
scheduledDate |
string (date) |
Date the order is scheduled for | "2026-01-15" |
items |
OrderItemDetailResponse[] |
Items included in this order | |
redeemedAt |
string (date-time) |
When the order was redeemed/served | "2026-01-15T12:30:00Z" |
cancelledAt |
string (date-time) |
When the order was cancelled | "2026-01-15T10:00:00Z" |
cancelledBy |
string (uuid) |
ID of the user who cancelled the order | "550e8400-e29b-41d4-a716-446655440000" |
createdAt |
string (date-time) |
When the order was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the order was last updated | "2026-01-15T10:30:00Z" |
StudentSummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Student ID | "550e8400-e29b-41d4-a716-446655440000" |
firstName |
string |
Student's first name | "Kofi" |
lastName |
string |
Student's last name | "Asante" |
className |
string |
Name of the student's class | "Grade 3A" |
OrderItemDetailResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order item ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the ordered item | "550e8400-e29b-41d4-a716-446655440000" |
itemName |
string |
Name of the ordered item | "Jollof Rice" |
variantId |
string (uuid) |
ID of the selected variant | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the selected variant | "Large" |
menuSectionId |
string (uuid) |
ID of the menu section this item was ordered from | "550e8400-e29b-41d4-a716-446655440000" |
sectionName |
string |
Name of the menu section | "Lunch Main Course" |
quantity |
integer (int32) |
Quantity ordered | 2 |
unitPrice |
number |
Unit price at time of order | 12.5 |
currency |
string |
Currency code | "GHS" |
served |
boolean |
Whether this item has been served | |
servedAt |
string (date-time) |
When the item was served | "2026-01-15T12:30:00Z" |
servedBy |
integer (int64) |
ID of the user who served the item | 42 |
servedByName |
string |
Name of the user who served the item | "Abena Mensah" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { OrderDetailResponse } from '@smartsapp/sdk/staff';
const { data: orderDetail, error } = await canteenStaff.serveOrderItem({
path: { id: "...", orderItemId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// orderDetail is typed as OrderDetailResponse
cancelOrder()¶
Cancel an order
PUT /api/canteen/orders/{id}/cancel
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: OrderResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order ID | "550e8400-e29b-41d4-a716-446655440000" |
orderNumber |
string |
Human-readable order number | "ORD-20260115-001" |
studentId |
string (uuid) |
ID of the student the order is for | "550e8400-e29b-41d4-a716-446655440000" |
mealTicketId |
string (uuid) |
ID of the meal ticket used for payment | "550e8400-e29b-41d4-a716-446655440000" |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Type of order: WALK_IN or PRE_ORDER | "TICKET" |
totalPrice |
number |
Total price of the order | 25.0 |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
How the order was paid: CASH, MEAL_TICKET, MOBILE_MONEY | "SIKA_ID" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status: DRAFT, CONFIRMED, SERVED, CANCELLED | "DRAFT" |
scheduledDate |
string (date) |
Date the order is scheduled for | "2026-01-15" |
createdBy |
string (uuid) |
ID of the user who created the order | "550e8400-e29b-41d4-a716-446655440000" |
redeemedAt |
string (date-time) |
When the order was redeemed/served | "2026-01-15T12:30:00Z" |
cancelledAt |
string (date-time) |
When the order was cancelled | "2026-01-15T10:00:00Z" |
cancelledBy |
string (uuid) |
ID of the user who cancelled the order | "550e8400-e29b-41d4-a716-446655440000" |
createdAt |
string (date-time) |
When the order was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the order was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { OrderResponse } from '@smartsapp/sdk/staff';
const { data: order, error } = await canteenStaff.cancelOrder({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// order is typed as OrderResponse
listOrders()¶
List orders with items and student info
GET /api/canteen/orders
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
startDate |
string (date) |
query | No | |
endDate |
string (date) |
query | No | |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
query | No | |
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseOrderDetailResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
OrderDetailResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
OrderDetailResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order ID | "550e8400-e29b-41d4-a716-446655440000" |
orderNumber |
string |
Human-readable order number | "ORD-20260115-001" |
student |
StudentSummary |
Student summary for order context | |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Type of order: WALK_IN or PRE_ORDER | "TICKET" |
totalPrice |
number |
Total price of the order | 25.0 |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
How the order was paid: CASH, MEAL_TICKET, MOBILE_MONEY | "SIKA_ID" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status: DRAFT, CONFIRMED, SERVED, CANCELLED | "DRAFT" |
scheduledDate |
string (date) |
Date the order is scheduled for | "2026-01-15" |
items |
OrderItemDetailResponse[] |
Items included in this order | |
redeemedAt |
string (date-time) |
When the order was redeemed/served | "2026-01-15T12:30:00Z" |
cancelledAt |
string (date-time) |
When the order was cancelled | "2026-01-15T10:00:00Z" |
cancelledBy |
string (uuid) |
ID of the user who cancelled the order | "550e8400-e29b-41d4-a716-446655440000" |
createdAt |
string (date-time) |
When the order was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the order was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { PagedResponseOrderDetailResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await canteenStaff.listOrders({
query: { startDate: "2026-01-01", endDate: "2026-01-01", status: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const orderDetails = result.content; // OrderDetailResponse[]
const { page, totalPages, totalElements, last } = result;
createOrder()¶
Create a new order
POST /api/canteen/orders
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateOrderRequest
| Field | Type | Required | Description |
|---|---|---|---|
studentId |
string (uuid) |
Yes | ID of the student placing the order |
mealTicketId |
string (uuid) |
No | ID of the meal ticket used for the order |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Yes | Type of order |
totalPrice |
number |
Yes | Total price of the order |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
Yes | Payment mode for the order |
scheduledDate |
string (date) |
Yes | Scheduled date for the order |
createdBy |
string (uuid) |
Yes | ID of the user creating the order |
items |
CreateOrderItemRequest[] |
Yes | List of order items |
CreateOrderItemRequest fields:
| Field | Type | Required | Description |
|---|---|---|---|
itemId |
string (uuid) |
Yes | ID of the item |
variantId |
string (uuid) |
No | ID of the item variant |
quantity |
integer (int32) |
No | Quantity of the item |
unitPrice |
number |
Yes | Unit price of the item |
Response: OrderResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order ID | "550e8400-e29b-41d4-a716-446655440000" |
orderNumber |
string |
Human-readable order number | "ORD-20260115-001" |
studentId |
string (uuid) |
ID of the student the order is for | "550e8400-e29b-41d4-a716-446655440000" |
mealTicketId |
string (uuid) |
ID of the meal ticket used for payment | "550e8400-e29b-41d4-a716-446655440000" |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Type of order: WALK_IN or PRE_ORDER | "TICKET" |
totalPrice |
number |
Total price of the order | 25.0 |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
How the order was paid: CASH, MEAL_TICKET, MOBILE_MONEY | "SIKA_ID" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status: DRAFT, CONFIRMED, SERVED, CANCELLED | "DRAFT" |
scheduledDate |
string (date) |
Date the order is scheduled for | "2026-01-15" |
createdBy |
string (uuid) |
ID of the user who created the order | "550e8400-e29b-41d4-a716-446655440000" |
redeemedAt |
string (date-time) |
When the order was redeemed/served | "2026-01-15T12:30:00Z" |
cancelledAt |
string (date-time) |
When the order was cancelled | "2026-01-15T10:00:00Z" |
cancelledBy |
string (uuid) |
ID of the user who cancelled the order | "550e8400-e29b-41d4-a716-446655440000" |
createdAt |
string (date-time) |
When the order was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the order was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateOrderRequest } from '@smartsapp/sdk/staff';
import type { CreateOrderRequest, OrderResponse } from '@smartsapp/sdk/staff';
const input: CreateOrderRequest = {
studentId: "550e8400-e29b-41d4-a716-446655440000",
mealTicketId: "550e8400-e29b-41d4-a716-446655440001",
orderType: "SCHEDULED",
totalPrice: 25.0
};
const parsed = zCreateOrderRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: order, error } = await canteenStaff.createOrder({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// order is typed as OrderResponse
getOrder()¶
Get an order with items and student info
GET /api/canteen/orders/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: OrderDetailResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order ID | "550e8400-e29b-41d4-a716-446655440000" |
orderNumber |
string |
Human-readable order number | "ORD-20260115-001" |
student |
StudentSummary |
Student summary for order context | |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Type of order: WALK_IN or PRE_ORDER | "TICKET" |
totalPrice |
number |
Total price of the order | 25.0 |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
How the order was paid: CASH, MEAL_TICKET, MOBILE_MONEY | "SIKA_ID" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status: DRAFT, CONFIRMED, SERVED, CANCELLED | "DRAFT" |
scheduledDate |
string (date) |
Date the order is scheduled for | "2026-01-15" |
items |
OrderItemDetailResponse[] |
Items included in this order | |
redeemedAt |
string (date-time) |
When the order was redeemed/served | "2026-01-15T12:30:00Z" |
cancelledAt |
string (date-time) |
When the order was cancelled | "2026-01-15T10:00:00Z" |
cancelledBy |
string (uuid) |
ID of the user who cancelled the order | "550e8400-e29b-41d4-a716-446655440000" |
createdAt |
string (date-time) |
When the order was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the order was last updated | "2026-01-15T10:30:00Z" |
StudentSummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Student ID | "550e8400-e29b-41d4-a716-446655440000" |
firstName |
string |
Student's first name | "Kofi" |
lastName |
string |
Student's last name | "Asante" |
className |
string |
Name of the student's class | "Grade 3A" |
OrderItemDetailResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order item ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the ordered item | "550e8400-e29b-41d4-a716-446655440000" |
itemName |
string |
Name of the ordered item | "Jollof Rice" |
variantId |
string (uuid) |
ID of the selected variant | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the selected variant | "Large" |
menuSectionId |
string (uuid) |
ID of the menu section this item was ordered from | "550e8400-e29b-41d4-a716-446655440000" |
sectionName |
string |
Name of the menu section | "Lunch Main Course" |
quantity |
integer (int32) |
Quantity ordered | 2 |
unitPrice |
number |
Unit price at time of order | 12.5 |
currency |
string |
Currency code | "GHS" |
served |
boolean |
Whether this item has been served | |
servedAt |
string (date-time) |
When the item was served | "2026-01-15T12:30:00Z" |
servedBy |
integer (int64) |
ID of the user who served the item | 42 |
servedByName |
string |
Name of the user who served the item | "Abena Mensah" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { OrderDetailResponse } from '@smartsapp/sdk/staff';
const { data: orderDetail, error } = await canteenStaff.getOrder({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// orderDetail is typed as OrderDetailResponse
Menu Sections¶
updateMenuSection()¶
Update a menu section
PUT /api/canteen/menus/{menuId}/sections/{sectionId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
sectionId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateMenuSectionRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
No | Name of the section |
servingStartTime |
string |
No | Start of serving window |
servingEndTime |
string |
No | End of serving window |
selectionMode |
"SINGLE" | "MULTIPLE" |
No | Selection mode: SINGLE (one item per order) or MULTIPLE (many items per order) |
themeColor |
string |
No | Hex color code for theming |
Response: MenuSectionResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu section ID | "550e8400-e29b-41d4-a716-446655440000" |
menuId |
string (uuid) |
ID of the parent menu | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the section | "Lunch Main Course" |
servingStartTime |
string |
Start of serving window | "12:00:00" |
servingEndTime |
string |
End of serving window | "13:30:00" |
selectionMode |
"SINGLE" | "MULTIPLE" |
How students select items: SINGLE or MULTIPLE | "SINGLE" |
themeColor |
string |
Hex colour code for theming | "#FF5733" |
createdAt |
string (date-time) |
When the section was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the section was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateMenuSectionRequest } from '@smartsapp/sdk/staff';
import type { UpdateMenuSectionRequest, MenuSectionResponse } from '@smartsapp/sdk/staff';
const input: UpdateMenuSectionRequest = {
name: "Lunch",
servingStartTime: "12:00:00",
servingEndTime: "13:30:00",
selectionMode: "SINGLE"
};
const parsed = zUpdateMenuSectionRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: menuSection, error } = await canteenStaff.updateMenuSection({
body: input,
path: { menuId: "...", sectionId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menuSection is typed as MenuSectionResponse
deleteMenuSection()¶
Delete a menu section
DELETE /api/canteen/menus/{menuId}/sections/{sectionId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
sectionId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteMenuSection({
path: { menuId: "...", sectionId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listMenuSections()¶
List sections for a menu
GET /api/canteen/menus/{menuId}/sections
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: MenuSectionResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu section ID | "550e8400-e29b-41d4-a716-446655440000" |
menuId |
string (uuid) |
ID of the parent menu | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the section | "Lunch Main Course" |
servingStartTime |
string |
Start of serving window | "12:00:00" |
servingEndTime |
string |
End of serving window | "13:30:00" |
selectionMode |
"SINGLE" | "MULTIPLE" |
How students select items: SINGLE or MULTIPLE | "SINGLE" |
themeColor |
string |
Hex colour code for theming | "#FF5733" |
createdAt |
string (date-time) |
When the section was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the section was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.listMenuSections({
path: { menuId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as MenuSectionResponse[]
createMenuSection()¶
Add a section to a menu
POST /api/canteen/menus/{menuId}/sections
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateMenuSectionRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Name of the section |
servingStartTime |
string |
No | Start of serving window |
servingEndTime |
string |
No | End of serving window |
selectionMode |
"SINGLE" | "MULTIPLE" |
Yes | Selection mode: SINGLE (one item per order) or MULTIPLE (many items per order) |
themeColor |
string |
No | Hex color code for theming |
Response: MenuSectionResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu section ID | "550e8400-e29b-41d4-a716-446655440000" |
menuId |
string (uuid) |
ID of the parent menu | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the section | "Lunch Main Course" |
servingStartTime |
string |
Start of serving window | "12:00:00" |
servingEndTime |
string |
End of serving window | "13:30:00" |
selectionMode |
"SINGLE" | "MULTIPLE" |
How students select items: SINGLE or MULTIPLE | "SINGLE" |
themeColor |
string |
Hex colour code for theming | "#FF5733" |
createdAt |
string (date-time) |
When the section was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the section was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateMenuSectionRequest } from '@smartsapp/sdk/staff';
import type { CreateMenuSectionRequest, MenuSectionResponse } from '@smartsapp/sdk/staff';
const input: CreateMenuSectionRequest = {
name: "Lunch",
servingStartTime: "12:00:00",
servingEndTime: "13:30:00",
selectionMode: "SINGLE"
};
const parsed = zCreateMenuSectionRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: menuSection, error } = await canteenStaff.createMenuSection({
body: input,
path: { menuId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menuSection is typed as MenuSectionResponse
Menus¶
getMenu()¶
Get a menu by ID
GET /api/canteen/menus/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: MenuResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the menu | "Term 1 Lunch Menu" |
description |
string |
Description of the menu | "Daily lunch options for Term 1" |
purpose |
"INFO_ONLY" | "PARENTS_CAN_ORDER" |
Purpose of the menu: LUNCH, BREAKFAST, SNACK | "INFO_ONLY" |
paymentType |
"ORDER_AND_PAY_ITEM_PRICING" | "ORDER_ONLY_NO_PAYMENT" | "ORDER_AND_PAY_TICKET_PRICING" |
Payment type: PREPAID, POSTPAID | "ORDER_AND_PAY_ITEM_PRICING" |
startDate |
string (date) |
First day the menu is active | "2026-01-06" |
endDate |
string (date) |
Last day the menu is active | "2026-03-28" |
orderingDeadlineType |
"DAILY" | "WEEKLY" |
Deadline type for ordering: DAILY, WEEKLY, NONE | "DAILY" |
dailyCutoffTime |
string |
Daily cutoff time for pre-orders | "08:00:00" |
dailyCutoffDays |
integer (int32) |
Number of days before the meal day the daily cutoff applies | 2 |
weeklyCutoffDay |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY" |
Weekly cutoff day for pre-orders | "MONDAY" |
weeklyCutoffTime |
string |
Weekly cutoff time of day | "23:59:00" |
orderCancellationHours |
integer (int32) |
Hours before scheduled date that cancellation is allowed | 24 |
published |
boolean |
Whether the menu is published and visible to parents | |
audience |
"ALL" | "SPECIFIC" |
Who can see this menu: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetSectionIds |
string (uuid)[] |
Target section IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom/grade IDs when audience is SPECIFIC | |
excludedStudentIds |
string (uuid)[] |
Individual student IDs excluded from this menu | |
visibilityDays |
integer (int32) |
How many days ahead of today parents can see this menu in the Parent App | 30 |
updatedBy |
string (uuid) |
ID of the user who last updated this menu | "550e8400-e29b-41d4-a716-446655440000" |
updatedByName |
string |
Name of the user who last updated this menu | "Abena Mensah" |
createdAt |
string (date-time) |
When the menu was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the menu was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { MenuResponse } from '@smartsapp/sdk/staff';
const { data: menu, error } = await canteenStaff.getMenu({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menu is typed as MenuResponse
updateMenu()¶
Update a menu
PUT /api/canteen/menus/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateMenuRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Name of the menu |
description |
string |
No | Description of the menu |
purpose |
"INFO_ONLY" | "PARENTS_CAN_ORDER" |
Yes | Purpose of the menu: PARENTS_CAN_ORDER (ordering enabled) or INFO_ONLY (view only) |
paymentType |
"ORDER_AND_PAY_ITEM_PRICING" | "ORDER_ONLY_NO_PAYMENT" | "ORDER_AND_PAY_TICKET_PRICING" |
No | Payment type for the menu. Only applies when purpose is PARENTS_CAN_ORDER. |
startDate |
string (date) |
Yes | Start date of the menu |
endDate |
string (date) |
Yes | End date of the menu |
orderingDeadlineType |
"DAILY" | "WEEKLY" |
No | Type of ordering deadline. Only applies when purpose is PARENTS_CAN_ORDER. |
dailyCutoffTime |
string |
No | Daily cutoff time for orders. Only applies when orderingDeadlineType is DAILY. |
dailyCutoffDays |
integer (int32) |
No | Number of days before the meal day the daily cutoff applies. Only applies when orderingDeadlineType is DAILY. Null or 0 means same-day cutoff. |
weeklyCutoffDay |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY" |
No | Weekly cutoff day for orders. Only applies when orderingDeadlineType is WEEKLY. |
weeklyCutoffTime |
string |
No | Weekly cutoff time of day. Only applies when orderingDeadlineType is WEEKLY. |
orderCancellationHours |
integer (int32) |
No | Hours before which an order can be cancelled. Only applies when purpose is PARENTS_CAN_ORDER. |
audience |
"ALL" | "SPECIFIC" |
Yes | Who can see this menu: ALL or SPECIFIC |
targetCampusIds |
string (uuid)[] |
No | Target campus IDs when audience is SPECIFIC |
targetSectionIds |
string (uuid)[] |
No | Target section IDs when audience is SPECIFIC |
targetClassroomIds |
string (uuid)[] |
No | Target classroom/grade IDs when audience is SPECIFIC |
excludedStudentIds |
string (uuid)[] |
No | Individual student IDs to exclude from this menu |
visibilityDays |
integer (int32) |
Yes | How many days ahead of today parents can see this menu in the Parent App. Range 1–30. |
Response: MenuResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the menu | "Term 1 Lunch Menu" |
description |
string |
Description of the menu | "Daily lunch options for Term 1" |
purpose |
"INFO_ONLY" | "PARENTS_CAN_ORDER" |
Purpose of the menu: LUNCH, BREAKFAST, SNACK | "INFO_ONLY" |
paymentType |
"ORDER_AND_PAY_ITEM_PRICING" | "ORDER_ONLY_NO_PAYMENT" | "ORDER_AND_PAY_TICKET_PRICING" |
Payment type: PREPAID, POSTPAID | "ORDER_AND_PAY_ITEM_PRICING" |
startDate |
string (date) |
First day the menu is active | "2026-01-06" |
endDate |
string (date) |
Last day the menu is active | "2026-03-28" |
orderingDeadlineType |
"DAILY" | "WEEKLY" |
Deadline type for ordering: DAILY, WEEKLY, NONE | "DAILY" |
dailyCutoffTime |
string |
Daily cutoff time for pre-orders | "08:00:00" |
dailyCutoffDays |
integer (int32) |
Number of days before the meal day the daily cutoff applies | 2 |
weeklyCutoffDay |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY" |
Weekly cutoff day for pre-orders | "MONDAY" |
weeklyCutoffTime |
string |
Weekly cutoff time of day | "23:59:00" |
orderCancellationHours |
integer (int32) |
Hours before scheduled date that cancellation is allowed | 24 |
published |
boolean |
Whether the menu is published and visible to parents | |
audience |
"ALL" | "SPECIFIC" |
Who can see this menu: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetSectionIds |
string (uuid)[] |
Target section IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom/grade IDs when audience is SPECIFIC | |
excludedStudentIds |
string (uuid)[] |
Individual student IDs excluded from this menu | |
visibilityDays |
integer (int32) |
How many days ahead of today parents can see this menu in the Parent App | 30 |
updatedBy |
string (uuid) |
ID of the user who last updated this menu | "550e8400-e29b-41d4-a716-446655440000" |
updatedByName |
string |
Name of the user who last updated this menu | "Abena Mensah" |
createdAt |
string (date-time) |
When the menu was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the menu was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateMenuRequest } from '@smartsapp/sdk/staff';
import type { UpdateMenuRequest, MenuResponse } from '@smartsapp/sdk/staff';
const input: UpdateMenuRequest = {
name: "Weekly Lunch Menu",
description: "Standard weekly lunch offerings",
purpose: "PARENTS_CAN_ORDER",
paymentType: "ORDER_AND_PAY_ITEM_PRICING"
};
const parsed = zUpdateMenuRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: menu, error } = await canteenStaff.updateMenu({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menu is typed as MenuResponse
deleteMenu()¶
Delete a menu
DELETE /api/canteen/menus/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteMenu({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
unpublishMenu()¶
Unpublish a menu
PUT /api/canteen/menus/{id}/unpublish
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: MenuResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the menu | "Term 1 Lunch Menu" |
description |
string |
Description of the menu | "Daily lunch options for Term 1" |
purpose |
"INFO_ONLY" | "PARENTS_CAN_ORDER" |
Purpose of the menu: LUNCH, BREAKFAST, SNACK | "INFO_ONLY" |
paymentType |
"ORDER_AND_PAY_ITEM_PRICING" | "ORDER_ONLY_NO_PAYMENT" | "ORDER_AND_PAY_TICKET_PRICING" |
Payment type: PREPAID, POSTPAID | "ORDER_AND_PAY_ITEM_PRICING" |
startDate |
string (date) |
First day the menu is active | "2026-01-06" |
endDate |
string (date) |
Last day the menu is active | "2026-03-28" |
orderingDeadlineType |
"DAILY" | "WEEKLY" |
Deadline type for ordering: DAILY, WEEKLY, NONE | "DAILY" |
dailyCutoffTime |
string |
Daily cutoff time for pre-orders | "08:00:00" |
dailyCutoffDays |
integer (int32) |
Number of days before the meal day the daily cutoff applies | 2 |
weeklyCutoffDay |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY" |
Weekly cutoff day for pre-orders | "MONDAY" |
weeklyCutoffTime |
string |
Weekly cutoff time of day | "23:59:00" |
orderCancellationHours |
integer (int32) |
Hours before scheduled date that cancellation is allowed | 24 |
published |
boolean |
Whether the menu is published and visible to parents | |
audience |
"ALL" | "SPECIFIC" |
Who can see this menu: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetSectionIds |
string (uuid)[] |
Target section IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom/grade IDs when audience is SPECIFIC | |
excludedStudentIds |
string (uuid)[] |
Individual student IDs excluded from this menu | |
visibilityDays |
integer (int32) |
How many days ahead of today parents can see this menu in the Parent App | 30 |
updatedBy |
string (uuid) |
ID of the user who last updated this menu | "550e8400-e29b-41d4-a716-446655440000" |
updatedByName |
string |
Name of the user who last updated this menu | "Abena Mensah" |
createdAt |
string (date-time) |
When the menu was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the menu was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { MenuResponse } from '@smartsapp/sdk/staff';
const { data: menu, error } = await canteenStaff.unpublishMenu({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menu is typed as MenuResponse
publishMenu()¶
Publish a menu
PUT /api/canteen/menus/{id}/publish
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: MenuResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the menu | "Term 1 Lunch Menu" |
description |
string |
Description of the menu | "Daily lunch options for Term 1" |
purpose |
"INFO_ONLY" | "PARENTS_CAN_ORDER" |
Purpose of the menu: LUNCH, BREAKFAST, SNACK | "INFO_ONLY" |
paymentType |
"ORDER_AND_PAY_ITEM_PRICING" | "ORDER_ONLY_NO_PAYMENT" | "ORDER_AND_PAY_TICKET_PRICING" |
Payment type: PREPAID, POSTPAID | "ORDER_AND_PAY_ITEM_PRICING" |
startDate |
string (date) |
First day the menu is active | "2026-01-06" |
endDate |
string (date) |
Last day the menu is active | "2026-03-28" |
orderingDeadlineType |
"DAILY" | "WEEKLY" |
Deadline type for ordering: DAILY, WEEKLY, NONE | "DAILY" |
dailyCutoffTime |
string |
Daily cutoff time for pre-orders | "08:00:00" |
dailyCutoffDays |
integer (int32) |
Number of days before the meal day the daily cutoff applies | 2 |
weeklyCutoffDay |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY" |
Weekly cutoff day for pre-orders | "MONDAY" |
weeklyCutoffTime |
string |
Weekly cutoff time of day | "23:59:00" |
orderCancellationHours |
integer (int32) |
Hours before scheduled date that cancellation is allowed | 24 |
published |
boolean |
Whether the menu is published and visible to parents | |
audience |
"ALL" | "SPECIFIC" |
Who can see this menu: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetSectionIds |
string (uuid)[] |
Target section IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom/grade IDs when audience is SPECIFIC | |
excludedStudentIds |
string (uuid)[] |
Individual student IDs excluded from this menu | |
visibilityDays |
integer (int32) |
How many days ahead of today parents can see this menu in the Parent App | 30 |
updatedBy |
string (uuid) |
ID of the user who last updated this menu | "550e8400-e29b-41d4-a716-446655440000" |
updatedByName |
string |
Name of the user who last updated this menu | "Abena Mensah" |
createdAt |
string (date-time) |
When the menu was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the menu was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { MenuResponse } from '@smartsapp/sdk/staff';
const { data: menu, error } = await canteenStaff.publishMenu({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menu is typed as MenuResponse
listMenus()¶
List menus with pagination
GET /api/canteen/menus
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseMenuResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
MenuResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
MenuResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the menu | "Term 1 Lunch Menu" |
description |
string |
Description of the menu | "Daily lunch options for Term 1" |
purpose |
"INFO_ONLY" | "PARENTS_CAN_ORDER" |
Purpose of the menu: LUNCH, BREAKFAST, SNACK | "INFO_ONLY" |
paymentType |
"ORDER_AND_PAY_ITEM_PRICING" | "ORDER_ONLY_NO_PAYMENT" | "ORDER_AND_PAY_TICKET_PRICING" |
Payment type: PREPAID, POSTPAID | "ORDER_AND_PAY_ITEM_PRICING" |
startDate |
string (date) |
First day the menu is active | "2026-01-06" |
endDate |
string (date) |
Last day the menu is active | "2026-03-28" |
orderingDeadlineType |
"DAILY" | "WEEKLY" |
Deadline type for ordering: DAILY, WEEKLY, NONE | "DAILY" |
dailyCutoffTime |
string |
Daily cutoff time for pre-orders | "08:00:00" |
dailyCutoffDays |
integer (int32) |
Number of days before the meal day the daily cutoff applies | 2 |
weeklyCutoffDay |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY" |
Weekly cutoff day for pre-orders | "MONDAY" |
weeklyCutoffTime |
string |
Weekly cutoff time of day | "23:59:00" |
orderCancellationHours |
integer (int32) |
Hours before scheduled date that cancellation is allowed | 24 |
published |
boolean |
Whether the menu is published and visible to parents | |
audience |
"ALL" | "SPECIFIC" |
Who can see this menu: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetSectionIds |
string (uuid)[] |
Target section IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom/grade IDs when audience is SPECIFIC | |
excludedStudentIds |
string (uuid)[] |
Individual student IDs excluded from this menu | |
visibilityDays |
integer (int32) |
How many days ahead of today parents can see this menu in the Parent App | 30 |
updatedBy |
string (uuid) |
ID of the user who last updated this menu | "550e8400-e29b-41d4-a716-446655440000" |
updatedByName |
string |
Name of the user who last updated this menu | "Abena Mensah" |
createdAt |
string (date-time) |
When the menu was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the menu was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { PagedResponseMenuResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await canteenStaff.listMenus({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const menus = result.content; // MenuResponse[]
const { page, totalPages, totalElements, last } = result;
createMenu()¶
Create a new menu
POST /api/canteen/menus
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateMenuRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Name of the menu |
description |
string |
No | Description of the menu |
purpose |
"INFO_ONLY" | "PARENTS_CAN_ORDER" |
Yes | Purpose of the menu: PARENTS_CAN_ORDER (ordering enabled) or INFO_ONLY (view only) |
paymentType |
"ORDER_AND_PAY_ITEM_PRICING" | "ORDER_ONLY_NO_PAYMENT" | "ORDER_AND_PAY_TICKET_PRICING" |
No | Payment type for the menu. Only applies when purpose is PARENTS_CAN_ORDER. |
startDate |
string (date) |
Yes | Start date of the menu |
endDate |
string (date) |
Yes | End date of the menu |
orderingDeadlineType |
"DAILY" | "WEEKLY" |
No | Type of ordering deadline. Only applies when purpose is PARENTS_CAN_ORDER. |
dailyCutoffTime |
string |
No | Daily cutoff time for orders. Only applies when orderingDeadlineType is DAILY. |
dailyCutoffDays |
integer (int32) |
No | Number of days before the meal day the daily cutoff applies. Only applies when orderingDeadlineType is DAILY. Null or 0 means same-day cutoff. |
weeklyCutoffDay |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY" |
No | Weekly cutoff day for orders. Only applies when orderingDeadlineType is WEEKLY. |
weeklyCutoffTime |
string |
No | Weekly cutoff time of day. Only applies when orderingDeadlineType is WEEKLY. |
orderCancellationHours |
integer (int32) |
No | Hours before which an order can be cancelled. Only applies when purpose is PARENTS_CAN_ORDER. |
audience |
"ALL" | "SPECIFIC" |
Yes | Who can see this menu: ALL or SPECIFIC |
targetCampusIds |
string (uuid)[] |
No | Target campus IDs when audience is SPECIFIC |
targetSectionIds |
string (uuid)[] |
No | Target section IDs when audience is SPECIFIC |
targetClassroomIds |
string (uuid)[] |
No | Target classroom/grade IDs when audience is SPECIFIC |
excludedStudentIds |
string (uuid)[] |
No | Individual student IDs to exclude from this menu, even if they belong to a targeted campus/class |
visibilityDays |
integer (int32) |
Yes | How many days ahead of today parents can see this menu in the Parent App. Range 1–30. |
Response: MenuResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Menu ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the menu | "Term 1 Lunch Menu" |
description |
string |
Description of the menu | "Daily lunch options for Term 1" |
purpose |
"INFO_ONLY" | "PARENTS_CAN_ORDER" |
Purpose of the menu: LUNCH, BREAKFAST, SNACK | "INFO_ONLY" |
paymentType |
"ORDER_AND_PAY_ITEM_PRICING" | "ORDER_ONLY_NO_PAYMENT" | "ORDER_AND_PAY_TICKET_PRICING" |
Payment type: PREPAID, POSTPAID | "ORDER_AND_PAY_ITEM_PRICING" |
startDate |
string (date) |
First day the menu is active | "2026-01-06" |
endDate |
string (date) |
Last day the menu is active | "2026-03-28" |
orderingDeadlineType |
"DAILY" | "WEEKLY" |
Deadline type for ordering: DAILY, WEEKLY, NONE | "DAILY" |
dailyCutoffTime |
string |
Daily cutoff time for pre-orders | "08:00:00" |
dailyCutoffDays |
integer (int32) |
Number of days before the meal day the daily cutoff applies | 2 |
weeklyCutoffDay |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY" |
Weekly cutoff day for pre-orders | "MONDAY" |
weeklyCutoffTime |
string |
Weekly cutoff time of day | "23:59:00" |
orderCancellationHours |
integer (int32) |
Hours before scheduled date that cancellation is allowed | 24 |
published |
boolean |
Whether the menu is published and visible to parents | |
audience |
"ALL" | "SPECIFIC" |
Who can see this menu: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetSectionIds |
string (uuid)[] |
Target section IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom/grade IDs when audience is SPECIFIC | |
excludedStudentIds |
string (uuid)[] |
Individual student IDs excluded from this menu | |
visibilityDays |
integer (int32) |
How many days ahead of today parents can see this menu in the Parent App | 30 |
updatedBy |
string (uuid) |
ID of the user who last updated this menu | "550e8400-e29b-41d4-a716-446655440000" |
updatedByName |
string |
Name of the user who last updated this menu | "Abena Mensah" |
createdAt |
string (date-time) |
When the menu was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the menu was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateMenuRequest } from '@smartsapp/sdk/staff';
import type { CreateMenuRequest, MenuResponse } from '@smartsapp/sdk/staff';
const input: CreateMenuRequest = {
name: "Weekly Lunch Menu",
description: "Standard weekly lunch offerings",
purpose: "PARENTS_CAN_ORDER",
paymentType: "ORDER_AND_PAY_ITEM_PRICING"
};
const parsed = zCreateMenuRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: menu, error } = await canteenStaff.createMenu({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menu is typed as MenuResponse
getFullMenuSchedule()¶
Get full menu schedule
GET /api/canteen/menus/{id}/schedule
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
startDate |
string (date) |
query | Yes | |
endDate |
string (date) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: MenuFullScheduleResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
menuId |
string (uuid) |
ID of the menu | "550e8400-e29b-41d4-a716-446655440000" |
sections |
SectionScheduleResponse[] |
Sections with their scheduled items |
SectionScheduleResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
sectionId |
string (uuid) |
ID of the menu section | "550e8400-e29b-41d4-a716-446655440000" |
sectionName |
string |
Name of the menu section | "Lunch Main Course" |
servingStartTime |
string |
Serving start time | "11:30:00" |
servingEndTime |
string |
Serving end time | "13:30:00" |
selectionMode |
"SINGLE" | "MULTIPLE" |
How students select items: SINGLE or MULTIPLE | "SINGLE" |
schedule |
MenuScheduleGroupedResponse[] |
Schedule entries grouped by date |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { MenuFullScheduleResponse } from '@smartsapp/sdk/staff';
const { data: menuFullSchedule, error } = await canteenStaff.getFullMenuSchedule({
path: { id: "..." },
query: { startDate: "2026-01-01", endDate: "2026-01-01" }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menuFullSchedule is typed as MenuFullScheduleResponse
Meal Tickets¶
getMealTicket()¶
Get a meal ticket by ID
GET /api/canteen/meal-tickets/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: MealTicketResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Meal ticket ID | "550e8400-e29b-41d4-a716-446655440000" |
menuId |
string (uuid) |
ID of the menu this ticket is linked to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the meal ticket | "Term 1 Lunch Pass" |
academicTermId |
string (uuid) |
ID of the academic term | "550e8400-e29b-41d4-a716-446655440000" |
pricingMethod |
"DAILY" | "MONTHLY" | "TERMLY" |
How the ticket price is calculated: UNIFORM, ITEM_BASED | "DAILY" |
pricingScheme |
"UNIFORM" | "DIFFERENTIAL" |
Pricing scheme: PER_MEAL, FLAT_RATE | "UNIFORM" |
uniformPrice |
number |
Uniform price when pricing method is UNIFORM | 500.0 |
active |
boolean |
Whether the meal ticket is currently active | |
createdAt |
string (date-time) |
When the ticket was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the ticket was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { MealTicketResponse } from '@smartsapp/sdk/staff';
const { data: mealTicket, error } = await canteenStaff.getMealTicket({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// mealTicket is typed as MealTicketResponse
updateMealTicket()¶
Update a meal ticket
PUT /api/canteen/meal-tickets/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateMealTicketRequest
| Field | Type | Required | Description |
|---|---|---|---|
menuId |
string (uuid) |
No | ID of the associated menu |
name |
string |
No | Name of the meal ticket |
academicTermId |
string (uuid) |
No | ID of the academic term |
pricingMethod |
"DAILY" | "MONTHLY" | "TERMLY" |
No | Pricing method for the meal ticket |
pricingScheme |
"UNIFORM" | "DIFFERENTIAL" |
No | Pricing scheme for the meal ticket |
uniformPrice |
number |
No | Uniform price if applicable |
Response: MealTicketResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Meal ticket ID | "550e8400-e29b-41d4-a716-446655440000" |
menuId |
string (uuid) |
ID of the menu this ticket is linked to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the meal ticket | "Term 1 Lunch Pass" |
academicTermId |
string (uuid) |
ID of the academic term | "550e8400-e29b-41d4-a716-446655440000" |
pricingMethod |
"DAILY" | "MONTHLY" | "TERMLY" |
How the ticket price is calculated: UNIFORM, ITEM_BASED | "DAILY" |
pricingScheme |
"UNIFORM" | "DIFFERENTIAL" |
Pricing scheme: PER_MEAL, FLAT_RATE | "UNIFORM" |
uniformPrice |
number |
Uniform price when pricing method is UNIFORM | 500.0 |
active |
boolean |
Whether the meal ticket is currently active | |
createdAt |
string (date-time) |
When the ticket was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the ticket was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateMealTicketRequest } from '@smartsapp/sdk/staff';
import type { UpdateMealTicketRequest, MealTicketResponse } from '@smartsapp/sdk/staff';
const input: UpdateMealTicketRequest = {
menuId: "550e8400-e29b-41d4-a716-446655440000",
name: "Term 1 Lunch Pass",
academicTermId: "550e8400-e29b-41d4-a716-446655440001",
pricingMethod: "UNIFORM"
};
const parsed = zUpdateMealTicketRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: mealTicket, error } = await canteenStaff.updateMealTicket({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// mealTicket is typed as MealTicketResponse
deleteMealTicket()¶
Delete a meal ticket
DELETE /api/canteen/meal-tickets/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteMealTicket({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listMealTickets()¶
List meal tickets with pagination
GET /api/canteen/meal-tickets
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseMealTicketResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
MealTicketResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
MealTicketResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Meal ticket ID | "550e8400-e29b-41d4-a716-446655440000" |
menuId |
string (uuid) |
ID of the menu this ticket is linked to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the meal ticket | "Term 1 Lunch Pass" |
academicTermId |
string (uuid) |
ID of the academic term | "550e8400-e29b-41d4-a716-446655440000" |
pricingMethod |
"DAILY" | "MONTHLY" | "TERMLY" |
How the ticket price is calculated: UNIFORM, ITEM_BASED | "DAILY" |
pricingScheme |
"UNIFORM" | "DIFFERENTIAL" |
Pricing scheme: PER_MEAL, FLAT_RATE | "UNIFORM" |
uniformPrice |
number |
Uniform price when pricing method is UNIFORM | 500.0 |
active |
boolean |
Whether the meal ticket is currently active | |
createdAt |
string (date-time) |
When the ticket was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the ticket was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { PagedResponseMealTicketResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await canteenStaff.listMealTickets({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const mealTickets = result.content; // MealTicketResponse[]
const { page, totalPages, totalElements, last } = result;
createMealTicket()¶
Create a new meal ticket
POST /api/canteen/meal-tickets
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateMealTicketRequest
| Field | Type | Required | Description |
|---|---|---|---|
menuId |
string (uuid) |
Yes | ID of the associated menu |
name |
string |
Yes | Name of the meal ticket |
academicTermId |
string (uuid) |
Yes | ID of the academic term |
pricingMethod |
"DAILY" | "MONTHLY" | "TERMLY" |
Yes | Pricing method for the meal ticket |
pricingScheme |
"UNIFORM" | "DIFFERENTIAL" |
Yes | Pricing scheme for the meal ticket |
uniformPrice |
number |
No | Uniform price if applicable |
Response: MealTicketResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Meal ticket ID | "550e8400-e29b-41d4-a716-446655440000" |
menuId |
string (uuid) |
ID of the menu this ticket is linked to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the meal ticket | "Term 1 Lunch Pass" |
academicTermId |
string (uuid) |
ID of the academic term | "550e8400-e29b-41d4-a716-446655440000" |
pricingMethod |
"DAILY" | "MONTHLY" | "TERMLY" |
How the ticket price is calculated: UNIFORM, ITEM_BASED | "DAILY" |
pricingScheme |
"UNIFORM" | "DIFFERENTIAL" |
Pricing scheme: PER_MEAL, FLAT_RATE | "UNIFORM" |
uniformPrice |
number |
Uniform price when pricing method is UNIFORM | 500.0 |
active |
boolean |
Whether the meal ticket is currently active | |
createdAt |
string (date-time) |
When the ticket was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the ticket was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateMealTicketRequest } from '@smartsapp/sdk/staff';
import type { CreateMealTicketRequest, MealTicketResponse } from '@smartsapp/sdk/staff';
const input: CreateMealTicketRequest = {
menuId: "550e8400-e29b-41d4-a716-446655440000",
name: "Term 1 Lunch Pass",
academicTermId: "550e8400-e29b-41d4-a716-446655440001",
pricingMethod: "UNIFORM"
};
const parsed = zCreateMealTicketRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: mealTicket, error } = await canteenStaff.createMealTicket({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// mealTicket is typed as MealTicketResponse
Item Variants¶
updateItemVariant()¶
Update a variant
PUT /api/canteen/items/{itemId}/variants/{variantId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
itemId |
string (uuid) |
path | Yes | |
variantId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateItemVariantRequest
| Field | Type | Required | Description |
|---|---|---|---|
variantName |
string |
No | Variant name |
price |
number |
No | Variant price |
audience |
"ALL" | "SPECIFIC" |
No | Audience scope |
targetCampusIds |
string (uuid)[] |
No | Campus IDs this variant is available to. Required when audience is SPECIFIC. |
targetClassroomIds |
string (uuid)[] |
No | Class/grade IDs this variant is available to. Required when audience is SPECIFIC. |
Response: ItemVariantResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Variant ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the parent item | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the variant | "Large" |
price |
number |
Price of this variant | 15.0 |
audience |
"ALL" | "SPECIFIC" |
Who can see this variant: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom IDs when audience is SPECIFIC | |
createdAt |
string (date-time) |
When the variant was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the variant was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateItemVariantRequest } from '@smartsapp/sdk/staff';
import type { UpdateItemVariantRequest, ItemVariantResponse } from '@smartsapp/sdk/staff';
const input: UpdateItemVariantRequest = {
variantName: "Small",
price: 5.0,
audience: "ALL",
targetCampusIds: []
};
const parsed = zUpdateItemVariantRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: itemVariant, error } = await canteenStaff.updateItemVariant({
body: input,
path: { itemId: "...", variantId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// itemVariant is typed as ItemVariantResponse
deleteItemVariant()¶
Delete a variant
DELETE /api/canteen/items/{itemId}/variants/{variantId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
itemId |
string (uuid) |
path | Yes | |
variantId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteItemVariant({
path: { itemId: "...", variantId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listItemVariants()¶
List variants for an item
GET /api/canteen/items/{itemId}/variants
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
itemId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: ItemVariantResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Variant ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the parent item | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the variant | "Large" |
price |
number |
Price of this variant | 15.0 |
audience |
"ALL" | "SPECIFIC" |
Who can see this variant: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom IDs when audience is SPECIFIC | |
createdAt |
string (date-time) |
When the variant was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the variant was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.listItemVariants({
path: { itemId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as ItemVariantResponse[]
createItemVariant()¶
Add a variant to an item
POST /api/canteen/items/{itemId}/variants
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
itemId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateItemVariantRequest
| Field | Type | Required | Description |
|---|---|---|---|
variantName |
string |
Yes | Variant name |
price |
number |
Yes | Variant price |
audience |
"ALL" | "SPECIFIC" |
Yes | Audience scope |
targetCampusIds |
string (uuid)[] |
No | Campus IDs this variant is available to. Required when audience is SPECIFIC. |
targetClassroomIds |
string (uuid)[] |
No | Class/grade IDs this variant is available to. Required when audience is SPECIFIC. |
Response: ItemVariantResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Variant ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the parent item | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the variant | "Large" |
price |
number |
Price of this variant | 15.0 |
audience |
"ALL" | "SPECIFIC" |
Who can see this variant: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom IDs when audience is SPECIFIC | |
createdAt |
string (date-time) |
When the variant was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the variant was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateItemVariantRequest } from '@smartsapp/sdk/staff';
import type { CreateItemVariantRequest, ItemVariantResponse } from '@smartsapp/sdk/staff';
const input: CreateItemVariantRequest = {
variantName: "Small",
price: 5.0,
audience: "ALL",
targetCampusIds: []
};
const parsed = zCreateItemVariantRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: itemVariant, error } = await canteenStaff.createItemVariant({
body: input,
path: { itemId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// itemVariant is typed as ItemVariantResponse
Items¶
getItem()¶
Get a item by ID
GET /api/canteen/items/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: ItemResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item ID | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the catering service that supplies this item | "550e8400-e29b-41d4-a716-446655440000" |
itemCategoryId |
string (uuid) |
ID of the item's category | "550e8400-e29b-41d4-a716-446655440000" |
categoryName |
string |
Name of the item's category | "Beverages" |
name |
string |
Name of the item | "Jollof Rice" |
image |
string |
URL of the item image | "https://storage.example.com/items/jollof.jpg" |
description |
string |
Description of the item | "Spicy tomato-based rice dish" |
allergens |
string |
Comma-separated list of allergens | "gluten, peanuts" |
maxQuantityPerDay |
integer (int32) |
Maximum quantity a student can order per day (cumulative across all orders for the same date). Null means unlimited (no daily cap). | 3 |
pricingStyle |
"FIXED" | "VARIANT" | "NO_PRICE" |
How this item is priced: UNIFORM or VARIANT | "FIXED" |
defaultPrice |
number |
Default price when pricing style is UNIFORM | 12.5 |
currency |
string |
Currency code | "GHS" |
variants |
ItemVariantResponse[] |
Available variants for this item | |
createdBy |
CreatedBySummary |
Summary of who created the order | |
createdAt |
string (date-time) |
When the item was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the item was last updated | "2026-01-15T10:30:00Z" |
ItemVariantResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Variant ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the parent item | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the variant | "Large" |
price |
number |
Price of this variant | 15.0 |
audience |
"ALL" | "SPECIFIC" |
Who can see this variant: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom IDs when audience is SPECIFIC | |
createdAt |
string (date-time) |
When the variant was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the variant was last updated | "2026-01-15T10:30:00Z" |
CreatedBySummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
User ID of the creator | "550e8400-e29b-41d4-a716-446655440000" |
firstName |
string |
Creator's first name | "Abena" |
lastName |
string |
Creator's last name | "Mensah" |
type |
string |
Creator type: STAFF or PARENT | "STAFF" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { ItemResponse } from '@smartsapp/sdk/staff';
const { data: item, error } = await canteenStaff.getItem({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// item is typed as ItemResponse
updateItem()¶
Update a item
PUT /api/canteen/items/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateItemRequest
| Field | Type | Required | Description |
|---|---|---|---|
cateringServiceId |
string (uuid) |
No | ID of the catering service |
itemCategoryId |
string (uuid) |
No | ID of the item category |
name |
string |
No | Name of the item |
image |
string |
No | URL of the item image |
description |
string |
No | Description of the item |
allergens |
string |
No | Allergen information |
maxQuantityPerDay |
integer (int32) |
No | Maximum quantity of this item a single student can order per day (cumulative across all orders for the same date). Null means unlimited (no daily cap). |
pricingStyle |
"FIXED" | "VARIANT" | "NO_PRICE" |
No | Pricing style for the item |
defaultPrice |
number |
No | Default price of the item |
variants |
CreateItemVariantRequest[] |
No | Variants for VARIANT pricing style. Ignored for FIXED/NO_PRICE. |
CreateItemVariantRequest fields:
| Field | Type | Required | Description |
|---|---|---|---|
variantName |
string |
Yes | Variant name |
price |
number |
Yes | Variant price |
audience |
"ALL" | "SPECIFIC" |
Yes | Audience scope |
targetCampusIds |
string (uuid)[] |
No | Campus IDs this variant is available to. Required when audience is SPECIFIC. |
targetClassroomIds |
string (uuid)[] |
No | Class/grade IDs this variant is available to. Required when audience is SPECIFIC. |
Response: ItemResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item ID | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the catering service that supplies this item | "550e8400-e29b-41d4-a716-446655440000" |
itemCategoryId |
string (uuid) |
ID of the item's category | "550e8400-e29b-41d4-a716-446655440000" |
categoryName |
string |
Name of the item's category | "Beverages" |
name |
string |
Name of the item | "Jollof Rice" |
image |
string |
URL of the item image | "https://storage.example.com/items/jollof.jpg" |
description |
string |
Description of the item | "Spicy tomato-based rice dish" |
allergens |
string |
Comma-separated list of allergens | "gluten, peanuts" |
maxQuantityPerDay |
integer (int32) |
Maximum quantity a student can order per day (cumulative across all orders for the same date). Null means unlimited (no daily cap). | 3 |
pricingStyle |
"FIXED" | "VARIANT" | "NO_PRICE" |
How this item is priced: UNIFORM or VARIANT | "FIXED" |
defaultPrice |
number |
Default price when pricing style is UNIFORM | 12.5 |
currency |
string |
Currency code | "GHS" |
variants |
ItemVariantResponse[] |
Available variants for this item | |
createdBy |
CreatedBySummary |
Summary of who created the order | |
createdAt |
string (date-time) |
When the item was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the item was last updated | "2026-01-15T10:30:00Z" |
ItemVariantResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Variant ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the parent item | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the variant | "Large" |
price |
number |
Price of this variant | 15.0 |
audience |
"ALL" | "SPECIFIC" |
Who can see this variant: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom IDs when audience is SPECIFIC | |
createdAt |
string (date-time) |
When the variant was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the variant was last updated | "2026-01-15T10:30:00Z" |
CreatedBySummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
User ID of the creator | "550e8400-e29b-41d4-a716-446655440000" |
firstName |
string |
Creator's first name | "Abena" |
lastName |
string |
Creator's last name | "Mensah" |
type |
string |
Creator type: STAFF or PARENT | "STAFF" |
Example:
import { canteenStaff, zUpdateItemRequest } from '@smartsapp/sdk/staff';
import type { UpdateItemRequest, ItemResponse } from '@smartsapp/sdk/staff';
const input: UpdateItemRequest = {
cateringServiceId: "550e8400-e29b-41d4-a716-446655440000",
itemCategoryId: "550e8400-e29b-41d4-a716-446655440001",
name: "Jollof Rice",
image: "https://example.com/jollof.png"
};
const parsed = zUpdateItemRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: item, error } = await canteenStaff.updateItem({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// item is typed as ItemResponse
deleteItem()¶
Delete a item
DELETE /api/canteen/items/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteItem({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listItems()¶
List items with pagination and optional filters
GET /api/canteen/items
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
cateringServiceId |
string (uuid) |
query | No | Filter by catering service |
itemCategoryId |
string (uuid) |
query | No | Filter by item category |
search |
string |
query | No | Search by item name |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseItemResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
ItemResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
ItemResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item ID | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the catering service that supplies this item | "550e8400-e29b-41d4-a716-446655440000" |
itemCategoryId |
string (uuid) |
ID of the item's category | "550e8400-e29b-41d4-a716-446655440000" |
categoryName |
string |
Name of the item's category | "Beverages" |
name |
string |
Name of the item | "Jollof Rice" |
image |
string |
URL of the item image | "https://storage.example.com/items/jollof.jpg" |
description |
string |
Description of the item | "Spicy tomato-based rice dish" |
allergens |
string |
Comma-separated list of allergens | "gluten, peanuts" |
maxQuantityPerDay |
integer (int32) |
Maximum quantity a student can order per day (cumulative across all orders for the same date). Null means unlimited (no daily cap). | 3 |
pricingStyle |
"FIXED" | "VARIANT" | "NO_PRICE" |
How this item is priced: UNIFORM or VARIANT | "FIXED" |
defaultPrice |
number |
Default price when pricing style is UNIFORM | 12.5 |
currency |
string |
Currency code | "GHS" |
variants |
ItemVariantResponse[] |
Available variants for this item | |
createdBy |
CreatedBySummary |
Summary of who created the order | |
createdAt |
string (date-time) |
When the item was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the item was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { PagedResponseItemResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await canteenStaff.listItems({
query: { page: 0, size: 0, cateringServiceId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const items = result.content; // ItemResponse[]
const { page, totalPages, totalElements, last } = result;
createItem()¶
Create a new item
POST /api/canteen/items
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateItemRequest
| Field | Type | Required | Description |
|---|---|---|---|
cateringServiceId |
string (uuid) |
Yes | ID of the catering service |
itemCategoryId |
string (uuid) |
Yes | ID of the item category |
name |
string |
Yes | Name of the item |
image |
string |
No | URL of the item image |
description |
string |
No | Description of the item |
allergens |
string |
No | Allergen information |
maxQuantityPerDay |
integer (int32) |
No | Maximum quantity of this item a single student can order per day (cumulative across all orders for the same date). Null means unlimited (no daily cap). |
pricingStyle |
"FIXED" | "VARIANT" | "NO_PRICE" |
Yes | Pricing style for the item |
defaultPrice |
number |
No | Default price of the item |
variants |
CreateItemVariantRequest[] |
No | Variants for VARIANT pricing style. Ignored for FIXED/NO_PRICE. |
CreateItemVariantRequest fields:
| Field | Type | Required | Description |
|---|---|---|---|
variantName |
string |
Yes | Variant name |
price |
number |
Yes | Variant price |
audience |
"ALL" | "SPECIFIC" |
Yes | Audience scope |
targetCampusIds |
string (uuid)[] |
No | Campus IDs this variant is available to. Required when audience is SPECIFIC. |
targetClassroomIds |
string (uuid)[] |
No | Class/grade IDs this variant is available to. Required when audience is SPECIFIC. |
Response: ItemResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item ID | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the catering service that supplies this item | "550e8400-e29b-41d4-a716-446655440000" |
itemCategoryId |
string (uuid) |
ID of the item's category | "550e8400-e29b-41d4-a716-446655440000" |
categoryName |
string |
Name of the item's category | "Beverages" |
name |
string |
Name of the item | "Jollof Rice" |
image |
string |
URL of the item image | "https://storage.example.com/items/jollof.jpg" |
description |
string |
Description of the item | "Spicy tomato-based rice dish" |
allergens |
string |
Comma-separated list of allergens | "gluten, peanuts" |
maxQuantityPerDay |
integer (int32) |
Maximum quantity a student can order per day (cumulative across all orders for the same date). Null means unlimited (no daily cap). | 3 |
pricingStyle |
"FIXED" | "VARIANT" | "NO_PRICE" |
How this item is priced: UNIFORM or VARIANT | "FIXED" |
defaultPrice |
number |
Default price when pricing style is UNIFORM | 12.5 |
currency |
string |
Currency code | "GHS" |
variants |
ItemVariantResponse[] |
Available variants for this item | |
createdBy |
CreatedBySummary |
Summary of who created the order | |
createdAt |
string (date-time) |
When the item was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the item was last updated | "2026-01-15T10:30:00Z" |
ItemVariantResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Variant ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the parent item | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the variant | "Large" |
price |
number |
Price of this variant | 15.0 |
audience |
"ALL" | "SPECIFIC" |
Who can see this variant: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom IDs when audience is SPECIFIC | |
createdAt |
string (date-time) |
When the variant was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the variant was last updated | "2026-01-15T10:30:00Z" |
CreatedBySummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
User ID of the creator | "550e8400-e29b-41d4-a716-446655440000" |
firstName |
string |
Creator's first name | "Abena" |
lastName |
string |
Creator's last name | "Mensah" |
type |
string |
Creator type: STAFF or PARENT | "STAFF" |
Example:
import { canteenStaff, zCreateItemRequest } from '@smartsapp/sdk/staff';
import type { CreateItemRequest, ItemResponse } from '@smartsapp/sdk/staff';
const input: CreateItemRequest = {
cateringServiceId: "550e8400-e29b-41d4-a716-446655440000",
itemCategoryId: "550e8400-e29b-41d4-a716-446655440001",
name: "Jollof Rice",
image: "https://example.com/jollof.png"
};
const parsed = zCreateItemRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: item, error } = await canteenStaff.createItem({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// item is typed as ItemResponse
listRecentlyUsedItems()¶
List items recently scheduled on menus (last 30 days)
GET /api/canteen/items/recently-used
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
limit |
integer (int32) |
query | No | Max number of items to return |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: ItemResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item ID | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the catering service that supplies this item | "550e8400-e29b-41d4-a716-446655440000" |
itemCategoryId |
string (uuid) |
ID of the item's category | "550e8400-e29b-41d4-a716-446655440000" |
categoryName |
string |
Name of the item's category | "Beverages" |
name |
string |
Name of the item | "Jollof Rice" |
image |
string |
URL of the item image | "https://storage.example.com/items/jollof.jpg" |
description |
string |
Description of the item | "Spicy tomato-based rice dish" |
allergens |
string |
Comma-separated list of allergens | "gluten, peanuts" |
maxQuantityPerDay |
integer (int32) |
Maximum quantity a student can order per day (cumulative across all orders for the same date). Null means unlimited (no daily cap). | 3 |
pricingStyle |
"FIXED" | "VARIANT" | "NO_PRICE" |
How this item is priced: UNIFORM or VARIANT | "FIXED" |
defaultPrice |
number |
Default price when pricing style is UNIFORM | 12.5 |
currency |
string |
Currency code | "GHS" |
variants |
ItemVariantResponse[] |
Available variants for this item | |
createdBy |
CreatedBySummary |
Summary of who created the order | |
createdAt |
string (date-time) |
When the item was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the item was last updated | "2026-01-15T10:30:00Z" |
ItemVariantResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Variant ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the parent item | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the variant | "Large" |
price |
number |
Price of this variant | 15.0 |
audience |
"ALL" | "SPECIFIC" |
Who can see this variant: ALL or SPECIFIC | "ALL" |
targetCampusIds |
string (uuid)[] |
Target campus IDs when audience is SPECIFIC | |
targetClassroomIds |
string (uuid)[] |
Target classroom IDs when audience is SPECIFIC | |
createdAt |
string (date-time) |
When the variant was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the variant was last updated | "2026-01-15T10:30:00Z" |
CreatedBySummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
User ID of the creator | "550e8400-e29b-41d4-a716-446655440000" |
firstName |
string |
Creator's first name | "Abena" |
lastName |
string |
Creator's last name | "Mensah" |
type |
string |
Creator type: STAFF or PARENT | "STAFF" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.listRecentlyUsedItems({
query: { limit: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as ItemResponse[]
getItemLibrary()¶
Get item library with recently used items and items grouped by category
GET /api/canteen/items/library
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
cateringServiceId |
string (uuid) |
query | No | Filter by catering service |
search |
string |
query | No | Search by item name |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: ItemLibraryResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
recentlyUsed |
ItemResponse[] |
Items recently scheduled on menus (last 30 days) | |
categories |
CategoryGroup[] |
All items grouped by category |
ItemResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item ID | "550e8400-e29b-41d4-a716-446655440000" |
cateringServiceId |
string (uuid) |
ID of the catering service that supplies this item | "550e8400-e29b-41d4-a716-446655440000" |
itemCategoryId |
string (uuid) |
ID of the item's category | "550e8400-e29b-41d4-a716-446655440000" |
categoryName |
string |
Name of the item's category | "Beverages" |
name |
string |
Name of the item | "Jollof Rice" |
image |
string |
URL of the item image | "https://storage.example.com/items/jollof.jpg" |
description |
string |
Description of the item | "Spicy tomato-based rice dish" |
allergens |
string |
Comma-separated list of allergens | "gluten, peanuts" |
maxQuantityPerDay |
integer (int32) |
Maximum quantity a student can order per day (cumulative across all orders for the same date). Null means unlimited (no daily cap). | 3 |
pricingStyle |
"FIXED" | "VARIANT" | "NO_PRICE" |
How this item is priced: UNIFORM or VARIANT | "FIXED" |
defaultPrice |
number |
Default price when pricing style is UNIFORM | 12.5 |
currency |
string |
Currency code | "GHS" |
variants |
ItemVariantResponse[] |
Available variants for this item | |
createdBy |
CreatedBySummary |
Summary of who created the order | |
createdAt |
string (date-time) |
When the item was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the item was last updated | "2026-01-15T10:30:00Z" |
CategoryGroup fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Category ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Category name | "Beverages" |
themeColor |
string |
Theme colour hex code for the category | "#FF5733" |
items |
ItemResponse[] |
Items belonging to this category |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { ItemLibraryResponse } from '@smartsapp/sdk/staff';
const { data: itemLibrary, error } = await canteenStaff.getItemLibrary({
query: { cateringServiceId: "...", search: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// itemLibrary is typed as ItemLibraryResponse
Item Categories¶
getItemCategory()¶
Get an item category by ID
GET /api/canteen/item-categories/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: ItemCategoryResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item category ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Category name | "Beverages" |
description |
string |
Description of the category | "All drink items" |
themeColor |
string |
Theme colour hex code | "#FF5733" |
totalItems |
integer (int64) |
Number of items in this category | 12 |
createdAt |
string (date-time) |
When the category was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the category was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { ItemCategoryResponse } from '@smartsapp/sdk/staff';
const { data: itemCategory, error } = await canteenStaff.getItemCategory({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// itemCategory is typed as ItemCategoryResponse
updateItemCategory()¶
Update an item category
PUT /api/canteen/item-categories/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateItemCategoryRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
No | Name of the item category |
description |
string |
No | Description of the item category |
themeColor |
string |
No | Theme color hex code |
Response: ItemCategoryResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item category ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Category name | "Beverages" |
description |
string |
Description of the category | "All drink items" |
themeColor |
string |
Theme colour hex code | "#FF5733" |
totalItems |
integer (int64) |
Number of items in this category | 12 |
createdAt |
string (date-time) |
When the category was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the category was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateItemCategoryRequest } from '@smartsapp/sdk/staff';
import type { UpdateItemCategoryRequest, ItemCategoryResponse } from '@smartsapp/sdk/staff';
const input: UpdateItemCategoryRequest = {
name: "Beverages",
description: "Drinks and refreshments",
themeColor: "#FF5733"
};
const parsed = zUpdateItemCategoryRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: itemCategory, error } = await canteenStaff.updateItemCategory({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// itemCategory is typed as ItemCategoryResponse
deleteItemCategory()¶
Delete an item category
DELETE /api/canteen/item-categories/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteItemCategory({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listItemCategories()¶
List item categories with pagination
GET /api/canteen/item-categories
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseItemCategoryResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
ItemCategoryResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
ItemCategoryResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item category ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Category name | "Beverages" |
description |
string |
Description of the category | "All drink items" |
themeColor |
string |
Theme colour hex code | "#FF5733" |
totalItems |
integer (int64) |
Number of items in this category | 12 |
createdAt |
string (date-time) |
When the category was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the category was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { PagedResponseItemCategoryResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await canteenStaff.listItemCategories({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const itemCategorys = result.content; // ItemCategoryResponse[]
const { page, totalPages, totalElements, last } = result;
createItemCategory()¶
Create a new item category
POST /api/canteen/item-categories
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateItemCategoryRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Name of the item category |
description |
string |
No | Description of the item category |
themeColor |
string |
No | Theme color hex code |
Response: ItemCategoryResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Item category ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Category name | "Beverages" |
description |
string |
Description of the category | "All drink items" |
themeColor |
string |
Theme colour hex code | "#FF5733" |
totalItems |
integer (int64) |
Number of items in this category | 12 |
createdAt |
string (date-time) |
When the category was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the category was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateItemCategoryRequest } from '@smartsapp/sdk/staff';
import type { CreateItemCategoryRequest, ItemCategoryResponse } from '@smartsapp/sdk/staff';
const input: CreateItemCategoryRequest = {
name: "Beverages",
description: "Drinks and refreshments",
themeColor: "#FF5733"
};
const parsed = zCreateItemCategoryRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: itemCategory, error } = await canteenStaff.createItemCategory({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// itemCategory is typed as ItemCategoryResponse
Feeding List¶
bulkRedeemOrders()¶
Bulk redeem multiple orders
PUT /api/canteen/feeding-list/bulk-redeem
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: BulkRedeemRequest
| Field | Type | Required | Description |
|---|---|---|---|
orderIds |
string (uuid)[] |
Yes | List of order IDs to redeem |
Response: FeedingListEntryResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order ID | "550e8400-e29b-41d4-a716-446655440000" |
orderNumber |
string |
Human-readable order number | "ORD-20260115-001" |
student |
StudentSummary |
Student summary for order context | |
createdBy |
CreatedBySummary |
Summary of who created the order | |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Type of order: WALK_IN or PRE_ORDER | "TICKET" |
totalPrice |
number |
Total price of the order | 25.0 |
currency |
string |
Currency code | "GHS" |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
How the order was paid: CASH, MEAL_TICKET, MOBILE_MONEY | "SIKA_ID" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status: DRAFT, CONFIRMED, SERVED, CANCELLED | "DRAFT" |
scheduledDate |
string (date-time) |
Date and time the order is scheduled for | "2026-01-15T12:00:00" |
items |
OrderItemDetailResponse[] |
Items included in this order | |
redeemedAt |
string (date-time) |
When the order was redeemed/served | "2026-01-15T12:30:00Z" |
createdAt |
string (date-time) |
When the order was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the order was last updated | "2026-01-15T10:30:00Z" |
StudentSummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Student ID | "550e8400-e29b-41d4-a716-446655440000" |
firstName |
string |
Student's first name | "Kofi" |
lastName |
string |
Student's last name | "Asante" |
className |
string |
Name of the student's class | "Grade 3A" |
CreatedBySummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
User ID of the creator | "550e8400-e29b-41d4-a716-446655440000" |
firstName |
string |
Creator's first name | "Abena" |
lastName |
string |
Creator's last name | "Mensah" |
type |
string |
Creator type: STAFF or PARENT | "STAFF" |
OrderItemDetailResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order item ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the ordered item | "550e8400-e29b-41d4-a716-446655440000" |
itemName |
string |
Name of the ordered item | "Jollof Rice" |
variantId |
string (uuid) |
ID of the selected variant | "550e8400-e29b-41d4-a716-446655440000" |
variantName |
string |
Name of the selected variant | "Large" |
menuSectionId |
string (uuid) |
ID of the menu section this item was ordered from | "550e8400-e29b-41d4-a716-446655440000" |
sectionName |
string |
Name of the menu section | "Lunch Main Course" |
quantity |
integer (int32) |
Quantity ordered | 2 |
unitPrice |
number |
Unit price at time of order | 12.5 |
currency |
string |
Currency code | "GHS" |
served |
boolean |
Whether this item has been served | |
servedAt |
string (date-time) |
When the item was served | "2026-01-15T12:30:00Z" |
servedBy |
integer (int64) |
ID of the user who served the item | 42 |
servedByName |
string |
Name of the user who served the item | "Abena Mensah" |
Example:
import { canteenStaff, zBulkRedeemRequest } from '@smartsapp/sdk/staff';
import type { BulkRedeemRequest } from '@smartsapp/sdk/staff';
const input: BulkRedeemRequest = {
orderIds: []
};
const parsed = zBulkRedeemRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data, error } = await canteenStaff.bulkRedeemOrders({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as FeedingListEntryResponse[]
listFeedingEntries()¶
List feeding list entries with pagination and filters
GET /api/canteen/feeding-list
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED"[] |
query | No | |
orderType |
"TICKET" | "PRE_ORDER" | "POS"[] |
query | No | |
dateFrom |
string (date) |
query | No | |
dateTo |
string (date) |
query | No | |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION"[] |
query | No | |
personnelId |
string (uuid) |
query | No | |
studentName |
string |
query | No | |
itemName |
string |
query | No | |
classroomId |
string (uuid) |
query | No | |
sectionId |
string (uuid) |
query | No | |
campusId |
string (uuid) |
query | No | |
menuId |
string (uuid) |
query | No | |
categoryId |
string (uuid) |
query | No | |
cateringServiceId |
string (uuid) |
query | No | |
attendanceStatus |
"PRESENT" | "ABSENT" | "LATE" | "EXCUSED" |
query | No | |
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseFeedingListEntryResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
FeedingListEntryResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
FeedingListEntryResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Order ID | "550e8400-e29b-41d4-a716-446655440000" |
orderNumber |
string |
Human-readable order number | "ORD-20260115-001" |
student |
StudentSummary |
Student summary for order context | |
createdBy |
CreatedBySummary |
Summary of who created the order | |
orderType |
"TICKET" | "PRE_ORDER" | "POS" |
Type of order: WALK_IN or PRE_ORDER | "TICKET" |
totalPrice |
number |
Total price of the order | 25.0 |
currency |
string |
Currency code | "GHS" |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
How the order was paid: CASH, MEAL_TICKET, MOBILE_MONEY | "SIKA_ID" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status: DRAFT, CONFIRMED, SERVED, CANCELLED | "DRAFT" |
scheduledDate |
string (date-time) |
Date and time the order is scheduled for | "2026-01-15T12:00:00" |
items |
OrderItemDetailResponse[] |
Items included in this order | |
redeemedAt |
string (date-time) |
When the order was redeemed/served | "2026-01-15T12:30:00Z" |
createdAt |
string (date-time) |
When the order was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the order was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { PagedResponseFeedingListEntryResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await canteenStaff.listFeedingEntries({
query: { status: "...", orderType: "...", dateFrom: "2026-01-01" }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const feedingListEntrys = result.content; // FeedingListEntryResponse[]
const { page, totalPages, totalElements, last } = result;
exportFeedingList()¶
Export feeding list as Excel
GET /api/canteen/feeding-list/export
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED"[] |
query | No | |
orderType |
"TICKET" | "PRE_ORDER" | "POS"[] |
query | No | |
dateFrom |
string (date) |
query | No | |
dateTo |
string (date) |
query | No | |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION"[] |
query | No | |
personnelId |
string (uuid) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: string (byte) (200)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.exportFeedingList({
query: { status: "...", orderType: "...", dateFrom: "2026-01-01" }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
Catering Services¶
getCateringService()¶
Get a catering service by ID
GET /api/canteen/catering-services/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: CateringServiceResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Catering service ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the catering service | "ABC Catering" |
logo |
string |
URL of the catering service logo | "https://storage.example.com/logos/abc.png" |
email |
string |
Contact email address | "[email protected]" |
phone |
string |
Contact phone number | "+233501234567" |
settlementAccountType |
"BANK" | "MOBILE_MONEY" |
Settlement account type (null if not configured) | "BANK" |
settlementAccountName |
string |
Account holder name on the settlement account | "ABC Catering Ltd" |
settlementAccountNumber |
string |
Bank account number or mobile money number | 1234567890 |
settlementBank |
"ABSA_BANK_GHANA" | "ACCESS_BANK_GHANA" | "AGRICULTURAL_DEVELOPMENT_BANK" | "BANK_OF_AFRICA_GHANA" | "CALBANK" | "CONSOLIDATED_BANK_GHANA" | "ECOBANK_GHANA" | "FBN_BANK_GHANA" | "FIDELITY_BANK_GHANA" | "FIRST_ATLANTIC_BANK" | "FIRST_NATIONAL_BANK_GHANA" | "GCB_BANK" | "GUARANTY_TRUST_BANK_GHANA" | "NATIONAL_INVESTMENT_BANK" | "OMNIBSIC_BANK_GHANA" | "PRUDENTIAL_BANK" | "REPUBLIC_BANK_GHANA" | "SOCIETE_GENERALE_GHANA" | "STANBIC_BANK_GHANA" | "STANDARD_CHARTERED_BANK_GHANA" | "UNITED_BANK_FOR_AFRICA_GHANA" | "UNIVERSAL_MERCHANT_BANK" | "ZENITH_BANK_GHANA" |
Bank (when settlementAccountType=BANK) | "GCB_BANK" |
settlementMobileMoneyProvider |
"MTN" | "TELECEL" | "AIRTELTIGO" |
Mobile money provider (when settlementAccountType=MOBILE_MONEY) | "MTN" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { CateringServiceResponse } from '@smartsapp/sdk/staff';
const { data: cateringService, error } = await canteenStaff.getCateringService({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// cateringService is typed as CateringServiceResponse
updateCateringService()¶
Update a catering service
PUT /api/canteen/catering-services/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateCateringServiceRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
No | Name of the catering service |
logo |
string |
No | URL of the catering service logo |
email |
string |
No | Contact email address |
phone |
string |
No | Contact phone number |
settlementAccountType |
"BANK" | "MOBILE_MONEY" |
No | Settlement account type. Null clears settlement details. |
settlementAccountName |
string |
No | Account holder name on the settlement account |
settlementAccountNumber |
string |
No | Bank account number or mobile money number |
settlementBank |
"ABSA_BANK_GHANA" | "ACCESS_BANK_GHANA" | "AGRICULTURAL_DEVELOPMENT_BANK" | "BANK_OF_AFRICA_GHANA" | "CALBANK" | "CONSOLIDATED_BANK_GHANA" | "ECOBANK_GHANA" | "FBN_BANK_GHANA" | "FIDELITY_BANK_GHANA" | "FIRST_ATLANTIC_BANK" | "FIRST_NATIONAL_BANK_GHANA" | "GCB_BANK" | "GUARANTY_TRUST_BANK_GHANA" | "NATIONAL_INVESTMENT_BANK" | "OMNIBSIC_BANK_GHANA" | "PRUDENTIAL_BANK" | "REPUBLIC_BANK_GHANA" | "SOCIETE_GENERALE_GHANA" | "STANBIC_BANK_GHANA" | "STANDARD_CHARTERED_BANK_GHANA" | "UNITED_BANK_FOR_AFRICA_GHANA" | "UNIVERSAL_MERCHANT_BANK" | "ZENITH_BANK_GHANA" |
No | Bank (required when settlementAccountType=BANK) |
settlementMobileMoneyProvider |
"MTN" | "TELECEL" | "AIRTELTIGO" |
No | Mobile money provider (required when settlementAccountType=MOBILE_MONEY) |
Response: CateringServiceResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Catering service ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the catering service | "ABC Catering" |
logo |
string |
URL of the catering service logo | "https://storage.example.com/logos/abc.png" |
email |
string |
Contact email address | "[email protected]" |
phone |
string |
Contact phone number | "+233501234567" |
settlementAccountType |
"BANK" | "MOBILE_MONEY" |
Settlement account type (null if not configured) | "BANK" |
settlementAccountName |
string |
Account holder name on the settlement account | "ABC Catering Ltd" |
settlementAccountNumber |
string |
Bank account number or mobile money number | 1234567890 |
settlementBank |
"ABSA_BANK_GHANA" | "ACCESS_BANK_GHANA" | "AGRICULTURAL_DEVELOPMENT_BANK" | "BANK_OF_AFRICA_GHANA" | "CALBANK" | "CONSOLIDATED_BANK_GHANA" | "ECOBANK_GHANA" | "FBN_BANK_GHANA" | "FIDELITY_BANK_GHANA" | "FIRST_ATLANTIC_BANK" | "FIRST_NATIONAL_BANK_GHANA" | "GCB_BANK" | "GUARANTY_TRUST_BANK_GHANA" | "NATIONAL_INVESTMENT_BANK" | "OMNIBSIC_BANK_GHANA" | "PRUDENTIAL_BANK" | "REPUBLIC_BANK_GHANA" | "SOCIETE_GENERALE_GHANA" | "STANBIC_BANK_GHANA" | "STANDARD_CHARTERED_BANK_GHANA" | "UNITED_BANK_FOR_AFRICA_GHANA" | "UNIVERSAL_MERCHANT_BANK" | "ZENITH_BANK_GHANA" |
Bank (when settlementAccountType=BANK) | "GCB_BANK" |
settlementMobileMoneyProvider |
"MTN" | "TELECEL" | "AIRTELTIGO" |
Mobile money provider (when settlementAccountType=MOBILE_MONEY) | "MTN" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateCateringServiceRequest } from '@smartsapp/sdk/staff';
import type { UpdateCateringServiceRequest, CateringServiceResponse } from '@smartsapp/sdk/staff';
const input: UpdateCateringServiceRequest = {
name: "Fresh Bites Catering",
logo: "https://example.com/logo.png",
email: "[email protected]",
phone: "+233201234567"
};
const parsed = zUpdateCateringServiceRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: cateringService, error } = await canteenStaff.updateCateringService({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// cateringService is typed as CateringServiceResponse
deleteCateringService()¶
Delete a catering service
DELETE /api/canteen/catering-services/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteCateringService({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listCateringServices()¶
List catering services with pagination
GET /api/canteen/catering-services
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseCateringServiceResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
CateringServiceResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
CateringServiceResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Catering service ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the catering service | "ABC Catering" |
logo |
string |
URL of the catering service logo | "https://storage.example.com/logos/abc.png" |
email |
string |
Contact email address | "[email protected]" |
phone |
string |
Contact phone number | "+233501234567" |
settlementAccountType |
"BANK" | "MOBILE_MONEY" |
Settlement account type (null if not configured) | "BANK" |
settlementAccountName |
string |
Account holder name on the settlement account | "ABC Catering Ltd" |
settlementAccountNumber |
string |
Bank account number or mobile money number | 1234567890 |
settlementBank |
"ABSA_BANK_GHANA" | "ACCESS_BANK_GHANA" | "AGRICULTURAL_DEVELOPMENT_BANK" | "BANK_OF_AFRICA_GHANA" | "CALBANK" | "CONSOLIDATED_BANK_GHANA" | "ECOBANK_GHANA" | "FBN_BANK_GHANA" | "FIDELITY_BANK_GHANA" | "FIRST_ATLANTIC_BANK" | "FIRST_NATIONAL_BANK_GHANA" | "GCB_BANK" | "GUARANTY_TRUST_BANK_GHANA" | "NATIONAL_INVESTMENT_BANK" | "OMNIBSIC_BANK_GHANA" | "PRUDENTIAL_BANK" | "REPUBLIC_BANK_GHANA" | "SOCIETE_GENERALE_GHANA" | "STANBIC_BANK_GHANA" | "STANDARD_CHARTERED_BANK_GHANA" | "UNITED_BANK_FOR_AFRICA_GHANA" | "UNIVERSAL_MERCHANT_BANK" | "ZENITH_BANK_GHANA" |
Bank (when settlementAccountType=BANK) | "GCB_BANK" |
settlementMobileMoneyProvider |
"MTN" | "TELECEL" | "AIRTELTIGO" |
Mobile money provider (when settlementAccountType=MOBILE_MONEY) | "MTN" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { PagedResponseCateringServiceResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await canteenStaff.listCateringServices({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const cateringServices = result.content; // CateringServiceResponse[]
const { page, totalPages, totalElements, last } = result;
createCateringService()¶
Create a new catering service
POST /api/canteen/catering-services
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateCateringServiceRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Name of the catering service |
logo |
string |
No | URL of the catering service logo |
email |
string |
Yes | Contact email address |
phone |
string |
Yes | Contact phone number |
settlementAccountType |
"BANK" | "MOBILE_MONEY" |
No | Settlement account type. Optional on create — can be configured later. |
settlementAccountName |
string |
No | Account holder name on the settlement account |
settlementAccountNumber |
string |
No | Bank account number or mobile money number |
settlementBank |
"ABSA_BANK_GHANA" | "ACCESS_BANK_GHANA" | "AGRICULTURAL_DEVELOPMENT_BANK" | "BANK_OF_AFRICA_GHANA" | "CALBANK" | "CONSOLIDATED_BANK_GHANA" | "ECOBANK_GHANA" | "FBN_BANK_GHANA" | "FIDELITY_BANK_GHANA" | "FIRST_ATLANTIC_BANK" | "FIRST_NATIONAL_BANK_GHANA" | "GCB_BANK" | "GUARANTY_TRUST_BANK_GHANA" | "NATIONAL_INVESTMENT_BANK" | "OMNIBSIC_BANK_GHANA" | "PRUDENTIAL_BANK" | "REPUBLIC_BANK_GHANA" | "SOCIETE_GENERALE_GHANA" | "STANBIC_BANK_GHANA" | "STANDARD_CHARTERED_BANK_GHANA" | "UNITED_BANK_FOR_AFRICA_GHANA" | "UNIVERSAL_MERCHANT_BANK" | "ZENITH_BANK_GHANA" |
No | Bank (required when settlementAccountType=BANK) |
settlementMobileMoneyProvider |
"MTN" | "TELECEL" | "AIRTELTIGO" |
No | Mobile money provider (required when settlementAccountType=MOBILE_MONEY) |
Response: CateringServiceResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Catering service ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the catering service | "ABC Catering" |
logo |
string |
URL of the catering service logo | "https://storage.example.com/logos/abc.png" |
email |
string |
Contact email address | "[email protected]" |
phone |
string |
Contact phone number | "+233501234567" |
settlementAccountType |
"BANK" | "MOBILE_MONEY" |
Settlement account type (null if not configured) | "BANK" |
settlementAccountName |
string |
Account holder name on the settlement account | "ABC Catering Ltd" |
settlementAccountNumber |
string |
Bank account number or mobile money number | 1234567890 |
settlementBank |
"ABSA_BANK_GHANA" | "ACCESS_BANK_GHANA" | "AGRICULTURAL_DEVELOPMENT_BANK" | "BANK_OF_AFRICA_GHANA" | "CALBANK" | "CONSOLIDATED_BANK_GHANA" | "ECOBANK_GHANA" | "FBN_BANK_GHANA" | "FIDELITY_BANK_GHANA" | "FIRST_ATLANTIC_BANK" | "FIRST_NATIONAL_BANK_GHANA" | "GCB_BANK" | "GUARANTY_TRUST_BANK_GHANA" | "NATIONAL_INVESTMENT_BANK" | "OMNIBSIC_BANK_GHANA" | "PRUDENTIAL_BANK" | "REPUBLIC_BANK_GHANA" | "SOCIETE_GENERALE_GHANA" | "STANBIC_BANK_GHANA" | "STANDARD_CHARTERED_BANK_GHANA" | "UNITED_BANK_FOR_AFRICA_GHANA" | "UNIVERSAL_MERCHANT_BANK" | "ZENITH_BANK_GHANA" |
Bank (when settlementAccountType=BANK) | "GCB_BANK" |
settlementMobileMoneyProvider |
"MTN" | "TELECEL" | "AIRTELTIGO" |
Mobile money provider (when settlementAccountType=MOBILE_MONEY) | "MTN" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateCateringServiceRequest } from '@smartsapp/sdk/staff';
import type { CreateCateringServiceRequest, CateringServiceResponse } from '@smartsapp/sdk/staff';
const input: CreateCateringServiceRequest = {
name: "Fresh Bites Catering",
logo: "https://example.com/logo.png",
email: "[email protected]",
phone: "+233201234567"
};
const parsed = zCreateCateringServiceRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: cateringService, error } = await canteenStaff.createCateringService({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// cateringService is typed as CateringServiceResponse
Menu Schedules¶
listScheduleEntries()¶
List schedule entries for a section, grouped by date
GET /api/canteen/menus/{menuId}/sections/{sectionId}/schedules
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
sectionId |
string (uuid) |
path | Yes | |
startDate |
string (date) |
query | Yes | |
endDate |
string (date) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: MenuScheduleGroupedResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
date |
string (date) |
Scheduled date | "2026-01-15" |
items |
MenuScheduleEntryResponse[] |
Items scheduled for this date |
MenuScheduleEntryResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Schedule entry ID | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the scheduled item | "550e8400-e29b-41d4-a716-446655440000" |
itemName |
string |
Name of the scheduled item | "Jollof Rice" |
defaultPrice |
number |
Default price of the item | 12.5 |
currency |
string |
Currency code | "GHS" |
scheduledViaCategoryId |
string (uuid) |
The category ID used to schedule this item, or null if scheduled directly | "550e8400-e29b-41d4-a716-446655440000" |
categoryName |
string |
Category name when scheduled via a category | "Beverages" |
variants |
ScheduleItemVariantResponse[] |
Available variants for this scheduled item | |
stockAvailable |
integer (int32) |
Stock available for this item on this day. Null means unlimited (no stock cap). | 40 |
recurrenceRule |
"SINGLE_DAY" | "EVERY_DAY" | "EVERY_WEEKDAY" | "SPECIFIC_DAYS" |
How this row was created — mirrors the request-time SchedulePattern. Lets the planner inspector show the correct repeat option when re-opened on a cell. | "SPECIFIC_DAYS" |
createdAt |
string (date-time) |
When the schedule entry was created | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.listScheduleEntries({
path: { menuId: "...", sectionId: "..." },
query: { startDate: "2026-01-01", endDate: "2026-01-01" }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as MenuScheduleGroupedResponse[]
scheduleItems()¶
Schedule items to a section
POST /api/canteen/menus/{menuId}/sections/{sectionId}/schedules
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
sectionId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateMenuScheduleRequest
| Field | Type | Required | Description |
|---|---|---|---|
itemId |
string (uuid) |
No | ID of the item to schedule. If categoryId is also provided, the categoryId is attached as a provenance tag to every created entry rather than triggering a category-batch schedule. At least one of itemId or categoryId is required. |
categoryId |
string (uuid) |
No | ID of the category. When provided alone, every item in the category is scheduled. When provided alongside itemId, it acts as a provenance tag applied to each created entry (used by the planner's delete-subsequent flow to find recurring expansions of a category-sourced item). At least one of itemId or categoryId is required. |
excludeItemIds |
string (uuid)[] |
No | Item IDs to exclude when scheduling by category. Only used with categoryId. |
date |
string (date) |
No | The specific date to schedule. Required when pattern is SINGLE_DAY. |
pattern |
"SINGLE_DAY" | "EVERY_DAY" | "EVERY_WEEKDAY" | "SPECIFIC_DAYS" |
Yes | Scheduling pattern: SINGLE_DAY, EVERY_DAY, EVERY_WEEKDAY, or SPECIFIC_DAYS. |
days |
"MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY"[] |
No | Days of the week to schedule. Required when pattern is SPECIFIC_DAYS. |
stockAvailable |
integer (int32) |
No | Stock available applied to every schedule entry created from this request (for multi-day patterns the same value is applied to each generated day). Null means unlimited (no stock cap). |
Response: MenuScheduleResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Schedule entry ID | "550e8400-e29b-41d4-a716-446655440000" |
menuSectionId |
string (uuid) |
ID of the menu section | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the scheduled item | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date the item is scheduled for | "2026-01-15" |
scheduledViaCategoryId |
string (uuid) |
The category ID used to schedule this item, or null if scheduled directly | "550e8400-e29b-41d4-a716-446655440000" |
stockAvailable |
integer (int32) |
Stock available for this item on this day. Null means unlimited (no stock cap). | 40 |
recurrenceRule |
"SINGLE_DAY" | "EVERY_DAY" | "EVERY_WEEKDAY" | "SPECIFIC_DAYS" |
How this row was created — mirrors the request-time SchedulePattern. Lets the planner inspector show the correct repeat option when re-opened on a cell. | "SPECIFIC_DAYS" |
createdAt |
string (date-time) |
When the schedule entry was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the schedule entry was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zCreateMenuScheduleRequest } from '@smartsapp/sdk/staff';
import type { CreateMenuScheduleRequest } from '@smartsapp/sdk/staff';
const input: CreateMenuScheduleRequest = {
itemId: "550e8400-...",
categoryId: "550e8400-...",
excludeItemIds: [],
date: "2026-04-07"
};
const parsed = zCreateMenuScheduleRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data, error } = await canteenStaff.scheduleItems({
body: input,
path: { menuId: "...", sectionId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as MenuScheduleResponse[]
bulkDeleteScheduleEntries()¶
Bulk delete schedule entries by item or category and date range
DELETE /api/canteen/menus/{menuId}/sections/{sectionId}/schedules
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
sectionId |
string (uuid) |
path | Yes | |
itemId |
string (uuid) |
query | No | |
categoryId |
string (uuid) |
query | No | |
startDate |
string (date) |
query | Yes | |
endDate |
string (date) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (200)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.bulkDeleteScheduleEntries({
path: { menuId: "...", sectionId: "..." },
query: { itemId: "...", categoryId: "...", startDate: "2026-01-01" }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
deleteScheduleEntry()¶
Remove a single schedule entry
DELETE /api/canteen/menus/{menuId}/sections/{sectionId}/schedules/{scheduleId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
sectionId |
string (uuid) |
path | Yes | |
scheduleId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.deleteScheduleEntry({
path: { menuId: "...", sectionId: "...", scheduleId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
updateScheduleEntry()¶
Update a schedule entry (stock available for the day)
PATCH /api/canteen/menus/{menuId}/sections/{sectionId}/schedules/{scheduleId}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
sectionId |
string (uuid) |
path | Yes | |
scheduleId |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateMenuScheduleRequest
| Field | Type | Required | Description |
|---|---|---|---|
stockAvailable |
integer (int32) |
No | Stock available for this day. Null means unlimited (no stock cap). |
Response: MenuScheduleResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Schedule entry ID | "550e8400-e29b-41d4-a716-446655440000" |
menuSectionId |
string (uuid) |
ID of the menu section | "550e8400-e29b-41d4-a716-446655440000" |
itemId |
string (uuid) |
ID of the scheduled item | "550e8400-e29b-41d4-a716-446655440000" |
date |
string (date) |
Date the item is scheduled for | "2026-01-15" |
scheduledViaCategoryId |
string (uuid) |
The category ID used to schedule this item, or null if scheduled directly | "550e8400-e29b-41d4-a716-446655440000" |
stockAvailable |
integer (int32) |
Stock available for this item on this day. Null means unlimited (no stock cap). | 40 |
recurrenceRule |
"SINGLE_DAY" | "EVERY_DAY" | "EVERY_WEEKDAY" | "SPECIFIC_DAYS" |
How this row was created — mirrors the request-time SchedulePattern. Lets the planner inspector show the correct repeat option when re-opened on a cell. | "SPECIFIC_DAYS" |
createdAt |
string (date-time) |
When the schedule entry was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the schedule entry was last updated | "2026-01-15T10:30:00Z" |
Example:
import { canteenStaff, zUpdateMenuScheduleRequest } from '@smartsapp/sdk/staff';
import type { UpdateMenuScheduleRequest, MenuScheduleResponse } from '@smartsapp/sdk/staff';
const input: UpdateMenuScheduleRequest = {
stockAvailable: 40
};
const parsed = zUpdateMenuScheduleRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: menuSchedule, error } = await canteenStaff.updateScheduleEntry({
body: input,
path: { menuId: "...", sectionId: "...", scheduleId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// menuSchedule is typed as MenuScheduleResponse
bulkUpdateStock()¶
Apply a stock cap (or clear it) to many schedule entries at once
PATCH /api/canteen/menus/{menuId}/sections/{sectionId}/schedules/bulk-stock
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
menuId |
string (uuid) |
path | Yes | |
sectionId |
string (uuid) |
path | Yes | |
itemId |
string (uuid) |
query | No | |
categoryId |
string (uuid) |
query | No | |
startDate |
string (date) |
query | Yes | |
endDate |
string (date) |
query | Yes | |
stockAvailable |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.bulkUpdateStock({
path: { menuId: "...", sectionId: "..." },
query: { itemId: "...", categoryId: "...", startDate: "2026-01-01" }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
Student Directory¶
listStudentDirectory()¶
List students with canteen data (balance, tickets, menus, allergies)
GET /api/canteen/students
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
search |
string |
query | No | |
classroomId |
string (uuid) |
query | No | |
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: StudentDirectoryResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
directory |
PagedResponseStudentDirectoryRowResponse |
Generic wrapper for paginated API responses | |
stats |
StudentDirectoryStatsResponse |
KPI stats for the student directory header |
PagedResponseStudentDirectoryRowResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
content |
StudentDirectoryRowResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
StudentDirectoryStatsResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
totalStudents |
integer (int64) |
Total active students in the school | 338 |
activePlans |
integer (int64) |
Students with active meal ticket plans | 284 |
debtAlerts |
integer (int64) |
Students with negative Sika ID balance | 12 |
safetyFlags |
integer (int64) |
Students with recorded allergies or dietary restrictions | 8 |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { StudentDirectoryResponse } from '@smartsapp/sdk/staff';
const { data: studentDirectory, error } = await canteenStaff.listStudentDirectory({
query: { search: "...", classroomId: "...", page: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// studentDirectory is typed as StudentDirectoryResponse
Reports¶
getTicketsReport()¶
Get tickets report
GET /api/canteen/reports/tickets
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
dateFrom |
string (date) |
query | Yes | |
dateTo |
string (date) |
query | Yes | |
campusId |
string (uuid) |
query | No | |
compare |
boolean |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: TicketsReportResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
purchased |
integer (int64) |
Total tickets purchased | 120 |
redeemed |
integer (int64) |
Total tickets redeemed | 89 |
unredeemed |
integer (int64) |
Total tickets not yet redeemed | 31 |
breakdown |
TicketBreakdownEntry[] |
TicketBreakdownEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
ticketName |
string |
Name of the ticket type | "Weekly Lunch Pass" |
numberSold |
integer (int64) |
Number of tickets sold | 60 |
numberRedeemed |
integer (int64) |
Number of tickets redeemed | 48 |
redemptionRate |
number (double) |
Redemption rate as a decimal | 0.8 |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { TicketsReportResponse } from '@smartsapp/sdk/staff';
const { data: ticketsReport, error } = await canteenStaff.getTicketsReport({
query: { dateFrom: "2026-01-01", dateTo: "2026-01-01", campusId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// ticketsReport is typed as TicketsReportResponse
exportTicketsReport()¶
Export tickets report as Excel
GET /api/canteen/reports/tickets/export
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
dateFrom |
string (date) |
query | Yes | |
dateTo |
string (date) |
query | Yes | |
campusId |
string (uuid) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: string (byte) (200)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.exportTicketsReport({
query: { dateFrom: "2026-01-01", dateTo: "2026-01-01", campusId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
getSikaIdReport()¶
Get Sika ID report
GET /api/canteen/reports/sika-id
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
dateFrom |
string (date) |
query | Yes | |
dateTo |
string (date) |
query | Yes | |
campusId |
string (uuid) |
query | No | |
compare |
boolean |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: SikaIdReportResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
todayDeposit |
TodayDeposit |
||
outstandingDebt |
OutstandingDebt |
||
activeUsers |
ActiveUsers |
||
transactions |
SikaIdTransactionEntry[] |
Individual transactions within the period |
TodayDeposit fields:
| Field | Type | Description | Example |
|---|---|---|---|
amount |
number |
Deposit total | 8500.0 |
currency |
string |
ISO 4217 currency code | "GHS" |
OutstandingDebt fields:
| Field | Type | Description | Example |
|---|---|---|---|
amount |
number |
Debt total | 350.0 |
currency |
string |
ISO 4217 currency code | "GHS" |
recoveredTodayPercent |
number |
Percent of yesterday's debt recovered today | 0 |
ActiveUsers fields:
| Field | Type | Description | Example |
|---|---|---|---|
count |
integer (int32) |
Distinct students with Sika ID activity | 24 |
SikaIdTransactionEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string |
Transaction ID (backed by the canteen order ID) | "550e8400-e29b-41d4-a716-446655440000" |
studentId |
string |
Student UUID | "660e8400-e29b-41d4-a716-446655440000" |
studentName |
string |
Student full name | "Kwame Asante" |
studentGrade |
string |
Student grade / classroom name | "Grade 5" |
studentInitials |
string |
Two-letter initials derived from studentName | "KA" |
transactionType |
"posPurchase" | "walletTopUp" | "mealRedemption" | "refund" | "allocation" |
Frontend transaction-type enum | "mealRedemption" |
transactionTypeLabel |
string |
Human-readable transaction-type label | "Meal Redemption" |
platform |
"offlinePos" | "onlinePortal" | "mobileApp" | "canteenTerminal" |
Frontend platform enum | "canteenTerminal" |
platformLabel |
string |
Human-readable platform label | "Canteen Terminal" |
status |
string |
Raw order status (frontend maps to success/failed/pending) | "SERVED" |
amount |
number |
Transaction amount | 50.0 |
currency |
string |
ISO 4217 currency code | "GHS" |
date |
string (date-time) |
Transaction timestamp | "2026-03-01T10:15:00Z" |
processedBy |
string |
UUID of the user who processed the transaction |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { SikaIdReportResponse } from '@smartsapp/sdk/staff';
const { data: sikaIdReport, error } = await canteenStaff.getSikaIdReport({
query: { dateFrom: "2026-01-01", dateTo: "2026-01-01", campusId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// sikaIdReport is typed as SikaIdReportResponse
exportSikaIdReport()¶
Export Sika ID report as Excel
GET /api/canteen/reports/sika-id/export
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
dateFrom |
string (date) |
query | Yes | |
dateTo |
string (date) |
query | Yes | |
campusId |
string (uuid) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: string (byte) (200)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.exportSikaIdReport({
query: { dateFrom: "2026-01-01", dateTo: "2026-01-01", campusId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
getSalesReport()¶
Get sales report
GET /api/canteen/reports/sales
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
dateFrom |
string (date) |
query | Yes | |
dateTo |
string (date) |
query | Yes | |
personnelId |
string (uuid) |
query | No | |
campusId |
string (uuid) |
query | No | |
compare |
boolean |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: SalesReportResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
totalRevenue |
number |
Total revenue for the period | 4520.5 |
creditSales |
number |
Total credit sales | 1200.0 |
customerCount |
integer (int64) |
Number of unique customers | 78 |
currency |
string |
ISO currency code | "GHS" |
refunds |
RefundSummary |
Total refunds (cancelled orders) for the period | |
revenueChart |
RevenueBarEntry[] |
Revenue time-series bars for the period | |
salesByType |
SalesByTypeEntry[] |
Sales breakdown by payment method | |
transactions |
SalesTransactionEntry[] |
RefundSummary fields:
| Field | Type | Description | Example |
|---|---|---|---|
amount |
number |
Total refunded amount | 125.5 |
count |
integer (int64) |
Number of refunded (cancelled) orders | 3 |
RevenueBarEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
label |
string |
Bucket label (e.g. day, month) | "Mar" |
value |
number |
Revenue in this bucket | 4520.5 |
SalesByTypeEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
Payment method | "SIKA_ID" |
amount |
number |
Total amount for this payment method | 1850.0 |
SalesTransactionEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
orderNumber |
string |
Order reference number | "ORD-20260301-001" |
studentName |
string |
Name of the student | "Kwame Asante" |
studentGrade |
string |
Classroom / grade of the student | "Primary 5" |
payer |
string |
Primary guardian paying for the order | "Mary Asante" |
createdByName |
string |
Name of the staff who created the order | "Ama Mensah" |
amount |
number |
Transaction amount | 25.5 |
currency |
string |
ISO currency code | "GHS" |
paymentMode |
"SIKA_ID" | "ONLINE_PAYMENT" | "CREDIT" | "CASH" | "ALLOCATION" |
Payment method used | "SIKA_ID" |
itemSummary |
string |
Comma-separated list of items | "Jollof Rice x1, Chicken x1" |
date |
string (date) |
Date of the transaction | "2026-03-01" |
time |
string (date-time) |
Timestamp of the transaction | "2026-03-01T12:30:00Z" |
status |
"DRAFT" | "PAID" | "SERVED" | "PARTIALLY_SERVED" | "CANCELLED" |
Current order status | "DRAFT" |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { SalesReportResponse } from '@smartsapp/sdk/staff';
const { data: salesReport, error } = await canteenStaff.getSalesReport({
query: { dateFrom: "2026-01-01", dateTo: "2026-01-01", personnelId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// salesReport is typed as SalesReportResponse
exportSalesReport()¶
Export sales report as Excel
GET /api/canteen/reports/sales/export
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
dateFrom |
string (date) |
query | Yes | |
dateTo |
string (date) |
query | Yes | |
personnelId |
string (uuid) |
query | No | |
campusId |
string (uuid) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: string (byte) (200)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.exportSalesReport({
query: { dateFrom: "2026-01-01", dateTo: "2026-01-01", personnelId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
getOrdersReport()¶
Get orders report
GET /api/canteen/reports/orders
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
dateFrom |
string (date) |
query | Yes | |
dateTo |
string (date) |
query | Yes | |
personnelId |
string (uuid) |
query | No | |
campusId |
string (uuid) |
query | No | |
compare |
boolean |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: OrdersReportResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
orderCount |
integer (int64) |
Total number of orders | 152 |
totalAmount |
number |
Total order amount | 4520.5 |
currency |
string |
ISO currency code | "GHS" |
cancelledOrders |
integer (int64) |
Number of cancelled orders | 5 |
trend |
OrderVolumeTrendEntry[] |
||
itemRanking |
ItemPerformanceEntry[] |
||
orderFrequency |
OrderFrequencyBucket[] |
Order frequency breakdown by time-of-day slot |
OrderVolumeTrendEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
date |
string (date) |
Date | "2026-03-01" |
count |
integer (int64) |
Number of orders on this date | 24 |
ItemPerformanceEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
itemName |
string |
Name of the menu item | "Jollof Rice" |
orderCount |
integer (int64) |
Total orders for this item | 45 |
revenue |
number |
Total revenue from this item | 675.0 |
OrderFrequencyBucket fields:
| Field | Type | Description | Example |
|---|---|---|---|
timeSlot |
string |
Time slot label | "11am-1pm" |
preOrders |
integer (int64) |
Number of pre-orders (ticket-based) in this slot | 18 |
walkIns |
integer (int64) |
Number of walk-ins (POS) in this slot | 25 |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { OrdersReportResponse } from '@smartsapp/sdk/staff';
const { data: ordersReport, error } = await canteenStaff.getOrdersReport({
query: { dateFrom: "2026-01-01", dateTo: "2026-01-01", personnelId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// ordersReport is typed as OrdersReportResponse
exportOrdersReport()¶
Export orders report as Excel
GET /api/canteen/reports/orders/export
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
dateFrom |
string (date) |
query | Yes | |
dateTo |
string (date) |
query | Yes | |
personnelId |
string (uuid) |
query | No | |
campusId |
string (uuid) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: string (byte) (200)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.exportOrdersReport({
query: { dateFrom: "2026-01-01", dateTo: "2026-01-01", personnelId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
Dashboard¶
getCanteenDashboard()¶
Get dashboard metrics for a date range
GET /api/canteen/dashboard
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
from |
string (date) |
query | No | |
to |
string (date) |
query | No | |
campusId |
string (uuid) |
query | No | |
cateringServiceId |
string (uuid) |
query | No | |
personnelId |
string (uuid) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: DashboardResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
totalStudentsOnFeedingList |
integer (int64) |
Total distinct students on the feeding list | |
studentsPresentOnFeedingList |
integer (int64) |
Students marked present and on the feeding list | |
studentsAbsentOnFeedingList |
integer (int64) |
Students marked absent but on the feeding list | |
totalMeals |
integer (int64) |
Total meals to be redeemed (non-cancelled orders) | |
mealsRedeemed |
integer (int64) |
Meals with status SERVED | |
mealsUnredeemed |
integer (int64) |
Meals with status PAID or PARTIALLY_SERVED | |
ordersByItem |
OrderByItemEntry[] |
Order breakdown by item | |
ordersByCategory |
OrderByCategoryEntry[] |
Order breakdown by category |
OrderByItemEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
itemName |
string |
Name of the item | |
categoryId |
string (uuid) |
Category ID of the item | "550e8400-..." |
imageUrl |
string |
URL of the item image, if set | |
totalQuantity |
integer (int32) |
Total quantity ordered across all variants | |
variants |
VariantQuantityEntry[] |
Breakdown by variant (empty list if item has no variants) |
OrderByCategoryEntry fields:
| Field | Type | Description | Example |
|---|---|---|---|
categoryId |
string (uuid) |
ID of the item category | "550e8400-..." |
categoryName |
string |
Name of the item category | "Beverages" |
count |
integer (int32) |
Number of orders in this category | 42 |
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
import type { DashboardResponse } from '@smartsapp/sdk/staff';
const { data: dashboard, error } = await canteenStaff.getCanteenDashboard({
query: { from: "2026-01-01", to: "2026-01-01", campusId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// dashboard is typed as DashboardResponse
exportDashboardOrders()¶
Export orders for a date range as Excel
GET /api/canteen/dashboard/export
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
from |
string (date) |
query | No | |
to |
string (date) |
query | No | |
campusId |
string (uuid) |
query | No | |
cateringServiceId |
string (uuid) |
query | No | |
personnelId |
string (uuid) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: string (byte) (200)
Example:
import { canteenStaff } from '@smartsapp/sdk/staff';
const { data, error } = await canteenStaff.exportDashboardOrders({
query: { from: "2026-01-01", to: "2026-01-01", campusId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
Academic Report (academicReport)¶
Not yet implemented
This module is planned but not yet available.
Invoice (invoice)¶
Not yet implemented
This module is planned but not yet available.
School (school)¶
Students¶
getStudent()¶
Get a student by ID
GET /api/school/students/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: StudentResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Student ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school the student belongs to | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the student's classroom | "550e8400-e29b-41d4-a716-446655440000" |
familyId |
string (uuid) |
ID of the student's family | "550e8400-e29b-41d4-a716-446655440000" |
studentIdNumber |
string |
School-assigned student ID number | "STU-2026-001" |
firstName |
string |
Student's first name | "Kofi" |
middleName |
string |
Student's middle name | "Mensah" |
lastName |
string |
Student's last name | "Asante" |
dateOfBirth |
string (date) |
Student's date of birth | "2015-03-20" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Student's gender | "MALE" |
profilePhotoUrl |
string |
URL of the student's profile photo | "https://storage.example.com/photos/student.jpg" |
nationality |
string |
Student's nationality | "Ghanaian" |
religion |
string |
Student's religion | "Christian" |
bloodGroup |
string |
Student's blood group | "O+" |
medicalNotes |
string |
Medical notes or allergies | "Allergic to peanuts" |
enrollmentDate |
string (date) |
Date the student enrolled | "2026-01-10" |
status |
"ACTIVE" | "INACTIVE" | "GRADUATED" | "WITHDRAWN" | "SUSPENDED" |
Current enrollment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { StudentResponse } from '@smartsapp/sdk/staff';
const { data: student, error } = await school.getStudent({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// student is typed as StudentResponse
updateStudent()¶
Update a student
PUT /api/school/students/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateStudentRequest
| Field | Type | Required | Description |
|---|---|---|---|
schoolId |
string (uuid) |
No | ID of the school |
classroomId |
string (uuid) |
No | ID of the classroom |
familyId |
string (uuid) |
No | ID of the family (optional) |
studentIdNumber |
string |
No | Student identification number |
firstName |
string |
No | First name of the student |
middleName |
string |
No | Middle name of the student |
lastName |
string |
No | Last name of the student |
dateOfBirth |
string (date) |
No | Date of birth |
gender |
"MALE" | "FEMALE" | "OTHER" |
No | Gender of the student |
profilePhotoUrl |
string |
No | URL of the profile photo |
nationality |
string |
No | Nationality of the student |
religion |
string |
No | Religion of the student |
bloodGroup |
string |
No | Blood group of the student |
medicalNotes |
string |
No | Medical notes for the student |
enrollmentDate |
string (date) |
No | Date of enrollment |
status |
"ACTIVE" | "INACTIVE" | "GRADUATED" | "WITHDRAWN" | "SUSPENDED" |
No | Status of the student |
Response: StudentResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Student ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school the student belongs to | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the student's classroom | "550e8400-e29b-41d4-a716-446655440000" |
familyId |
string (uuid) |
ID of the student's family | "550e8400-e29b-41d4-a716-446655440000" |
studentIdNumber |
string |
School-assigned student ID number | "STU-2026-001" |
firstName |
string |
Student's first name | "Kofi" |
middleName |
string |
Student's middle name | "Mensah" |
lastName |
string |
Student's last name | "Asante" |
dateOfBirth |
string (date) |
Student's date of birth | "2015-03-20" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Student's gender | "MALE" |
profilePhotoUrl |
string |
URL of the student's profile photo | "https://storage.example.com/photos/student.jpg" |
nationality |
string |
Student's nationality | "Ghanaian" |
religion |
string |
Student's religion | "Christian" |
bloodGroup |
string |
Student's blood group | "O+" |
medicalNotes |
string |
Medical notes or allergies | "Allergic to peanuts" |
enrollmentDate |
string (date) |
Date the student enrolled | "2026-01-10" |
status |
"ACTIVE" | "INACTIVE" | "GRADUATED" | "WITHDRAWN" | "SUSPENDED" |
Current enrollment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateStudentRequest } from '@smartsapp/sdk/staff';
import type { UpdateStudentRequest, StudentResponse } from '@smartsapp/sdk/staff';
const input: UpdateStudentRequest = {
schoolId: "550e8400-e29b-41d4-a716-446655440000",
classroomId: "550e8400-e29b-41d4-a716-446655440001",
familyId: "550e8400-e29b-41d4-a716-446655440002",
studentIdNumber: "STU-2024-001"
};
const parsed = zUpdateStudentRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: student, error } = await school.updateStudent({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// student is typed as StudentResponse
deleteStudent()¶
Delete a student
DELETE /api/school/students/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteStudent({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listStudents()¶
List students with pagination
GET /api/school/students
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseStudentResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
StudentResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
StudentResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Student ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school the student belongs to | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the student's classroom | "550e8400-e29b-41d4-a716-446655440000" |
familyId |
string (uuid) |
ID of the student's family | "550e8400-e29b-41d4-a716-446655440000" |
studentIdNumber |
string |
School-assigned student ID number | "STU-2026-001" |
firstName |
string |
Student's first name | "Kofi" |
middleName |
string |
Student's middle name | "Mensah" |
lastName |
string |
Student's last name | "Asante" |
dateOfBirth |
string (date) |
Student's date of birth | "2015-03-20" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Student's gender | "MALE" |
profilePhotoUrl |
string |
URL of the student's profile photo | "https://storage.example.com/photos/student.jpg" |
nationality |
string |
Student's nationality | "Ghanaian" |
religion |
string |
Student's religion | "Christian" |
bloodGroup |
string |
Student's blood group | "O+" |
medicalNotes |
string |
Medical notes or allergies | "Allergic to peanuts" |
enrollmentDate |
string (date) |
Date the student enrolled | "2026-01-10" |
status |
"ACTIVE" | "INACTIVE" | "GRADUATED" | "WITHDRAWN" | "SUSPENDED" |
Current enrollment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseStudentResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listStudents({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const students = result.content; // StudentResponse[]
const { page, totalPages, totalElements, last } = result;
createStudent()¶
Create a new student
POST /api/school/students
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateStudentRequest
| Field | Type | Required | Description |
|---|---|---|---|
schoolId |
string (uuid) |
Yes | ID of the school |
classroomId |
string (uuid) |
Yes | ID of the classroom |
familyId |
string (uuid) |
No | ID of the family (optional) |
studentIdNumber |
string |
No | Student identification number |
firstName |
string |
Yes | First name of the student |
middleName |
string |
No | Middle name of the student |
lastName |
string |
Yes | Last name of the student |
dateOfBirth |
string (date) |
No | Date of birth |
gender |
"MALE" | "FEMALE" | "OTHER" |
No | Gender of the student |
profilePhotoUrl |
string |
No | URL of the profile photo |
nationality |
string |
No | Nationality of the student |
religion |
string |
No | Religion of the student |
bloodGroup |
string |
No | Blood group of the student |
medicalNotes |
string |
No | Medical notes for the student |
enrollmentDate |
string (date) |
No | Date of enrollment |
Response: StudentResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Student ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school the student belongs to | "550e8400-e29b-41d4-a716-446655440000" |
classroomId |
string (uuid) |
ID of the student's classroom | "550e8400-e29b-41d4-a716-446655440000" |
familyId |
string (uuid) |
ID of the student's family | "550e8400-e29b-41d4-a716-446655440000" |
studentIdNumber |
string |
School-assigned student ID number | "STU-2026-001" |
firstName |
string |
Student's first name | "Kofi" |
middleName |
string |
Student's middle name | "Mensah" |
lastName |
string |
Student's last name | "Asante" |
dateOfBirth |
string (date) |
Student's date of birth | "2015-03-20" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Student's gender | "MALE" |
profilePhotoUrl |
string |
URL of the student's profile photo | "https://storage.example.com/photos/student.jpg" |
nationality |
string |
Student's nationality | "Ghanaian" |
religion |
string |
Student's religion | "Christian" |
bloodGroup |
string |
Student's blood group | "O+" |
medicalNotes |
string |
Medical notes or allergies | "Allergic to peanuts" |
enrollmentDate |
string (date) |
Date the student enrolled | "2026-01-10" |
status |
"ACTIVE" | "INACTIVE" | "GRADUATED" | "WITHDRAWN" | "SUSPENDED" |
Current enrollment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateStudentRequest } from '@smartsapp/sdk/staff';
import type { CreateStudentRequest, StudentResponse } from '@smartsapp/sdk/staff';
const input: CreateStudentRequest = {
schoolId: "550e8400-e29b-41d4-a716-446655440000",
classroomId: "550e8400-e29b-41d4-a716-446655440001",
familyId: "550e8400-e29b-41d4-a716-446655440002",
studentIdNumber: "STU-2024-001"
};
const parsed = zCreateStudentRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: student, error } = await school.createStudent({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// student is typed as StudentResponse
Staff¶
getStaffMember()¶
Get a staff member by ID
GET /api/school/staff/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: StaffResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Staff member ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus the staff member is assigned to | "550e8400-e29b-41d4-a716-446655440000" |
staffIdNumber |
string |
Staff ID number | "STF-2026-001" |
firstName |
string |
First name | "Abena" |
middleName |
string |
Middle name | "Osei" |
lastName |
string |
Last name | "Mensah" |
email |
string |
Email address | "[email protected]" |
phone |
string |
Phone number | "+233501234567" |
dateOfBirth |
string (date) |
Date of birth | "1985-06-15" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Gender | "MALE" |
profilePhotoUrl |
string |
URL of the staff member's profile photo | "https://storage.example.com/photos/staff.jpg" |
role |
"TEACHER" | "ADMINISTRATOR" | "HEADMASTER" | "SUPPORT" | "OTHER" |
Staff role: TEACHER, ADMIN, PRINCIPAL, etc. | "TEACHER" |
department |
string |
Department name | "Mathematics" |
employmentType |
"FULL_TIME" | "PART_TIME" | "CONTRACT" |
Employment type: FULL_TIME, PART_TIME, CONTRACT | "FULL_TIME" |
hireDate |
string (date) |
Date the staff member was hired | "2024-09-01" |
status |
"ACTIVE" | "INACTIVE" | "ON_LEAVE" | "TERMINATED" |
Employment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { StaffResponse } from '@smartsapp/sdk/staff';
const { data: staff, error } = await school.getStaffMember({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// staff is typed as StaffResponse
updateStaffMember()¶
Update a staff member
PUT /api/school/staff/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateStaffRequest
| Field | Type | Required | Description |
|---|---|---|---|
schoolId |
string (uuid) |
No | ID of the school |
campusId |
string (uuid) |
No | ID of the campus (optional) |
staffIdNumber |
string |
No | Staff identification number |
firstName |
string |
No | First name of the staff member |
middleName |
string |
No | Middle name of the staff member |
lastName |
string |
No | Last name of the staff member |
email |
string |
No | Email address |
phone |
string |
No | Phone number |
dateOfBirth |
string (date) |
No | Date of birth |
gender |
"MALE" | "FEMALE" | "OTHER" |
No | Gender of the staff member |
profilePhotoUrl |
string |
No | URL of the profile photo |
role |
"TEACHER" | "ADMINISTRATOR" | "HEADMASTER" | "SUPPORT" | "OTHER" |
No | Role of the staff member |
department |
string |
No | Department of the staff member |
employmentType |
"FULL_TIME" | "PART_TIME" | "CONTRACT" |
No | Employment type |
hireDate |
string (date) |
No | Date of hire |
status |
"ACTIVE" | "INACTIVE" | "ON_LEAVE" | "TERMINATED" |
No | Status of the staff member |
Response: StaffResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Staff member ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus the staff member is assigned to | "550e8400-e29b-41d4-a716-446655440000" |
staffIdNumber |
string |
Staff ID number | "STF-2026-001" |
firstName |
string |
First name | "Abena" |
middleName |
string |
Middle name | "Osei" |
lastName |
string |
Last name | "Mensah" |
email |
string |
Email address | "[email protected]" |
phone |
string |
Phone number | "+233501234567" |
dateOfBirth |
string (date) |
Date of birth | "1985-06-15" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Gender | "MALE" |
profilePhotoUrl |
string |
URL of the staff member's profile photo | "https://storage.example.com/photos/staff.jpg" |
role |
"TEACHER" | "ADMINISTRATOR" | "HEADMASTER" | "SUPPORT" | "OTHER" |
Staff role: TEACHER, ADMIN, PRINCIPAL, etc. | "TEACHER" |
department |
string |
Department name | "Mathematics" |
employmentType |
"FULL_TIME" | "PART_TIME" | "CONTRACT" |
Employment type: FULL_TIME, PART_TIME, CONTRACT | "FULL_TIME" |
hireDate |
string (date) |
Date the staff member was hired | "2024-09-01" |
status |
"ACTIVE" | "INACTIVE" | "ON_LEAVE" | "TERMINATED" |
Employment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateStaffRequest } from '@smartsapp/sdk/staff';
import type { UpdateStaffRequest, StaffResponse } from '@smartsapp/sdk/staff';
const input: UpdateStaffRequest = {
schoolId: "550e8400-e29b-41d4-a716-446655440000",
campusId: "550e8400-e29b-41d4-a716-446655440001",
staffIdNumber: "STF-2024-001",
firstName: "Jane"
};
const parsed = zUpdateStaffRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: staff, error } = await school.updateStaffMember({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// staff is typed as StaffResponse
deleteStaffMember()¶
Delete a staff member
DELETE /api/school/staff/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteStaffMember({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listStaff()¶
List staff with pagination
GET /api/school/staff
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseStaffResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
StaffResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
StaffResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Staff member ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus the staff member is assigned to | "550e8400-e29b-41d4-a716-446655440000" |
staffIdNumber |
string |
Staff ID number | "STF-2026-001" |
firstName |
string |
First name | "Abena" |
middleName |
string |
Middle name | "Osei" |
lastName |
string |
Last name | "Mensah" |
email |
string |
Email address | "[email protected]" |
phone |
string |
Phone number | "+233501234567" |
dateOfBirth |
string (date) |
Date of birth | "1985-06-15" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Gender | "MALE" |
profilePhotoUrl |
string |
URL of the staff member's profile photo | "https://storage.example.com/photos/staff.jpg" |
role |
"TEACHER" | "ADMINISTRATOR" | "HEADMASTER" | "SUPPORT" | "OTHER" |
Staff role: TEACHER, ADMIN, PRINCIPAL, etc. | "TEACHER" |
department |
string |
Department name | "Mathematics" |
employmentType |
"FULL_TIME" | "PART_TIME" | "CONTRACT" |
Employment type: FULL_TIME, PART_TIME, CONTRACT | "FULL_TIME" |
hireDate |
string (date) |
Date the staff member was hired | "2024-09-01" |
status |
"ACTIVE" | "INACTIVE" | "ON_LEAVE" | "TERMINATED" |
Employment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseStaffResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listStaff({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const staffs = result.content; // StaffResponse[]
const { page, totalPages, totalElements, last } = result;
createStaff()¶
Create a new staff member
POST /api/school/staff
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateStaffRequest
| Field | Type | Required | Description |
|---|---|---|---|
schoolId |
string (uuid) |
Yes | ID of the school |
campusId |
string (uuid) |
No | ID of the campus (optional) |
staffIdNumber |
string |
No | Staff identification number |
firstName |
string |
Yes | First name of the staff member |
middleName |
string |
No | Middle name of the staff member |
lastName |
string |
Yes | Last name of the staff member |
email |
string |
No | Email address |
phone |
string |
No | Phone number |
dateOfBirth |
string (date) |
No | Date of birth |
gender |
"MALE" | "FEMALE" | "OTHER" |
No | Gender of the staff member |
profilePhotoUrl |
string |
No | URL of the profile photo |
role |
"TEACHER" | "ADMINISTRATOR" | "HEADMASTER" | "SUPPORT" | "OTHER" |
No | Role of the staff member |
department |
string |
No | Department of the staff member |
employmentType |
"FULL_TIME" | "PART_TIME" | "CONTRACT" |
No | Employment type |
hireDate |
string (date) |
No | Date of hire |
Response: StaffResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Staff member ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus the staff member is assigned to | "550e8400-e29b-41d4-a716-446655440000" |
staffIdNumber |
string |
Staff ID number | "STF-2026-001" |
firstName |
string |
First name | "Abena" |
middleName |
string |
Middle name | "Osei" |
lastName |
string |
Last name | "Mensah" |
email |
string |
Email address | "[email protected]" |
phone |
string |
Phone number | "+233501234567" |
dateOfBirth |
string (date) |
Date of birth | "1985-06-15" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Gender | "MALE" |
profilePhotoUrl |
string |
URL of the staff member's profile photo | "https://storage.example.com/photos/staff.jpg" |
role |
"TEACHER" | "ADMINISTRATOR" | "HEADMASTER" | "SUPPORT" | "OTHER" |
Staff role: TEACHER, ADMIN, PRINCIPAL, etc. | "TEACHER" |
department |
string |
Department name | "Mathematics" |
employmentType |
"FULL_TIME" | "PART_TIME" | "CONTRACT" |
Employment type: FULL_TIME, PART_TIME, CONTRACT | "FULL_TIME" |
hireDate |
string (date) |
Date the staff member was hired | "2024-09-01" |
status |
"ACTIVE" | "INACTIVE" | "ON_LEAVE" | "TERMINATED" |
Employment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateStaffRequest } from '@smartsapp/sdk/staff';
import type { CreateStaffRequest, StaffResponse } from '@smartsapp/sdk/staff';
const input: CreateStaffRequest = {
schoolId: "550e8400-e29b-41d4-a716-446655440000",
campusId: "550e8400-e29b-41d4-a716-446655440001",
staffIdNumber: "STF-2024-001",
firstName: "Jane"
};
const parsed = zCreateStaffRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: staff, error } = await school.createStaff({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// staff is typed as StaffResponse
Sections¶
getSection()¶
Get a section by ID
GET /api/school/sections/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: SectionResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Section ID | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus this section belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the section | "Primary School" |
code |
string |
Short unique code for the section | "PRI" |
levelOrder |
integer (int32) |
Sort order within the campus | 1 |
description |
string |
Description of the section | "Grades 1 through 6" |
isActive |
boolean |
Whether the section is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { SectionResponse } from '@smartsapp/sdk/staff';
const { data: section, error } = await school.getSection({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// section is typed as SectionResponse
updateSection()¶
Update a section
PUT /api/school/sections/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateSectionRequest
| Field | Type | Required | Description |
|---|---|---|---|
campusId |
string (uuid) |
No | ID of the campus this section belongs to |
name |
string |
No | Name of the section |
code |
string |
No | Unique code for the section |
levelOrder |
integer (int32) |
No | Order level of the section |
description |
string |
No | Description of the section |
isActive |
boolean |
No | Whether the section is active |
Response: SectionResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Section ID | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus this section belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the section | "Primary School" |
code |
string |
Short unique code for the section | "PRI" |
levelOrder |
integer (int32) |
Sort order within the campus | 1 |
description |
string |
Description of the section | "Grades 1 through 6" |
isActive |
boolean |
Whether the section is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateSectionRequest } from '@smartsapp/sdk/staff';
import type { UpdateSectionRequest, SectionResponse } from '@smartsapp/sdk/staff';
const input: UpdateSectionRequest = {
campusId: "550e8400-e29b-41d4-a716-446655440000",
name: "Primary",
code: "PRI",
levelOrder: 1
};
const parsed = zUpdateSectionRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: section, error } = await school.updateSection({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// section is typed as SectionResponse
deleteSection()¶
Delete a section
DELETE /api/school/sections/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteSection({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listSections()¶
List sections with pagination
GET /api/school/sections
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseSectionResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
SectionResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
SectionResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Section ID | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus this section belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the section | "Primary School" |
code |
string |
Short unique code for the section | "PRI" |
levelOrder |
integer (int32) |
Sort order within the campus | 1 |
description |
string |
Description of the section | "Grades 1 through 6" |
isActive |
boolean |
Whether the section is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseSectionResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listSections({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const sections = result.content; // SectionResponse[]
const { page, totalPages, totalElements, last } = result;
createSection()¶
Create a new section
POST /api/school/sections
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateSectionRequest
| Field | Type | Required | Description |
|---|---|---|---|
campusId |
string (uuid) |
Yes | ID of the campus this section belongs to |
name |
string |
Yes | Name of the section |
code |
string |
No | Unique code for the section |
levelOrder |
integer (int32) |
No | Order level of the section |
description |
string |
No | Description of the section |
Response: SectionResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Section ID | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus this section belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the section | "Primary School" |
code |
string |
Short unique code for the section | "PRI" |
levelOrder |
integer (int32) |
Sort order within the campus | 1 |
description |
string |
Description of the section | "Grades 1 through 6" |
isActive |
boolean |
Whether the section is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateSectionRequest } from '@smartsapp/sdk/staff';
import type { CreateSectionRequest, SectionResponse } from '@smartsapp/sdk/staff';
const input: CreateSectionRequest = {
campusId: "550e8400-e29b-41d4-a716-446655440000",
name: "Primary",
code: "PRI",
levelOrder: 1
};
const parsed = zCreateSectionRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: section, error } = await school.createSection({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// section is typed as SectionResponse
Schools¶
getSchool()¶
Get a school by ID
GET /api/school/schools/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: SchoolResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
School ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the school | "Lincoln International Academy" |
code |
string |
Short unique code for the school | "LIA" |
logoUrl |
string |
URL of the school logo | "https://storage.example.com/logos/lia.png" |
address |
string |
Physical address of the school | 12 |
phone |
string |
Contact phone number | "+233302123456" |
email |
string |
Contact email address | "[email protected]" |
website |
string |
School website URL | "https://lincolnacademy.edu" |
accreditationNumber |
string |
Government accreditation number | "ACC-2024-00123" |
defaultCurrency |
string |
Default currency code for the school | "GHS" |
isActive |
boolean |
Whether the school is currently active | |
createdAt |
string (date-time) |
When the school was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the school was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { SchoolResponse } from '@smartsapp/sdk/staff';
const { data: school, error } = await school.getSchool({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// school is typed as SchoolResponse
updateSchool()¶
Update a school
PUT /api/school/schools/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateSchoolRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
No | Official name of the school |
code |
string |
No | Unique code for the school |
logoUrl |
string |
No | URL of the school logo |
address |
string |
No | Physical address of the school |
phone |
string |
No | Contact phone number |
email |
string |
No | Contact email address |
website |
string |
No | School website URL |
accreditationNumber |
string |
No | Accreditation number |
defaultCurrency |
string |
No | ISO 4217 currency code for all financial operations |
isActive |
boolean |
No | Whether the school is active |
Response: SchoolResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
School ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the school | "Lincoln International Academy" |
code |
string |
Short unique code for the school | "LIA" |
logoUrl |
string |
URL of the school logo | "https://storage.example.com/logos/lia.png" |
address |
string |
Physical address of the school | 12 |
phone |
string |
Contact phone number | "+233302123456" |
email |
string |
Contact email address | "[email protected]" |
website |
string |
School website URL | "https://lincolnacademy.edu" |
accreditationNumber |
string |
Government accreditation number | "ACC-2024-00123" |
defaultCurrency |
string |
Default currency code for the school | "GHS" |
isActive |
boolean |
Whether the school is currently active | |
createdAt |
string (date-time) |
When the school was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the school was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateSchoolRequest } from '@smartsapp/sdk/staff';
import type { UpdateSchoolRequest, SchoolResponse } from '@smartsapp/sdk/staff';
const input: UpdateSchoolRequest = {
name: "Accra Academy",
code: "ACAD",
logoUrl: "https://example.com/logo.png",
address: 123
};
const parsed = zUpdateSchoolRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: school, error } = await school.updateSchool({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// school is typed as SchoolResponse
deleteSchool()¶
Delete a school
DELETE /api/school/schools/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteSchool({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listSchools()¶
List schools with pagination
GET /api/school/schools
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseSchoolResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
SchoolResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
SchoolResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
School ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the school | "Lincoln International Academy" |
code |
string |
Short unique code for the school | "LIA" |
logoUrl |
string |
URL of the school logo | "https://storage.example.com/logos/lia.png" |
address |
string |
Physical address of the school | 12 |
phone |
string |
Contact phone number | "+233302123456" |
email |
string |
Contact email address | "[email protected]" |
website |
string |
School website URL | "https://lincolnacademy.edu" |
accreditationNumber |
string |
Government accreditation number | "ACC-2024-00123" |
defaultCurrency |
string |
Default currency code for the school | "GHS" |
isActive |
boolean |
Whether the school is currently active | |
createdAt |
string (date-time) |
When the school was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the school was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseSchoolResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listSchools({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const schools = result.content; // SchoolResponse[]
const { page, totalPages, totalElements, last } = result;
createSchool()¶
Create a new school
POST /api/school/schools
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateSchoolRequest
| Field | Type | Required | Description |
|---|---|---|---|
name |
string |
Yes | Official name of the school |
code |
string |
No | Unique code for the school |
logoUrl |
string |
No | URL of the school logo |
address |
string |
No | Physical address of the school |
phone |
string |
No | Contact phone number |
email |
string |
No | Contact email address |
website |
string |
No | School website URL |
accreditationNumber |
string |
No | Accreditation number |
defaultCurrency |
string |
No | ISO 4217 currency code for all financial operations |
Response: SchoolResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
School ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the school | "Lincoln International Academy" |
code |
string |
Short unique code for the school | "LIA" |
logoUrl |
string |
URL of the school logo | "https://storage.example.com/logos/lia.png" |
address |
string |
Physical address of the school | 12 |
phone |
string |
Contact phone number | "+233302123456" |
email |
string |
Contact email address | "[email protected]" |
website |
string |
School website URL | "https://lincolnacademy.edu" |
accreditationNumber |
string |
Government accreditation number | "ACC-2024-00123" |
defaultCurrency |
string |
Default currency code for the school | "GHS" |
isActive |
boolean |
Whether the school is currently active | |
createdAt |
string (date-time) |
When the school was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the school was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateSchoolRequest } from '@smartsapp/sdk/staff';
import type { CreateSchoolRequest, SchoolResponse } from '@smartsapp/sdk/staff';
const input: CreateSchoolRequest = {
name: "Accra Academy",
code: "ACAD",
logoUrl: "https://example.com/logo.png",
address: 123
};
const parsed = zCreateSchoolRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: school, error } = await school.createSchool({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// school is typed as SchoolResponse
Guardians¶
getGuardian()¶
Get a guardian by ID
GET /api/school/guardians/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: GuardianResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Guardian ID | "550e8400-e29b-41d4-a716-446655440000" |
familyId |
string (uuid) |
ID of the family this guardian belongs to | "550e8400-e29b-41d4-a716-446655440000" |
guardianType |
"FATHER" | "MOTHER" | "STEPFATHER" | "STEPMOTHER" | "GRANDFATHER" | "GRANDMOTHER" | "UNCLE" | "AUNT" | "OLDER_SIBLING" | "LEGAL_GUARDIAN" | "FOSTER_PARENT" | "RELATIVE" | "FAMILY_FRIEND" | "OTHER" |
Type of guardian: FATHER, MOTHER, LEGAL_GUARDIAN, OTHER | "FATHER" |
firstName |
string |
Guardian's first name | "Kwame" |
middleName |
string |
Guardian's middle name | "Mensah" |
lastName |
string |
Guardian's last name | "Asante" |
email |
string |
Guardian's email address | "[email protected]" |
phonePrimary |
string |
Primary phone number | "+233501234567" |
phoneSecondary |
string |
Secondary phone number | "+233509876543" |
occupation |
string |
Guardian's occupation | "Software Engineer" |
employer |
string |
Guardian's employer | "TechCorp Ltd" |
address |
string |
Guardian's residential address | 15 |
nationalId |
string |
National identification number | "GHA-123456789" |
profilePhotoUrl |
string |
URL of the guardian's profile photo | "https://storage.example.com/photos/guardian.jpg" |
isEmergencyContact |
boolean |
Whether this guardian is an emergency contact | |
canPickupStudent |
boolean |
Whether this guardian is authorised to pick up the student | |
isPrimaryContact |
boolean |
Whether this guardian is the primary contact for the family | |
isActive |
boolean |
Whether this guardian record is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { GuardianResponse } from '@smartsapp/sdk/staff';
const { data: guardian, error } = await school.getGuardian({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// guardian is typed as GuardianResponse
updateGuardian()¶
Update a guardian
PUT /api/school/guardians/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateGuardianRequest
| Field | Type | Required | Description |
|---|---|---|---|
familyId |
string (uuid) |
No | ID of the family (optional) |
guardianType |
"FATHER" | "MOTHER" | "STEPFATHER" | "STEPMOTHER" | "GRANDFATHER" | "GRANDMOTHER" | "UNCLE" | "AUNT" | "OLDER_SIBLING" | "LEGAL_GUARDIAN" | "FOSTER_PARENT" | "RELATIVE" | "FAMILY_FRIEND" | "OTHER" |
No | Type of guardian |
firstName |
string |
No | First name of the guardian |
middleName |
string |
No | Middle name of the guardian |
lastName |
string |
No | Last name of the guardian |
email |
string |
No | Email address |
phonePrimary |
string |
No | Primary phone number |
phoneSecondary |
string |
No | Secondary phone number |
occupation |
string |
No | Occupation of the guardian |
employer |
string |
No | Employer of the guardian |
address |
string |
No | Address of the guardian |
nationalId |
string |
No | National ID number |
profilePhotoUrl |
string |
No | URL of the profile photo |
isEmergencyContact |
boolean |
No | Whether this guardian is an emergency contact |
canPickupStudent |
boolean |
No | Whether this guardian can pick up the student |
isPrimaryContact |
boolean |
No | Whether this is the primary contact |
isActive |
boolean |
No | Whether the guardian is active |
Response: GuardianResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Guardian ID | "550e8400-e29b-41d4-a716-446655440000" |
familyId |
string (uuid) |
ID of the family this guardian belongs to | "550e8400-e29b-41d4-a716-446655440000" |
guardianType |
"FATHER" | "MOTHER" | "STEPFATHER" | "STEPMOTHER" | "GRANDFATHER" | "GRANDMOTHER" | "UNCLE" | "AUNT" | "OLDER_SIBLING" | "LEGAL_GUARDIAN" | "FOSTER_PARENT" | "RELATIVE" | "FAMILY_FRIEND" | "OTHER" |
Type of guardian: FATHER, MOTHER, LEGAL_GUARDIAN, OTHER | "FATHER" |
firstName |
string |
Guardian's first name | "Kwame" |
middleName |
string |
Guardian's middle name | "Mensah" |
lastName |
string |
Guardian's last name | "Asante" |
email |
string |
Guardian's email address | "[email protected]" |
phonePrimary |
string |
Primary phone number | "+233501234567" |
phoneSecondary |
string |
Secondary phone number | "+233509876543" |
occupation |
string |
Guardian's occupation | "Software Engineer" |
employer |
string |
Guardian's employer | "TechCorp Ltd" |
address |
string |
Guardian's residential address | 15 |
nationalId |
string |
National identification number | "GHA-123456789" |
profilePhotoUrl |
string |
URL of the guardian's profile photo | "https://storage.example.com/photos/guardian.jpg" |
isEmergencyContact |
boolean |
Whether this guardian is an emergency contact | |
canPickupStudent |
boolean |
Whether this guardian is authorised to pick up the student | |
isPrimaryContact |
boolean |
Whether this guardian is the primary contact for the family | |
isActive |
boolean |
Whether this guardian record is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateGuardianRequest } from '@smartsapp/sdk/staff';
import type { UpdateGuardianRequest, GuardianResponse } from '@smartsapp/sdk/staff';
const input: UpdateGuardianRequest = {
familyId: "550e8400-e29b-41d4-a716-446655440000",
guardianType: "FATHER",
firstName: "James",
middleName: "Robert"
};
const parsed = zUpdateGuardianRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: guardian, error } = await school.updateGuardian({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// guardian is typed as GuardianResponse
deleteGuardian()¶
Delete a guardian
DELETE /api/school/guardians/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteGuardian({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listGuardians()¶
List guardians with pagination
GET /api/school/guardians
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseGuardianResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
GuardianResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
GuardianResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Guardian ID | "550e8400-e29b-41d4-a716-446655440000" |
familyId |
string (uuid) |
ID of the family this guardian belongs to | "550e8400-e29b-41d4-a716-446655440000" |
guardianType |
"FATHER" | "MOTHER" | "STEPFATHER" | "STEPMOTHER" | "GRANDFATHER" | "GRANDMOTHER" | "UNCLE" | "AUNT" | "OLDER_SIBLING" | "LEGAL_GUARDIAN" | "FOSTER_PARENT" | "RELATIVE" | "FAMILY_FRIEND" | "OTHER" |
Type of guardian: FATHER, MOTHER, LEGAL_GUARDIAN, OTHER | "FATHER" |
firstName |
string |
Guardian's first name | "Kwame" |
middleName |
string |
Guardian's middle name | "Mensah" |
lastName |
string |
Guardian's last name | "Asante" |
email |
string |
Guardian's email address | "[email protected]" |
phonePrimary |
string |
Primary phone number | "+233501234567" |
phoneSecondary |
string |
Secondary phone number | "+233509876543" |
occupation |
string |
Guardian's occupation | "Software Engineer" |
employer |
string |
Guardian's employer | "TechCorp Ltd" |
address |
string |
Guardian's residential address | 15 |
nationalId |
string |
National identification number | "GHA-123456789" |
profilePhotoUrl |
string |
URL of the guardian's profile photo | "https://storage.example.com/photos/guardian.jpg" |
isEmergencyContact |
boolean |
Whether this guardian is an emergency contact | |
canPickupStudent |
boolean |
Whether this guardian is authorised to pick up the student | |
isPrimaryContact |
boolean |
Whether this guardian is the primary contact for the family | |
isActive |
boolean |
Whether this guardian record is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseGuardianResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listGuardians({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const guardians = result.content; // GuardianResponse[]
const { page, totalPages, totalElements, last } = result;
createGuardian()¶
Create a new guardian
POST /api/school/guardians
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateGuardianRequest
| Field | Type | Required | Description |
|---|---|---|---|
familyId |
string (uuid) |
No | ID of the family (optional) |
guardianType |
"FATHER" | "MOTHER" | "STEPFATHER" | "STEPMOTHER" | "GRANDFATHER" | "GRANDMOTHER" | "UNCLE" | "AUNT" | "OLDER_SIBLING" | "LEGAL_GUARDIAN" | "FOSTER_PARENT" | "RELATIVE" | "FAMILY_FRIEND" | "OTHER" |
No | Type of guardian |
firstName |
string |
Yes | First name of the guardian |
middleName |
string |
No | Middle name of the guardian |
lastName |
string |
Yes | Last name of the guardian |
email |
string |
No | Email address |
phonePrimary |
string |
Yes | Primary phone number |
phoneSecondary |
string |
No | Secondary phone number |
occupation |
string |
No | Occupation of the guardian |
employer |
string |
No | Employer of the guardian |
address |
string |
No | Address of the guardian |
nationalId |
string |
No | National ID number |
profilePhotoUrl |
string |
No | URL of the profile photo |
isEmergencyContact |
boolean |
No | Whether this guardian is an emergency contact |
canPickupStudent |
boolean |
No | Whether this guardian can pick up the student |
isPrimaryContact |
boolean |
No | Whether this is the primary contact |
Response: GuardianResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Guardian ID | "550e8400-e29b-41d4-a716-446655440000" |
familyId |
string (uuid) |
ID of the family this guardian belongs to | "550e8400-e29b-41d4-a716-446655440000" |
guardianType |
"FATHER" | "MOTHER" | "STEPFATHER" | "STEPMOTHER" | "GRANDFATHER" | "GRANDMOTHER" | "UNCLE" | "AUNT" | "OLDER_SIBLING" | "LEGAL_GUARDIAN" | "FOSTER_PARENT" | "RELATIVE" | "FAMILY_FRIEND" | "OTHER" |
Type of guardian: FATHER, MOTHER, LEGAL_GUARDIAN, OTHER | "FATHER" |
firstName |
string |
Guardian's first name | "Kwame" |
middleName |
string |
Guardian's middle name | "Mensah" |
lastName |
string |
Guardian's last name | "Asante" |
email |
string |
Guardian's email address | "[email protected]" |
phonePrimary |
string |
Primary phone number | "+233501234567" |
phoneSecondary |
string |
Secondary phone number | "+233509876543" |
occupation |
string |
Guardian's occupation | "Software Engineer" |
employer |
string |
Guardian's employer | "TechCorp Ltd" |
address |
string |
Guardian's residential address | 15 |
nationalId |
string |
National identification number | "GHA-123456789" |
profilePhotoUrl |
string |
URL of the guardian's profile photo | "https://storage.example.com/photos/guardian.jpg" |
isEmergencyContact |
boolean |
Whether this guardian is an emergency contact | |
canPickupStudent |
boolean |
Whether this guardian is authorised to pick up the student | |
isPrimaryContact |
boolean |
Whether this guardian is the primary contact for the family | |
isActive |
boolean |
Whether this guardian record is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateGuardianRequest } from '@smartsapp/sdk/staff';
import type { CreateGuardianRequest, GuardianResponse } from '@smartsapp/sdk/staff';
const input: CreateGuardianRequest = {
familyId: "550e8400-e29b-41d4-a716-446655440000",
guardianType: "FATHER",
firstName: "James",
middleName: "Robert"
};
const parsed = zCreateGuardianRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: guardian, error } = await school.createGuardian({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// guardian is typed as GuardianResponse
Families¶
getFamily()¶
Get a family by ID
GET /api/school/families/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: FamilyResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Family ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school this family belongs to | "550e8400-e29b-41d4-a716-446655440000" |
familyName |
string |
Family surname | "Asante" |
familyCode |
string |
Unique family code | "FAM-001" |
primaryAddress |
string |
Primary residential address | 15 |
primaryPhone |
string |
Primary contact phone number | "+233501234567" |
primaryEmail |
string |
Primary contact email | "[email protected]" |
notes |
string |
Additional notes about the family | "Two children enrolled" |
isActive |
boolean |
Whether the family record is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { FamilyResponse } from '@smartsapp/sdk/staff';
const { data: family, error } = await school.getFamily({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// family is typed as FamilyResponse
updateFamily()¶
Update a family
PUT /api/school/families/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateFamilyRequest
| Field | Type | Required | Description |
|---|---|---|---|
schoolId |
string (uuid) |
No | ID of the school |
familyName |
string |
No | Name of the family |
familyCode |
string |
No | Unique family code |
primaryAddress |
string |
No | Primary address of the family |
primaryPhone |
string |
No | Primary phone number |
primaryEmail |
string |
No | Primary email address |
notes |
string |
No | Additional notes |
isActive |
boolean |
No | Whether the family is active |
Response: FamilyResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Family ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school this family belongs to | "550e8400-e29b-41d4-a716-446655440000" |
familyName |
string |
Family surname | "Asante" |
familyCode |
string |
Unique family code | "FAM-001" |
primaryAddress |
string |
Primary residential address | 15 |
primaryPhone |
string |
Primary contact phone number | "+233501234567" |
primaryEmail |
string |
Primary contact email | "[email protected]" |
notes |
string |
Additional notes about the family | "Two children enrolled" |
isActive |
boolean |
Whether the family record is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateFamilyRequest } from '@smartsapp/sdk/staff';
import type { UpdateFamilyRequest, FamilyResponse } from '@smartsapp/sdk/staff';
const input: UpdateFamilyRequest = {
schoolId: "550e8400-e29b-41d4-a716-446655440000",
familyName: "Doe Family",
familyCode: "FAM-2024-001",
primaryAddress: 123
};
const parsed = zUpdateFamilyRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: family, error } = await school.updateFamily({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// family is typed as FamilyResponse
deleteFamily()¶
Delete a family
DELETE /api/school/families/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteFamily({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listFamilies()¶
List families with pagination
GET /api/school/families
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseFamilyResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
FamilyResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
FamilyResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Family ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school this family belongs to | "550e8400-e29b-41d4-a716-446655440000" |
familyName |
string |
Family surname | "Asante" |
familyCode |
string |
Unique family code | "FAM-001" |
primaryAddress |
string |
Primary residential address | 15 |
primaryPhone |
string |
Primary contact phone number | "+233501234567" |
primaryEmail |
string |
Primary contact email | "[email protected]" |
notes |
string |
Additional notes about the family | "Two children enrolled" |
isActive |
boolean |
Whether the family record is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseFamilyResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listFamilies({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const familys = result.content; // FamilyResponse[]
const { page, totalPages, totalElements, last } = result;
createFamily()¶
Create a new family
POST /api/school/families
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateFamilyRequest
| Field | Type | Required | Description |
|---|---|---|---|
schoolId |
string (uuid) |
Yes | ID of the school |
familyName |
string |
Yes | Name of the family |
familyCode |
string |
No | Unique family code |
primaryAddress |
string |
No | Primary address of the family |
primaryPhone |
string |
No | Primary phone number |
primaryEmail |
string |
No | Primary email address |
notes |
string |
No | Additional notes |
Response: FamilyResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Family ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school this family belongs to | "550e8400-e29b-41d4-a716-446655440000" |
familyName |
string |
Family surname | "Asante" |
familyCode |
string |
Unique family code | "FAM-001" |
primaryAddress |
string |
Primary residential address | 15 |
primaryPhone |
string |
Primary contact phone number | "+233501234567" |
primaryEmail |
string |
Primary contact email | "[email protected]" |
notes |
string |
Additional notes about the family | "Two children enrolled" |
isActive |
boolean |
Whether the family record is active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateFamilyRequest } from '@smartsapp/sdk/staff';
import type { CreateFamilyRequest, FamilyResponse } from '@smartsapp/sdk/staff';
const input: CreateFamilyRequest = {
schoolId: "550e8400-e29b-41d4-a716-446655440000",
familyName: "Doe Family",
familyCode: "FAM-2024-001",
primaryAddress: 123
};
const parsed = zCreateFamilyRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: family, error } = await school.createFamily({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// family is typed as FamilyResponse
Classrooms¶
getClassroom()¶
Get a classroom by ID
GET /api/school/classrooms/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: ClassroomResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Classroom ID | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section this classroom belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the classroom | "Grade 3A" |
code |
string |
Short unique code for the classroom | "G3A" |
academicYear |
string |
Academic year the classroom is associated with | "2025/2026" |
capacity |
integer (int32) |
Maximum student capacity | 35 |
classTeacherId |
string (uuid) |
ID of the assigned class teacher | "550e8400-e29b-41d4-a716-446655440000" |
roomNumber |
string |
Physical room number | "B-204" |
isActive |
boolean |
Whether the classroom is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { ClassroomResponse } from '@smartsapp/sdk/staff';
const { data: classroom, error } = await school.getClassroom({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// classroom is typed as ClassroomResponse
updateClassroom()¶
Update a classroom
PUT /api/school/classrooms/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateClassroomRequest
| Field | Type | Required | Description |
|---|---|---|---|
sectionId |
string (uuid) |
No | ID of the section this classroom belongs to |
name |
string |
No | Name of the classroom |
code |
string |
No | Unique code for the classroom |
academicYear |
string |
No | Academic year |
capacity |
integer (int32) |
No | Maximum student capacity |
classTeacherId |
string (uuid) |
No | ID of the class teacher |
roomNumber |
string |
No | Room number |
isActive |
boolean |
No | Whether the classroom is active |
Response: ClassroomResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Classroom ID | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section this classroom belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the classroom | "Grade 3A" |
code |
string |
Short unique code for the classroom | "G3A" |
academicYear |
string |
Academic year the classroom is associated with | "2025/2026" |
capacity |
integer (int32) |
Maximum student capacity | 35 |
classTeacherId |
string (uuid) |
ID of the assigned class teacher | "550e8400-e29b-41d4-a716-446655440000" |
roomNumber |
string |
Physical room number | "B-204" |
isActive |
boolean |
Whether the classroom is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateClassroomRequest } from '@smartsapp/sdk/staff';
import type { UpdateClassroomRequest, ClassroomResponse } from '@smartsapp/sdk/staff';
const input: UpdateClassroomRequest = {
sectionId: "550e8400-e29b-41d4-a716-446655440000",
name: "Class 1A",
code: "CLS-1A",
academicYear: "2024-2025"
};
const parsed = zUpdateClassroomRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: classroom, error } = await school.updateClassroom({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// classroom is typed as ClassroomResponse
deleteClassroom()¶
Delete a classroom
DELETE /api/school/classrooms/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteClassroom({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listClassrooms()¶
List classrooms with pagination
GET /api/school/classrooms
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseClassroomResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
ClassroomResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
ClassroomResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Classroom ID | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section this classroom belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the classroom | "Grade 3A" |
code |
string |
Short unique code for the classroom | "G3A" |
academicYear |
string |
Academic year the classroom is associated with | "2025/2026" |
capacity |
integer (int32) |
Maximum student capacity | 35 |
classTeacherId |
string (uuid) |
ID of the assigned class teacher | "550e8400-e29b-41d4-a716-446655440000" |
roomNumber |
string |
Physical room number | "B-204" |
isActive |
boolean |
Whether the classroom is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseClassroomResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listClassrooms({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const classrooms = result.content; // ClassroomResponse[]
const { page, totalPages, totalElements, last } = result;
createClassroom()¶
Create a new classroom
POST /api/school/classrooms
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateClassroomRequest
| Field | Type | Required | Description |
|---|---|---|---|
sectionId |
string (uuid) |
Yes | ID of the section this classroom belongs to |
name |
string |
Yes | Name of the classroom |
code |
string |
No | Unique code for the classroom |
academicYear |
string |
No | Academic year |
capacity |
integer (int32) |
No | Maximum student capacity |
classTeacherId |
string (uuid) |
No | ID of the class teacher |
roomNumber |
string |
No | Room number |
Response: ClassroomResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Classroom ID | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section this classroom belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the classroom | "Grade 3A" |
code |
string |
Short unique code for the classroom | "G3A" |
academicYear |
string |
Academic year the classroom is associated with | "2025/2026" |
capacity |
integer (int32) |
Maximum student capacity | 35 |
classTeacherId |
string (uuid) |
ID of the assigned class teacher | "550e8400-e29b-41d4-a716-446655440000" |
roomNumber |
string |
Physical room number | "B-204" |
isActive |
boolean |
Whether the classroom is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateClassroomRequest } from '@smartsapp/sdk/staff';
import type { CreateClassroomRequest, ClassroomResponse } from '@smartsapp/sdk/staff';
const input: CreateClassroomRequest = {
sectionId: "550e8400-e29b-41d4-a716-446655440000",
name: "Class 1A",
code: "CLS-1A",
academicYear: "2024-2025"
};
const parsed = zCreateClassroomRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: classroom, error } = await school.createClassroom({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// classroom is typed as ClassroomResponse
Campuses¶
getCampus()¶
Get a campus by ID
GET /api/school/campuses/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: CampusResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Campus ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school this campus belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the campus | "East Campus" |
code |
string |
Short unique code for the campus | "EAST" |
address |
string |
Physical address of the campus | 45 |
phone |
string |
Contact phone number | "+233302654321" |
email |
string |
Contact email address | "[email protected]" |
principalName |
string |
Name of the campus principal | "Dr. Ama Darko" |
isActive |
boolean |
Whether the campus is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { CampusResponse } from '@smartsapp/sdk/staff';
const { data: campus, error } = await school.getCampus({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// campus is typed as CampusResponse
updateCampus()¶
Update a campus
PUT /api/school/campuses/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateCampusRequest
| Field | Type | Required | Description |
|---|---|---|---|
schoolId |
string (uuid) |
No | ID of the school this campus belongs to |
name |
string |
No | Name of the campus |
code |
string |
No | Unique code for the campus |
address |
string |
No | Physical address of the campus |
phone |
string |
No | Contact phone number |
email |
string |
No | Contact email address |
principalName |
string |
No | Name of the campus principal |
isActive |
boolean |
No | Whether the campus is active |
Response: CampusResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Campus ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school this campus belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the campus | "East Campus" |
code |
string |
Short unique code for the campus | "EAST" |
address |
string |
Physical address of the campus | 45 |
phone |
string |
Contact phone number | "+233302654321" |
email |
string |
Contact email address | "[email protected]" |
principalName |
string |
Name of the campus principal | "Dr. Ama Darko" |
isActive |
boolean |
Whether the campus is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateCampusRequest } from '@smartsapp/sdk/staff';
import type { UpdateCampusRequest, CampusResponse } from '@smartsapp/sdk/staff';
const input: UpdateCampusRequest = {
schoolId: "550e8400-e29b-41d4-a716-446655440000",
name: "Main Campus",
code: "MAIN",
address: 456
};
const parsed = zUpdateCampusRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: campus, error } = await school.updateCampus({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// campus is typed as CampusResponse
deleteCampus()¶
Delete a campus
DELETE /api/school/campuses/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteCampus({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listCampuses()¶
List campuses with pagination
GET /api/school/campuses
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseCampusResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
CampusResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
CampusResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Campus ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school this campus belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the campus | "East Campus" |
code |
string |
Short unique code for the campus | "EAST" |
address |
string |
Physical address of the campus | 45 |
phone |
string |
Contact phone number | "+233302654321" |
email |
string |
Contact email address | "[email protected]" |
principalName |
string |
Name of the campus principal | "Dr. Ama Darko" |
isActive |
boolean |
Whether the campus is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseCampusResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listCampuses({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const campus = result.content; // CampusResponse[]
const { page, totalPages, totalElements, last } = result;
createCampus()¶
Create a new campus
POST /api/school/campuses
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateCampusRequest
| Field | Type | Required | Description |
|---|---|---|---|
schoolId |
string (uuid) |
Yes | ID of the school this campus belongs to |
name |
string |
Yes | Name of the campus |
code |
string |
No | Unique code for the campus |
address |
string |
No | Physical address of the campus |
phone |
string |
No | Contact phone number |
email |
string |
No | Contact email address |
principalName |
string |
No | Name of the campus principal |
Response: CampusResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Campus ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school this campus belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the campus | "East Campus" |
code |
string |
Short unique code for the campus | "EAST" |
address |
string |
Physical address of the campus | 45 |
phone |
string |
Contact phone number | "+233302654321" |
email |
string |
Contact email address | "[email protected]" |
principalName |
string |
Name of the campus principal | "Dr. Ama Darko" |
isActive |
boolean |
Whether the campus is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateCampusRequest } from '@smartsapp/sdk/staff';
import type { CreateCampusRequest, CampusResponse } from '@smartsapp/sdk/staff';
const input: CreateCampusRequest = {
schoolId: "550e8400-e29b-41d4-a716-446655440000",
name: "Main Campus",
code: "MAIN",
address: 456
};
const parsed = zCreateCampusRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: campus, error } = await school.createCampus({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// campus is typed as CampusResponse
Academic Years¶
getAcademicYear()¶
Get an academic year by ID
GET /api/school/academic-years/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AcademicYearResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic year ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus (null for school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section (null for campus-wide or school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the academic year | "2025/2026" |
startDate |
string (date) |
Start date of the academic year | "2025-09-01" |
endDate |
string (date) |
End date of the academic year | "2026-07-15" |
periodType |
"TERM" | "SEMESTER" | "QUARTER" | "TRIMESTER" |
How the year is divided: TERM, SEMESTER, QUARTER | "TERM" |
numberOfPeriods |
integer (int32) |
Number of periods in the academic year | 3 |
isActive |
boolean |
Whether this academic year is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { AcademicYearResponse } from '@smartsapp/sdk/staff';
const { data: academicYear, error } = await school.getAcademicYear({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicYear is typed as AcademicYearResponse
updateAcademicYear()¶
Update an academic year
PUT /api/school/academic-years/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateAcademicYearRequest
| Field | Type | Required | Description |
|---|---|---|---|
campusId |
string (uuid) |
No | Campus ID for campus-level override (null for school-wide) |
sectionId |
string (uuid) |
No | Section ID for section-level override (null to inherit from campus/school) |
name |
string |
No | Name of the academic year |
startDate |
string (date) |
No | Start date of the academic year |
endDate |
string (date) |
No | End date of the academic year |
periodType |
"TERM" | "SEMESTER" | "QUARTER" | "TRIMESTER" |
No | Type of periods used |
isActive |
boolean |
No | Whether the academic year is active |
Response: AcademicYearResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic year ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus (null for school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section (null for campus-wide or school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the academic year | "2025/2026" |
startDate |
string (date) |
Start date of the academic year | "2025-09-01" |
endDate |
string (date) |
End date of the academic year | "2026-07-15" |
periodType |
"TERM" | "SEMESTER" | "QUARTER" | "TRIMESTER" |
How the year is divided: TERM, SEMESTER, QUARTER | "TERM" |
numberOfPeriods |
integer (int32) |
Number of periods in the academic year | 3 |
isActive |
boolean |
Whether this academic year is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateAcademicYearRequest } from '@smartsapp/sdk/staff';
import type { UpdateAcademicYearRequest, AcademicYearResponse } from '@smartsapp/sdk/staff';
const input: UpdateAcademicYearRequest = {
campusId: "550e8400-...",
sectionId: "550e8400-...",
name: "2025-2026",
startDate: "2025-09-01"
};
const parsed = zUpdateAcademicYearRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: academicYear, error } = await school.updateAcademicYear({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicYear is typed as AcademicYearResponse
deleteAcademicYear()¶
Delete an academic year
DELETE /api/school/academic-years/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteAcademicYear({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listAcademicYears()¶
List academic years with pagination
GET /api/school/academic-years
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseAcademicYearResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
AcademicYearResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
AcademicYearResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic year ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus (null for school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section (null for campus-wide or school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the academic year | "2025/2026" |
startDate |
string (date) |
Start date of the academic year | "2025-09-01" |
endDate |
string (date) |
End date of the academic year | "2026-07-15" |
periodType |
"TERM" | "SEMESTER" | "QUARTER" | "TRIMESTER" |
How the year is divided: TERM, SEMESTER, QUARTER | "TERM" |
numberOfPeriods |
integer (int32) |
Number of periods in the academic year | 3 |
isActive |
boolean |
Whether this academic year is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { PagedResponseAcademicYearResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await school.listAcademicYears({
query: { page: 0, size: 0 }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const academicYears = result.content; // AcademicYearResponse[]
const { page, totalPages, totalElements, last } = result;
createAcademicYear()¶
Create a new academic year
POST /api/school/academic-years
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateAcademicYearRequest
| Field | Type | Required | Description |
|---|---|---|---|
campusId |
string (uuid) |
No | Campus ID for campus-level override (null for school-wide) |
sectionId |
string (uuid) |
No | Section ID for section-level override (null to inherit from campus/school) |
name |
string |
Yes | Name of the academic year |
startDate |
string (date) |
Yes | Start date of the academic year |
endDate |
string (date) |
Yes | End date of the academic year |
periodType |
"TERM" | "SEMESTER" | "QUARTER" | "TRIMESTER" |
Yes | Type of periods used |
Response: AcademicYearResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic year ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus (null for school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section (null for campus-wide or school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the academic year | "2025/2026" |
startDate |
string (date) |
Start date of the academic year | "2025-09-01" |
endDate |
string (date) |
End date of the academic year | "2026-07-15" |
periodType |
"TERM" | "SEMESTER" | "QUARTER" | "TRIMESTER" |
How the year is divided: TERM, SEMESTER, QUARTER | "TERM" |
numberOfPeriods |
integer (int32) |
Number of periods in the academic year | 3 |
isActive |
boolean |
Whether this academic year is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateAcademicYearRequest } from '@smartsapp/sdk/staff';
import type { CreateAcademicYearRequest, AcademicYearResponse } from '@smartsapp/sdk/staff';
const input: CreateAcademicYearRequest = {
campusId: "550e8400-...",
sectionId: "550e8400-...",
name: "2025-2026",
startDate: "2025-09-01"
};
const parsed = zCreateAcademicYearRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: academicYear, error } = await school.createAcademicYear({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicYear is typed as AcademicYearResponse
resolveAcademicYear()¶
Resolve the effective academic year with inheritance
GET /api/school/academic-years/resolve
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
campusId |
string (uuid) |
query | No | |
sectionId |
string (uuid) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AcademicYearResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic year ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus (null for school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
sectionId |
string (uuid) |
ID of the section (null for campus-wide or school-wide) | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the academic year | "2025/2026" |
startDate |
string (date) |
Start date of the academic year | "2025-09-01" |
endDate |
string (date) |
End date of the academic year | "2026-07-15" |
periodType |
"TERM" | "SEMESTER" | "QUARTER" | "TRIMESTER" |
How the year is divided: TERM, SEMESTER, QUARTER | "TERM" |
numberOfPeriods |
integer (int32) |
Number of periods in the academic year | 3 |
isActive |
boolean |
Whether this academic year is currently active | |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { AcademicYearResponse } from '@smartsapp/sdk/staff';
const { data: academicYear, error } = await school.resolveAcademicYear({
query: { campusId: "...", sectionId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicYear is typed as AcademicYearResponse
Academic Periods¶
getAcademicPeriod()¶
Get an academic period by ID
GET /api/school/academic-periods/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AcademicPeriodResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic period ID | "550e8400-e29b-41d4-a716-446655440000" |
academicYearId |
string (uuid) |
ID of the academic year this period belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the period | "Term 1" |
startDate |
string (date) |
Start date of the period | "2025-09-01" |
endDate |
string (date) |
End date of the period | "2025-12-15" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { AcademicPeriodResponse } from '@smartsapp/sdk/staff';
const { data: academicPeriod, error } = await school.getAcademicPeriod({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicPeriod is typed as AcademicPeriodResponse
updateAcademicPeriod()¶
Update an academic period
PUT /api/school/academic-periods/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateAcademicPeriodRequest
| Field | Type | Required | Description |
|---|---|---|---|
academicYearId |
string (uuid) |
No | ID of the academic year this period belongs to |
name |
string |
No | Name of the period |
startDate |
string (date) |
No | Start date of the period |
endDate |
string (date) |
No | End date of the period |
Response: AcademicPeriodResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic period ID | "550e8400-e29b-41d4-a716-446655440000" |
academicYearId |
string (uuid) |
ID of the academic year this period belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the period | "Term 1" |
startDate |
string (date) |
Start date of the period | "2025-09-01" |
endDate |
string (date) |
End date of the period | "2025-12-15" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateAcademicPeriodRequest } from '@smartsapp/sdk/staff';
import type { UpdateAcademicPeriodRequest, AcademicPeriodResponse } from '@smartsapp/sdk/staff';
const input: UpdateAcademicPeriodRequest = {
academicYearId: "550e8400-...",
name: "Term 1",
startDate: "2025-09-01",
endDate: "2025-12-15"
};
const parsed = zUpdateAcademicPeriodRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: academicPeriod, error } = await school.updateAcademicPeriod({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicPeriod is typed as AcademicPeriodResponse
deleteAcademicPeriod()¶
Delete an academic period
DELETE /api/school/academic-periods/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteAcademicPeriod({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listAcademicPeriods()¶
List academic periods for an academic year
GET /api/school/academic-periods
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
academicYearId |
string (uuid) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AcademicPeriodResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic period ID | "550e8400-e29b-41d4-a716-446655440000" |
academicYearId |
string (uuid) |
ID of the academic year this period belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the period | "Term 1" |
startDate |
string (date) |
Start date of the period | "2025-09-01" |
endDate |
string (date) |
End date of the period | "2025-12-15" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.listAcademicPeriods({
query: { academicYearId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as AcademicPeriodResponse[]
createAcademicPeriod()¶
Create a new academic period
POST /api/school/academic-periods
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateAcademicPeriodRequest
| Field | Type | Required | Description |
|---|---|---|---|
academicYearId |
string (uuid) |
Yes | ID of the academic year this period belongs to |
name |
string |
Yes | Name of the period |
startDate |
string (date) |
Yes | Start date of the period |
endDate |
string (date) |
Yes | End date of the period |
Response: AcademicPeriodResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic period ID | "550e8400-e29b-41d4-a716-446655440000" |
academicYearId |
string (uuid) |
ID of the academic year this period belongs to | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the period | "Term 1" |
startDate |
string (date) |
Start date of the period | "2025-09-01" |
endDate |
string (date) |
End date of the period | "2025-12-15" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateAcademicPeriodRequest } from '@smartsapp/sdk/staff';
import type { CreateAcademicPeriodRequest, AcademicPeriodResponse } from '@smartsapp/sdk/staff';
const input: CreateAcademicPeriodRequest = {
academicYearId: "550e8400-...",
name: "Term 1",
startDate: "2025-09-01",
endDate: "2025-12-15"
};
const parsed = zCreateAcademicPeriodRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: academicPeriod, error } = await school.createAcademicPeriod({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicPeriod is typed as AcademicPeriodResponse
Academic Holidays¶
getAcademicHoliday()¶
Get an academic holiday by ID
GET /api/school/academic-holidays/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AcademicHolidayResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic holiday ID | "550e8400-e29b-41d4-a716-446655440000" |
academicYearId |
string (uuid) |
ID of the academic year | "550e8400-e29b-41d4-a716-446655440000" |
academicPeriodId |
string (uuid) |
ID of the academic period this holiday falls within | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the holiday | "Mid-term break" |
startDate |
string (date) |
Start date of the holiday | "2025-10-20" |
endDate |
string (date) |
End date of the holiday | "2025-10-24" |
description |
string |
Additional details about the holiday | "School closed for all students and staff" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { AcademicHolidayResponse } from '@smartsapp/sdk/staff';
const { data: academicHoliday, error } = await school.getAcademicHoliday({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicHoliday is typed as AcademicHolidayResponse
updateAcademicHoliday()¶
Update an academic holiday
PUT /api/school/academic-holidays/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: UpdateAcademicHolidayRequest
| Field | Type | Required | Description |
|---|---|---|---|
academicYearId |
string (uuid) |
No | ID of the academic year this holiday belongs to |
academicPeriodId |
string (uuid) |
No | ID of the academic period (null for year-level breaks) |
name |
string |
No | Name of the holiday |
startDate |
string (date) |
No | Start date of the holiday |
endDate |
string (date) |
No | End date of the holiday |
description |
string |
No | Description of the holiday |
Response: AcademicHolidayResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic holiday ID | "550e8400-e29b-41d4-a716-446655440000" |
academicYearId |
string (uuid) |
ID of the academic year | "550e8400-e29b-41d4-a716-446655440000" |
academicPeriodId |
string (uuid) |
ID of the academic period this holiday falls within | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the holiday | "Mid-term break" |
startDate |
string (date) |
Start date of the holiday | "2025-10-20" |
endDate |
string (date) |
End date of the holiday | "2025-10-24" |
description |
string |
Additional details about the holiday | "School closed for all students and staff" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zUpdateAcademicHolidayRequest } from '@smartsapp/sdk/staff';
import type { UpdateAcademicHolidayRequest, AcademicHolidayResponse } from '@smartsapp/sdk/staff';
const input: UpdateAcademicHolidayRequest = {
academicYearId: "550e8400-...",
academicPeriodId: "550e8400-...",
name: "Christmas Break",
startDate: "2025-12-20"
};
const parsed = zUpdateAcademicHolidayRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: academicHoliday, error } = await school.updateAcademicHoliday({
body: input,
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicHoliday is typed as AcademicHolidayResponse
deleteAcademicHoliday()¶
Delete an academic holiday
DELETE /api/school/academic-holidays/{id}
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
id |
string (uuid) |
path | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: void (204)
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.deleteAcademicHoliday({
path: { id: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
listAcademicHolidays()¶
List academic holidays for an academic year
GET /api/school/academic-holidays
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
academicYearId |
string (uuid) |
query | Yes | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: AcademicHolidayResponse[] (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic holiday ID | "550e8400-e29b-41d4-a716-446655440000" |
academicYearId |
string (uuid) |
ID of the academic year | "550e8400-e29b-41d4-a716-446655440000" |
academicPeriodId |
string (uuid) |
ID of the academic period this holiday falls within | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the holiday | "Mid-term break" |
startDate |
string (date) |
Start date of the holiday | "2025-10-20" |
endDate |
string (date) |
End date of the holiday | "2025-10-24" |
description |
string |
Additional details about the holiday | "School closed for all students and staff" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
const { data, error } = await school.listAcademicHolidays({
query: { academicYearId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// data is typed as AcademicHolidayResponse[]
createAcademicHoliday()¶
Create a new academic holiday
POST /api/school/academic-holidays
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreateAcademicHolidayRequest
| Field | Type | Required | Description |
|---|---|---|---|
academicYearId |
string (uuid) |
Yes | ID of the academic year this holiday belongs to |
academicPeriodId |
string (uuid) |
No | ID of the academic period (null for year-level breaks) |
name |
string |
Yes | Name of the holiday |
startDate |
string (date) |
Yes | Start date of the holiday |
endDate |
string (date) |
Yes | End date of the holiday |
description |
string |
No | Description of the holiday |
Response: AcademicHolidayResponse (201)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Academic holiday ID | "550e8400-e29b-41d4-a716-446655440000" |
academicYearId |
string (uuid) |
ID of the academic year | "550e8400-e29b-41d4-a716-446655440000" |
academicPeriodId |
string (uuid) |
ID of the academic period this holiday falls within | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the holiday | "Mid-term break" |
startDate |
string (date) |
Start date of the holiday | "2025-10-20" |
endDate |
string (date) |
End date of the holiday | "2025-10-24" |
description |
string |
Additional details about the holiday | "School closed for all students and staff" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school, zCreateAcademicHolidayRequest } from '@smartsapp/sdk/staff';
import type { CreateAcademicHolidayRequest, AcademicHolidayResponse } from '@smartsapp/sdk/staff';
const input: CreateAcademicHolidayRequest = {
academicYearId: "550e8400-...",
academicPeriodId: "550e8400-...",
name: "Christmas Break",
startDate: "2025-12-20"
};
const parsed = zCreateAcademicHolidayRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data: academicHoliday, error } = await school.createAcademicHoliday({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// academicHoliday is typed as AcademicHolidayResponse
My Staff Profile¶
getMyStaffProfile()¶
Get the authenticated user's staff profile
GET /api/school/my-staff-profile
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: StaffResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Staff member ID | "550e8400-e29b-41d4-a716-446655440000" |
schoolId |
string (uuid) |
ID of the school | "550e8400-e29b-41d4-a716-446655440000" |
campusId |
string (uuid) |
ID of the campus the staff member is assigned to | "550e8400-e29b-41d4-a716-446655440000" |
staffIdNumber |
string |
Staff ID number | "STF-2026-001" |
firstName |
string |
First name | "Abena" |
middleName |
string |
Middle name | "Osei" |
lastName |
string |
Last name | "Mensah" |
email |
string |
Email address | "[email protected]" |
phone |
string |
Phone number | "+233501234567" |
dateOfBirth |
string (date) |
Date of birth | "1985-06-15" |
gender |
"MALE" | "FEMALE" | "OTHER" |
Gender | "MALE" |
profilePhotoUrl |
string |
URL of the staff member's profile photo | "https://storage.example.com/photos/staff.jpg" |
role |
"TEACHER" | "ADMINISTRATOR" | "HEADMASTER" | "SUPPORT" | "OTHER" |
Staff role: TEACHER, ADMIN, PRINCIPAL, etc. | "TEACHER" |
department |
string |
Department name | "Mathematics" |
employmentType |
"FULL_TIME" | "PART_TIME" | "CONTRACT" |
Employment type: FULL_TIME, PART_TIME, CONTRACT | "FULL_TIME" |
hireDate |
string (date) |
Date the staff member was hired | "2024-09-01" |
status |
"ACTIVE" | "INACTIVE" | "ON_LEAVE" | "TERMINATED" |
Employment status | "ACTIVE" |
createdAt |
string (date-time) |
When the record was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the record was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { StaffResponse } from '@smartsapp/sdk/staff';
const { data: staff, error } = await school.getMyStaffProfile();
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// staff is typed as StaffResponse
My School¶
getMySchool()¶
Get the authenticated user's school
GET /api/school/my-school
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: SchoolResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
School ID | "550e8400-e29b-41d4-a716-446655440000" |
name |
string |
Name of the school | "Lincoln International Academy" |
code |
string |
Short unique code for the school | "LIA" |
logoUrl |
string |
URL of the school logo | "https://storage.example.com/logos/lia.png" |
address |
string |
Physical address of the school | 12 |
phone |
string |
Contact phone number | "+233302123456" |
email |
string |
Contact email address | "[email protected]" |
website |
string |
School website URL | "https://lincolnacademy.edu" |
accreditationNumber |
string |
Government accreditation number | "ACC-2024-00123" |
defaultCurrency |
string |
Default currency code for the school | "GHS" |
isActive |
boolean |
Whether the school is currently active | |
createdAt |
string (date-time) |
When the school was created | "2026-01-15T10:30:00Z" |
updatedAt |
string (date-time) |
When the school was last updated | "2026-01-15T10:30:00Z" |
Example:
import { school } from '@smartsapp/sdk/staff';
import type { SchoolResponse } from '@smartsapp/sdk/staff';
const { data: school, error } = await school.getMySchool();
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
// school is typed as SchoolResponse
Platform (shared)¶
These modules are available in both staff and parent SDKs.
Wallet (wallet)¶
Wallet¶
creditWallet()¶
Credit a student's Sika ID wallet
POST /api/wallet/credit
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Request Body: CreditWalletRequest
| Field | Type | Required | Description |
|---|---|---|---|
studentId |
string (uuid) |
Yes | ID of the student whose wallet is being credited |
amount |
number |
Yes | Amount to credit (positive) |
currency |
string |
Yes | ISO 4217 currency code |
Response: void (200)
Example:
import { wallet, zCreditWalletRequest } from '@smartsapp/sdk/staff';
import type { CreditWalletRequest } from '@smartsapp/sdk/staff';
const input: CreditWalletRequest = {
studentId: "00000000-0000-0000-0000-000000000001",
amount: 150.0,
currency: "GHS"
};
const parsed = zCreditWalletRequest.safeParse(input);
if (!parsed.success) {
console.error(parsed.error.issues);
// [{ path: ['fieldName'], message: 'Required', code: 'invalid_type' }, ...]
return;
}
const { data, error } = await wallet.creditWallet({
body: input
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
Audit (audit)¶
Audit Logs¶
listAuditEntries()¶
List audit log entries with optional filters
GET /api/platform/audit-logs
Parameters:
| Name | Type | In | Required | Description |
|---|---|---|---|---|
entityType |
string |
query | No | |
entityId |
string |
query | No | |
actorId |
string |
query | No | |
page |
integer (int32) |
query | No | |
size |
integer (int32) |
query | No | |
X-Request-Id |
string (uuid) |
header | No | Optional client-generated request ID for tracing. Auto-generated if omitted. |
Response: PagedResponseAuditLogResponse (200)
| Field | Type | Description | Example |
|---|---|---|---|
content |
AuditLogResponse[] |
Items on the current page | |
page |
integer (int32) |
Current page number (0-based) | 0 |
size |
integer (int32) |
Page size | 20 |
totalElements |
integer (int64) |
Total number of elements | 42 |
totalPages |
integer (int32) |
Total number of pages | 3 |
last |
boolean |
Whether this is the last page |
AuditLogResponse fields:
| Field | Type | Description | Example |
|---|---|---|---|
id |
string (uuid) |
Audit log entry ID | "550e8400-..." |
entityType |
string |
Type of the audited entity | "CanteenOrder" |
entityId |
string |
ID of the audited entity | |
action |
"CREATE" | "UPDATE" | "DELETE" |
Action performed | "CREATE" |
actorId |
string |
ID of the user who performed the action | |
beforeState |
string |
Entity state before the action (JSON) | |
afterState |
string |
Entity state after the action (JSON) | |
createdAt |
string (date-time) |
When the action occurred | "2026-01-01T08:00:00Z" |
Example:
import { audit } from '@smartsapp/sdk/staff';
import type { PagedResponseAuditLogResponse } from '@smartsapp/sdk/staff';
const { data: result, error } = await audit.listAuditEntries({
query: { entityType: "...", entityId: "...", actorId: "..." }
});
if (error) {
// error is typed as ProblemDetail (RFC 9457)
// { type, title, status, detail }
console.error(error.title, error.detail);
return;
}
const auditLogs = result.content; // AuditLogResponse[]
const { page, totalPages, totalElements, last } = result;
Auth (auth)¶
Not yet implemented
This module is planned but not yet available.
Chat (chat)¶
Not yet implemented
This module is planned but not yet available.
Engagement (engagement)¶
Not yet implemented
This module is planned but not yet available.
Notifications (notifications)¶
Not yet implemented
This module is planned but not yet available.