/v1/trainee/calendar, router traineeCalendarRouter in src/modules/trainee-calendar/trainee-calendar.routes.ts.
Lane: trainee. Each route uses authenticateTrainee only, without the app access guard. Preview tokens can call the two GET routes. See Authentication.
Rules that apply to every endpoint
- Feature switch. When the studio’s
settings.calendarEnabledis explicitlyfalse, every endpoint returns 403calendar is disabled for this studio. The same flag is exposed to the app asstudio.calendarEnabledon sign-in andme. - Which coach. Slots are for the trainee’s assigned coach (
Client.coachId). A trainee with no assigned coach gets the studio’s oldest activeHEAD_COACH, or failing that the oldest active coach. - Time zone. Availability windows are wall-clock minutes of the day. They are converted to UTC instants in the studio’s time zone (
Studio.timezone, defaultAsia/Jerusalem). The trainee’s own zone is not used here. - Bookable types.
TRAININGandCONVERSATION(BOOKABLE_SLOT_TYPES).
Endpoints
GET /v1/trainee/calendar/slots
Lists the free slots in a time range.
Auth: trainee token.
string
required
ISO date or date-time. Start of the range.
string
required
ISO date or date-time. Must be after
from.string
TRAINING or CONVERSATION. Omit for both.generateSlots):
- The coach’s active
AvailabilityWindowrows are loaded. A window is eitherRECURRINGon aweekday, or bound to onedate. Each hasstartMinute,endMinute,durationMinand aslotType. - For each day in the range, each matching window is cut into back-to-back slots of
durationMin. The walk covers at most 31 days fromfrom(MAX_SLOT_RANGE_DAYS), whatevertosays. - A slot is kept when it starts inside the range, starts in the future, and does not overlap any calendar event of that coach whose status is not
CANCELLED.
items is empty.
Errors:
POST /v1/trainee/calendar/book
Books one slot.
Auth: trainee token. Refused for preview tokens.
string
required
The coach from the slot.
string
required
TRAINING or CONVERSATION.string
required
The slot’s
startsAt, exactly as returned.string
required
The slot’s
endsAt, exactly as returned. Must be after startsAt.CalendarEvent with title set to the trainee’s name, type set to the slot type and status CONFIRMED. The module sends no notification and writes no Google Calendar event.
The availability check and the insert are separate queries, not one transaction. Two trainees booking the same slot at the same instant are not guarded by a database constraint.
Response: 201. The created event.
GET /v1/trainee/calendar/meetings
Lists every calendar event linked to the trainee, past and future, including cancelled ones.
Auth: trainee token.
No parameters. Ordered by startsAt, newest first. This endpoint does not check the calendar feature switch.
Response: 200.
type the coach chose. studio.timezone is included so the app can show times in the studio’s zone.
Errors: none beyond the lane errors.
POST /v1/trainee/calendar/meetings/:id/cancel
Cancels one of the trainee’s upcoming meetings.
Auth: trainee token. Refused for preview tokens.
string
required
The calendar event id.
status to CANCELLED. The slot becomes bookable again, because cancelled events are ignored when slots are generated. Cancelling an already cancelled meeting returns it unchanged. Like the meetings list, this endpoint does not check the calendar feature switch.
Response: 200. The event row, same shape as a booking, with status CANCELLED.
Errors: