Skip to main content
Was this helpful?

User API

User, Profile, and Permission Surface

Manage profile data, language, visibility preferences, and permission bootstrap

These routes back the signed-in user settings area and the helper APIs the frontend uses to hydrate the current session. They do not include admin-only user management.

JWT or user API keyMultipart uploadProfile preferencesPermission bootstrap

Source

  • Profile controller: backend-nestjs/src/controllers/user-profile.controller.ts
  • Language controller: backend-nestjs/src/controllers/user-language.controller.ts
  • Permissions controller: backend-nestjs/src/controllers/user-permissions.controller.ts
  • Users controller: backend-nestjs/src/users/users.controller.ts
  • DTOs: backend-nestjs/src/dto/user-profile.dto.ts, backend-nestjs/src/users/dto/list-users.query.dto.ts

Authentication and Permissions

  • All routes on this page require authentication.
  • Routes using JwtAuthGuard accept bearer JWT and, where supported, user API keys.
  • POST /api/user/profile-picture is marked with @AllowIncompleteOnboarding(), so it can be used before onboarding is complete.
  • Profile writes are scoped to the authenticated user only.

Endpoint Reference

Profile and Settings

MethodPathPurposeRequest or queryAuthSource
GET/api/user/profileRead the current user profile and settings.NoneJWT or user API keycontrollers/user-profile.controller.ts
POST/api/user/profile-pictureUpload and set a profile picture.Multipart field: fileJWT or user API keycontrollers/user-profile.controller.ts
PATCH/api/user/profileUpdate profile fields and UI preferences.Body: profile fieldsJWT or user API keycontrollers/user-profile.controller.ts
DELETE/api/user/event-labels/:labelRemove one saved event label and strip it from the user's events.Path: labelJWT or user API keycontrollers/user-profile.controller.ts
PATCH/api/user/themeUpdate theme color only.Body: themeColorJWT or user API keycontrollers/user-profile.controller.ts
PATCH/api/user/passwordChange the current user's password.Body: currentPassword,newPasswordJWT or user API keycontrollers/user-profile.controller.ts
PATCH/api/users/me/languageUpdate the preferred UI language.Body: preferredLanguageJWT or user API keycontrollers/user-language.controller.ts

Session Bootstrap and Sharing Helpers

MethodPathPurposeRequest or queryAuthSource
GET/api/users/meRead the current user entity from the users service.NoneJWT or user API keyusers/users.controller.ts
GET/api/usersSearch users for sharing flows.Query: searchJWT or user API keyusers/users.controller.ts
GET/api/user-permissionsGet the current permission snapshot.NoneJWT or user API keycontrollers/user-permissions.controller.ts
GET/api/user-permissions/accessible-organizationsList organizations accessible to the current user.NoneJWT or user API keycontrollers/user-permissions.controller.ts
GET/api/user-permissions/accessible-reservation-calendarsList reservation calendars accessible to the current user.NoneJWT or user API keycontrollers/user-permissions.controller.ts

Request Shapes

Update profile

UpdateProfileDto in backend-nestjs/src/dto/user-profile.dto.ts

  • username: optional, minimum 3 chars
  • email: optional, valid email
  • firstName: optional string
  • lastName: optional string
  • profilePictureUrl: optional URL, max 2048 chars
  • weekStartDay: optional integer 0..6
  • defaultCalendarView: optional month|week
  • timezone: optional string
  • timeFormat: optional 12h|24h
  • language: optional enum en|hu|de|fr
  • preferredLanguage: optional enum en|hu|de|fr
  • hideReservationsTab: optional boolean
  • hiddenResourceIds: optional number array
  • visibleCalendarIds: optional number array
  • visibleResourceTypeIds: optional number array
  • hiddenFromLiveFocusTags: optional string array, max 64 chars each
  • eventLabels: optional string array, max 64 chars each
  • defaultTasksCalendarId: optional number or null

Implementation behavior from the controller:

  • Username and email uniqueness are rechecked only if those fields actually changed.
  • hiddenFromLiveFocusTags and eventLabels are normalized, deduplicated, trimmed, and capped to 100 items.
  • defaultTasksCalendarId can be cleared with null.
  • Changing defaultTasksCalendarId can trigger task-to-calendar resyncs for tasks with due dates.

Profile picture upload

Rules enforced in backend-nestjs/src/controllers/user-profile.controller.ts

  • field name: file
  • allowed MIME types: image/jpeg, image/png, image/gif, image/webp
  • max file size: 2MB

Theme and password

  • UpdateThemeDto.themeColor: optional hex string #rgb or #rrggbb
  • ChangePasswordDto.currentPassword: required string
  • ChangePasswordDto.newPassword: required, minimum 6 chars

Language

  • UpdateLanguagePreferenceDto.preferredLanguage: required enum en|hu|de|fr
  • ListUsersQueryDto.search: optional safe text, max 80 chars

Example Calls

Update profile preferences

curl -X PATCH "$PRIMECAL_API/api/user/profile" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"timezone": "Europe/Budapest",
"timeFormat": "24h",
"weekStartDay": 1,
"visibleCalendarIds": [2, 3, 5],
"hiddenFromLiveFocusTags": ["no_focus", "private"],
"defaultTasksCalendarId": 7
}'

Upload a profile picture

curl -X POST "$PRIMECAL_API/api/user/profile-picture" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@C:/tmp/avatar.webp"

Search users for sharing

curl "$PRIMECAL_API/api/users?search=justin" \
-H "Authorization: Bearer $TOKEN"

Bootstrap permission-aware UI

curl "$PRIMECAL_API/api/user-permissions" \
-H "Authorization: Bearer $TOKEN"

Response Notes

  • GET /api/user/profile returns the richest user-settings payload, including visibility preferences, live-focus hidden tags, event labels, onboarding state, and privacy policy acceptance info.
  • GET /api/users/me is a lighter current-user lookup from the users service.
  • PATCH /api/user/password returns a simple success message after validating the current password.
  • DELETE /api/user/event-labels/:label returns the removed label, remaining labels, and the number of events affected.

Best Practices

  • Use GET /api/user/profile as the primary settings bootstrap route.
  • Use GET /api/user-permissions before rendering reservations, organization settings, or role-sensitive UI.
  • Send only changed fields in PATCH /api/user/profile; the controller intentionally performs narrow uniqueness checks.
  • Keep eventLabels and hiddenFromLiveFocusTags normalized on the client too, so UI state matches the backend normalization rules.
  • Use Personal Logs API for audit history rather than overloading these settings endpoints with activity concerns.