> For the complete documentation index, see [llms.txt](https://mobile-calendar.gitbook.io/v1/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mobile-calendar.gitbook.io/v1/rest-api/employees.md).

# Employees

Employees of the account together with their permission sets (one object, 1:1).

## Get all employees with their complete permission sets

> Lists every active employee of the account together with the FULL permission object (employee and permissions are one resource, 1:1 — there are no separate permission endpoints). Each entry carries all permission flags (false = not granted) and \`permissions.rooms\` (room restriction; empty = all rooms). Passwords are never returned. OWNER-ONLY: this whole resource is available only to the account owner — employee tokens (AI agent / MCP) get 403 regardless of scopes, and no panel permission grants employees.\* scopes to an employee. Required scope: \`employees.read\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"employees","description":"Employees of the account together with their permission sets (one object, 1:1)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"EmployeesListResponse":{"required":["data"],"properties":{"data":{"required":["employees"],"properties":{"employees":{"type":"array","items":{"$ref":"#/components/schemas/EmployeeEntry"}}},"type":"object"},"meta":{"properties":{"total":{"type":"integer"}},"type":"object"}},"type":"object"},"EmployeeEntry":{"required":["employeeId","email","forename","name","position","positionName","lang","phone","phonePrefix","phoneCountry","avatar","portal","lastLogin","permissions"],"properties":{"employeeId":{"type":"integer"},"email":{"description":"Employee login.","type":"string"},"forename":{"type":"string"},"name":{"type":"string"},"position":{"type":"integer","enum":[0,1,2,3,4,5,6]},"positionName":{"type":"string","enum":["ADMINISTRATOR","RECEPTIONIST","HOUSEKEEPER","MANAGER","OWNER","MAINTENANCE_TECHNICIAN","FOOD_AND_BEVERAGE_MANAGER"]},"lang":{"description":"Panel language of the employee.","type":"string"},"phone":{"type":"string"},"phonePrefix":{"type":"string","nullable":true},"phoneCountry":{"type":"string","nullable":true},"avatar":{"description":"Avatar URL; managed in the panel (not via this API).","type":"string","nullable":true},"portal":{"description":"Read-only: 0 = full panel, 1 = limited housekeeper panel.","type":"integer"},"lastLogin":{"description":"Most recent login — the newest session in the panel's Employees → employee → Devices tab (falls back to the account's login timestamp when no session is recorded).","type":"string","format":"date-time","nullable":true},"lastActivity":{"description":"Last activity of any of the employee's sessions (last sync of the app/panel).","type":"string","format":"date-time","nullable":true},"devices":{"description":"GET /employees/{employeeId} only: the employee's sessions exactly as the Devices tab shows them, newest activity first. `ipAddress` is personal data — this resource is owner-only.","type":"array","items":{"properties":{"browser":{"type":"string","nullable":true},"system":{"type":"string","nullable":true},"platform":{"description":"desktop / ios / android","type":"string","nullable":true},"ipAddress":{"type":"string","nullable":true},"loggedInAt":{"type":"string","format":"date-time","nullable":true},"lastActivityAt":{"type":"string","format":"date-time","nullable":true}},"type":"object"}},"permissions":{"$ref":"#/components/schemas/EmployeePermissions"}},"type":"object"},"EmployeePermissions":{"description":"Complete permission set of an employee — 1:1 with the panel's Uprawnienia screen. Every flag defaults to false; unknown keys are rejected with 422 (a typo in a flag name must not silently mean 'no permission'). `rooms` restricts the employee to specific rooms: empty list = access to ALL rooms.","properties":{"addRoom":{"description":"add rooms","type":"boolean"},"editRoom":{"description":"edit rooms (includes room photos)","type":"boolean"},"deleteRoom":{"description":"delete rooms","type":"boolean"},"filterRoom":{"description":"filter rooms","type":"boolean"},"addReservation":{"description":"add reservations","type":"boolean"},"showReservation":{"description":"view reservations","type":"boolean"},"editReservation":{"description":"edit reservations","type":"boolean"},"deleteReservation":{"description":"delete reservations","type":"boolean"},"editDeletePastReservations":{"description":"edit/delete past reservations","type":"boolean"},"registration":{"description":"guest check-in (meldunek)","type":"boolean"},"changeReservationPaymentStatus":{"description":"change reservation payment status","type":"boolean"},"searchReservation":{"description":"search reservations","type":"boolean"},"dashboard":{"description":"calendar / arrivals-departures view","type":"boolean"},"arrivalsDeparturesReport":{"description":"arrivals & departures report","type":"boolean"},"printCalendar":{"description":"print the calendar","type":"boolean"},"widget":{"description":"dashboard widgets","type":"boolean"},"customerDatabase":{"description":"client database (full CRUD)","type":"boolean"},"statistics":{"description":"statistics","type":"boolean"},"exportReservations":{"description":"export reservations","type":"boolean"},"importReservations":{"description":"import reservations","type":"boolean"},"searchAvailableRooms":{"description":"search available rooms","type":"boolean"},"pricing":{"description":"price lists (mobile-calendar + OTA channels + rate plans)","type":"boolean"},"reservations":{"description":"reservations module","type":"boolean"},"sendConfirmation":{"description":"send confirmations to guests","type":"boolean"},"messagesTemplates":{"description":"message templates","type":"boolean"},"smtpConfiguration":{"description":"SMTP configuration","type":"boolean"},"invoicing":{"description":"invoicing (full CRUD)","type":"boolean"},"editObjectData":{"description":"property data, regulations, privacy policy","type":"boolean"},"restoreReservation":{"description":"restore deleted reservations","type":"boolean"},"changeEmail":{"description":"change own e-mail","type":"boolean"},"changePassword":{"description":"change own password","type":"boolean"},"twoFactorAuth":{"description":"two-factor authentication","type":"boolean"},"editPersonalData":{"description":"account personal/invoicing data","type":"boolean"},"meals":{"description":"meals configuration (Restaurant)","type":"boolean"},"additionalServices":{"description":"additional services (full CRUD)","type":"boolean"},"onlineBookingEngine":{"description":"online booking engine","type":"boolean"},"googleCalendar":{"description":"Google Calendar","type":"boolean"},"booking":{"description":"channel manager (Booking.com/Airbnb/Slowhop/iCal)","type":"boolean"},"reservationSource":{"description":"reservation sources","type":"boolean"},"notifications":{"description":"notifications","type":"boolean"},"settings":{"description":"account settings","type":"boolean"},"buySubscription":{"description":"buy subscription","type":"boolean"},"showNewChanges":{"description":"changelog","type":"boolean"},"iCalendar":{"description":"iCalendar sync","type":"boolean"},"addTask":{"description":"add tasks","type":"boolean"},"changeRoomStatus":{"description":"change room status (clean/dirty)","type":"boolean"},"history":{"description":"change history (audit log)","type":"boolean"},"tasks":{"description":"tasks module","type":"boolean"},"employees":{"description":"employees management (this module)","type":"boolean"},"restApi":{"description":"REST API keys","type":"boolean"},"onlineCheckIn":{"description":"online check-in","type":"boolean"},"smsConfiguration":{"description":"SMS configuration","type":"boolean"},"autoMessage":{"description":"automatic messages","type":"boolean"},"localTax":{"description":"local tax configuration","type":"boolean"},"ksef":{"description":"KSeF e-invoicing","type":"boolean"},"webbuilder":{"description":"website builder","type":"boolean"},"reviews":{"description":"OTA reviews","type":"boolean"},"locks":{"description":"door locks","type":"boolean"},"messaging":{"description":"unified inbox (messages)","type":"boolean"},"ereceipt":{"description":"e-receipts","type":"boolean"},"rooms":{"description":"Room restriction: room ids the employee may see (GET /rooms). EMPTY list = no restriction (all rooms).","type":"array","items":{"type":"integer"}}},"type":"object","additionalProperties":false},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]}}},"paths":{"/employees":{"get":{"tags":["employees"],"summary":"Get all employees with their complete permission sets","description":"Lists every active employee of the account together with the FULL permission object (employee and permissions are one resource, 1:1 — there are no separate permission endpoints). Each entry carries all permission flags (false = not granted) and `permissions.rooms` (room restriction; empty = all rooms). Passwords are never returned. OWNER-ONLY: this whole resource is available only to the account owner — employee tokens (AI agent / MCP) get 403 regardless of scopes, and no panel permission grants employees.* scopes to an employee. Required scope: `employees.read`.","operationId":"listEmployees","responses":{"200":{"description":"Employees","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeesListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}}}}}}}
```

## Create an employee together with their permissions

> Creates a panel account for an employee (login = \`email\`, must be unique across ALL mobile-calendar accounts — 409 when taken) and saves the permission set in the same request. Permissions omitted = every flag false and no room restriction; \`position\` is only an informational label and grants nothing by itself — enable the flags you need explicitly (e.g. a receptionist typically gets showReservation, addReservation, editReservation, dashboard, customerDatabase). \`permissions.rooms\` limits the employee to the listed rooms (ids from GET /rooms; empty = all rooms). Unknown fields ANYWHERE in the body — including inside \`permissions\` — are rejected with 422, so a mistyped flag can never pass silently. OWNER-ONLY (employee tokens get 403). Required scope: \`employees.create\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"employees","description":"Employees of the account together with their permission sets (one object, 1:1)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"EmployeeWriteRequest":{"description":"POST creates the employee together with the permission set (one object — permissions are 1:1 with the employee).","required":["email","password","forename","name"],"properties":{"email":{"description":"Login; must be unique across ALL mobile-calendar accounts (owners and employees) — 409 otherwise.","type":"string","maxLength":100},"password":{"description":"Write-only, never returned. Min 8 characters.","type":"string","maxLength":200,"minLength":8},"forename":{"type":"string","maxLength":100},"name":{"type":"string","maxLength":100},"position":{"description":"Informational label: 0 administrator, 1 receptionist, 2 housekeeper, 3 manager, 4 owner, 5 maintenance technician, 6 F&B manager. Does NOT grant permissions by itself — set the flags explicitly.","type":"integer","default":0,"enum":[0,1,2,3,4,5,6]},"lang":{"description":"Panel language code.","type":"string","default":"en"},"phone":{"description":"Digits, spaces and dashes only.","type":"string","maxLength":20},"phonePrefix":{"type":"string","nullable":true},"phoneCountry":{"type":"string","nullable":true},"permissions":{"$ref":"#/components/schemas/EmployeePermissions"}},"type":"object"},"EmployeePermissions":{"description":"Complete permission set of an employee — 1:1 with the panel's Uprawnienia screen. Every flag defaults to false; unknown keys are rejected with 422 (a typo in a flag name must not silently mean 'no permission'). `rooms` restricts the employee to specific rooms: empty list = access to ALL rooms.","properties":{"addRoom":{"description":"add rooms","type":"boolean"},"editRoom":{"description":"edit rooms (includes room photos)","type":"boolean"},"deleteRoom":{"description":"delete rooms","type":"boolean"},"filterRoom":{"description":"filter rooms","type":"boolean"},"addReservation":{"description":"add reservations","type":"boolean"},"showReservation":{"description":"view reservations","type":"boolean"},"editReservation":{"description":"edit reservations","type":"boolean"},"deleteReservation":{"description":"delete reservations","type":"boolean"},"editDeletePastReservations":{"description":"edit/delete past reservations","type":"boolean"},"registration":{"description":"guest check-in (meldunek)","type":"boolean"},"changeReservationPaymentStatus":{"description":"change reservation payment status","type":"boolean"},"searchReservation":{"description":"search reservations","type":"boolean"},"dashboard":{"description":"calendar / arrivals-departures view","type":"boolean"},"arrivalsDeparturesReport":{"description":"arrivals & departures report","type":"boolean"},"printCalendar":{"description":"print the calendar","type":"boolean"},"widget":{"description":"dashboard widgets","type":"boolean"},"customerDatabase":{"description":"client database (full CRUD)","type":"boolean"},"statistics":{"description":"statistics","type":"boolean"},"exportReservations":{"description":"export reservations","type":"boolean"},"importReservations":{"description":"import reservations","type":"boolean"},"searchAvailableRooms":{"description":"search available rooms","type":"boolean"},"pricing":{"description":"price lists (mobile-calendar + OTA channels + rate plans)","type":"boolean"},"reservations":{"description":"reservations module","type":"boolean"},"sendConfirmation":{"description":"send confirmations to guests","type":"boolean"},"messagesTemplates":{"description":"message templates","type":"boolean"},"smtpConfiguration":{"description":"SMTP configuration","type":"boolean"},"invoicing":{"description":"invoicing (full CRUD)","type":"boolean"},"editObjectData":{"description":"property data, regulations, privacy policy","type":"boolean"},"restoreReservation":{"description":"restore deleted reservations","type":"boolean"},"changeEmail":{"description":"change own e-mail","type":"boolean"},"changePassword":{"description":"change own password","type":"boolean"},"twoFactorAuth":{"description":"two-factor authentication","type":"boolean"},"editPersonalData":{"description":"account personal/invoicing data","type":"boolean"},"meals":{"description":"meals configuration (Restaurant)","type":"boolean"},"additionalServices":{"description":"additional services (full CRUD)","type":"boolean"},"onlineBookingEngine":{"description":"online booking engine","type":"boolean"},"googleCalendar":{"description":"Google Calendar","type":"boolean"},"booking":{"description":"channel manager (Booking.com/Airbnb/Slowhop/iCal)","type":"boolean"},"reservationSource":{"description":"reservation sources","type":"boolean"},"notifications":{"description":"notifications","type":"boolean"},"settings":{"description":"account settings","type":"boolean"},"buySubscription":{"description":"buy subscription","type":"boolean"},"showNewChanges":{"description":"changelog","type":"boolean"},"iCalendar":{"description":"iCalendar sync","type":"boolean"},"addTask":{"description":"add tasks","type":"boolean"},"changeRoomStatus":{"description":"change room status (clean/dirty)","type":"boolean"},"history":{"description":"change history (audit log)","type":"boolean"},"tasks":{"description":"tasks module","type":"boolean"},"employees":{"description":"employees management (this module)","type":"boolean"},"restApi":{"description":"REST API keys","type":"boolean"},"onlineCheckIn":{"description":"online check-in","type":"boolean"},"smsConfiguration":{"description":"SMS configuration","type":"boolean"},"autoMessage":{"description":"automatic messages","type":"boolean"},"localTax":{"description":"local tax configuration","type":"boolean"},"ksef":{"description":"KSeF e-invoicing","type":"boolean"},"webbuilder":{"description":"website builder","type":"boolean"},"reviews":{"description":"OTA reviews","type":"boolean"},"locks":{"description":"door locks","type":"boolean"},"messaging":{"description":"unified inbox (messages)","type":"boolean"},"ereceipt":{"description":"e-receipts","type":"boolean"},"rooms":{"description":"Room restriction: room ids the employee may see (GET /rooms). EMPTY list = no restriction (all rooms).","type":"array","items":{"type":"integer"}}},"type":"object","additionalProperties":false},"EmployeeResponse":{"required":["data"],"properties":{"data":{"required":["employee"],"properties":{"employee":{"$ref":"#/components/schemas/EmployeeEntry"}},"type":"object"},"meta":{"properties":{"devicesLoggedOut":{"description":"PATCH only: true when the e-mail or password change logged the employee out of all devices.","type":"boolean"}},"type":"object"}},"type":"object"},"EmployeeEntry":{"required":["employeeId","email","forename","name","position","positionName","lang","phone","phonePrefix","phoneCountry","avatar","portal","lastLogin","permissions"],"properties":{"employeeId":{"type":"integer"},"email":{"description":"Employee login.","type":"string"},"forename":{"type":"string"},"name":{"type":"string"},"position":{"type":"integer","enum":[0,1,2,3,4,5,6]},"positionName":{"type":"string","enum":["ADMINISTRATOR","RECEPTIONIST","HOUSEKEEPER","MANAGER","OWNER","MAINTENANCE_TECHNICIAN","FOOD_AND_BEVERAGE_MANAGER"]},"lang":{"description":"Panel language of the employee.","type":"string"},"phone":{"type":"string"},"phonePrefix":{"type":"string","nullable":true},"phoneCountry":{"type":"string","nullable":true},"avatar":{"description":"Avatar URL; managed in the panel (not via this API).","type":"string","nullable":true},"portal":{"description":"Read-only: 0 = full panel, 1 = limited housekeeper panel.","type":"integer"},"lastLogin":{"description":"Most recent login — the newest session in the panel's Employees → employee → Devices tab (falls back to the account's login timestamp when no session is recorded).","type":"string","format":"date-time","nullable":true},"lastActivity":{"description":"Last activity of any of the employee's sessions (last sync of the app/panel).","type":"string","format":"date-time","nullable":true},"devices":{"description":"GET /employees/{employeeId} only: the employee's sessions exactly as the Devices tab shows them, newest activity first. `ipAddress` is personal data — this resource is owner-only.","type":"array","items":{"properties":{"browser":{"type":"string","nullable":true},"system":{"type":"string","nullable":true},"platform":{"description":"desktop / ios / android","type":"string","nullable":true},"ipAddress":{"type":"string","nullable":true},"loggedInAt":{"type":"string","format":"date-time","nullable":true},"lastActivityAt":{"type":"string","format":"date-time","nullable":true}},"type":"object"}},"permissions":{"$ref":"#/components/schemas/EmployeePermissions"}},"type":"object"},"ApiProblem400":{"description":"Request syntax/format error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"400 Bad Request","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem409":{"description":"Conflict with resource state or integrity constraints.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"409 Conflict","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem422":{"description":"Input data validation error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"422 Unprocessable Entity (validation)","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"description":"Map: field name → error message(s)","type":"object","additionalProperties":{"$ref":"#/components/schemas/ErrorValue"}}},"type":"object"}]},"ErrorValue":{"description":"Single error message or list of messages.","oneOf":[{"description":"Error value in error map can be:\n- single string, or\n- array of strings (multiple messages for one field).","type":"string"},{"type":"array","items":{"type":"string"}}]}}},"paths":{"/employees":{"post":{"tags":["employees"],"summary":"Create an employee together with their permissions","description":"Creates a panel account for an employee (login = `email`, must be unique across ALL mobile-calendar accounts — 409 when taken) and saves the permission set in the same request. Permissions omitted = every flag false and no room restriction; `position` is only an informational label and grants nothing by itself — enable the flags you need explicitly (e.g. a receptionist typically gets showReservation, addReservation, editReservation, dashboard, customerDatabase). `permissions.rooms` limits the employee to the listed rooms (ids from GET /rooms; empty = all rooms). Unknown fields ANYWHERE in the body — including inside `permissions` — are rejected with 422, so a mistyped flag can never pass silently. OWNER-ONLY (employee tokens get 403). Required scope: `employees.create`.","operationId":"createEmployee","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeWriteRequest"}}}},"responses":{"201":{"description":"Employee created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeResponse"}}}},"400":{"description":"Malformed JSON body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem400"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"409":{"description":"An account with this e-mail already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem409"}}}},"422":{"description":"Validation error (unknown fields, bad flag name, unknown rooms)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem422"}}}}}}}}}
```

## Get one employee with their complete permission set

> Single employee of the account with the full permission object (see GET /employees), the last login / last activity and the list of the employee's sessions (\`devices\`: browser, system, IP, login time, last activity — the panel's Devices tab). OWNER-ONLY (employee tokens get 403). Required scope: \`employees.read\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"employees","description":"Employees of the account together with their permission sets (one object, 1:1)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"EmployeeResponse":{"required":["data"],"properties":{"data":{"required":["employee"],"properties":{"employee":{"$ref":"#/components/schemas/EmployeeEntry"}},"type":"object"},"meta":{"properties":{"devicesLoggedOut":{"description":"PATCH only: true when the e-mail or password change logged the employee out of all devices.","type":"boolean"}},"type":"object"}},"type":"object"},"EmployeeEntry":{"required":["employeeId","email","forename","name","position","positionName","lang","phone","phonePrefix","phoneCountry","avatar","portal","lastLogin","permissions"],"properties":{"employeeId":{"type":"integer"},"email":{"description":"Employee login.","type":"string"},"forename":{"type":"string"},"name":{"type":"string"},"position":{"type":"integer","enum":[0,1,2,3,4,5,6]},"positionName":{"type":"string","enum":["ADMINISTRATOR","RECEPTIONIST","HOUSEKEEPER","MANAGER","OWNER","MAINTENANCE_TECHNICIAN","FOOD_AND_BEVERAGE_MANAGER"]},"lang":{"description":"Panel language of the employee.","type":"string"},"phone":{"type":"string"},"phonePrefix":{"type":"string","nullable":true},"phoneCountry":{"type":"string","nullable":true},"avatar":{"description":"Avatar URL; managed in the panel (not via this API).","type":"string","nullable":true},"portal":{"description":"Read-only: 0 = full panel, 1 = limited housekeeper panel.","type":"integer"},"lastLogin":{"description":"Most recent login — the newest session in the panel's Employees → employee → Devices tab (falls back to the account's login timestamp when no session is recorded).","type":"string","format":"date-time","nullable":true},"lastActivity":{"description":"Last activity of any of the employee's sessions (last sync of the app/panel).","type":"string","format":"date-time","nullable":true},"devices":{"description":"GET /employees/{employeeId} only: the employee's sessions exactly as the Devices tab shows them, newest activity first. `ipAddress` is personal data — this resource is owner-only.","type":"array","items":{"properties":{"browser":{"type":"string","nullable":true},"system":{"type":"string","nullable":true},"platform":{"description":"desktop / ios / android","type":"string","nullable":true},"ipAddress":{"type":"string","nullable":true},"loggedInAt":{"type":"string","format":"date-time","nullable":true},"lastActivityAt":{"type":"string","format":"date-time","nullable":true}},"type":"object"}},"permissions":{"$ref":"#/components/schemas/EmployeePermissions"}},"type":"object"},"EmployeePermissions":{"description":"Complete permission set of an employee — 1:1 with the panel's Uprawnienia screen. Every flag defaults to false; unknown keys are rejected with 422 (a typo in a flag name must not silently mean 'no permission'). `rooms` restricts the employee to specific rooms: empty list = access to ALL rooms.","properties":{"addRoom":{"description":"add rooms","type":"boolean"},"editRoom":{"description":"edit rooms (includes room photos)","type":"boolean"},"deleteRoom":{"description":"delete rooms","type":"boolean"},"filterRoom":{"description":"filter rooms","type":"boolean"},"addReservation":{"description":"add reservations","type":"boolean"},"showReservation":{"description":"view reservations","type":"boolean"},"editReservation":{"description":"edit reservations","type":"boolean"},"deleteReservation":{"description":"delete reservations","type":"boolean"},"editDeletePastReservations":{"description":"edit/delete past reservations","type":"boolean"},"registration":{"description":"guest check-in (meldunek)","type":"boolean"},"changeReservationPaymentStatus":{"description":"change reservation payment status","type":"boolean"},"searchReservation":{"description":"search reservations","type":"boolean"},"dashboard":{"description":"calendar / arrivals-departures view","type":"boolean"},"arrivalsDeparturesReport":{"description":"arrivals & departures report","type":"boolean"},"printCalendar":{"description":"print the calendar","type":"boolean"},"widget":{"description":"dashboard widgets","type":"boolean"},"customerDatabase":{"description":"client database (full CRUD)","type":"boolean"},"statistics":{"description":"statistics","type":"boolean"},"exportReservations":{"description":"export reservations","type":"boolean"},"importReservations":{"description":"import reservations","type":"boolean"},"searchAvailableRooms":{"description":"search available rooms","type":"boolean"},"pricing":{"description":"price lists (mobile-calendar + OTA channels + rate plans)","type":"boolean"},"reservations":{"description":"reservations module","type":"boolean"},"sendConfirmation":{"description":"send confirmations to guests","type":"boolean"},"messagesTemplates":{"description":"message templates","type":"boolean"},"smtpConfiguration":{"description":"SMTP configuration","type":"boolean"},"invoicing":{"description":"invoicing (full CRUD)","type":"boolean"},"editObjectData":{"description":"property data, regulations, privacy policy","type":"boolean"},"restoreReservation":{"description":"restore deleted reservations","type":"boolean"},"changeEmail":{"description":"change own e-mail","type":"boolean"},"changePassword":{"description":"change own password","type":"boolean"},"twoFactorAuth":{"description":"two-factor authentication","type":"boolean"},"editPersonalData":{"description":"account personal/invoicing data","type":"boolean"},"meals":{"description":"meals configuration (Restaurant)","type":"boolean"},"additionalServices":{"description":"additional services (full CRUD)","type":"boolean"},"onlineBookingEngine":{"description":"online booking engine","type":"boolean"},"googleCalendar":{"description":"Google Calendar","type":"boolean"},"booking":{"description":"channel manager (Booking.com/Airbnb/Slowhop/iCal)","type":"boolean"},"reservationSource":{"description":"reservation sources","type":"boolean"},"notifications":{"description":"notifications","type":"boolean"},"settings":{"description":"account settings","type":"boolean"},"buySubscription":{"description":"buy subscription","type":"boolean"},"showNewChanges":{"description":"changelog","type":"boolean"},"iCalendar":{"description":"iCalendar sync","type":"boolean"},"addTask":{"description":"add tasks","type":"boolean"},"changeRoomStatus":{"description":"change room status (clean/dirty)","type":"boolean"},"history":{"description":"change history (audit log)","type":"boolean"},"tasks":{"description":"tasks module","type":"boolean"},"employees":{"description":"employees management (this module)","type":"boolean"},"restApi":{"description":"REST API keys","type":"boolean"},"onlineCheckIn":{"description":"online check-in","type":"boolean"},"smsConfiguration":{"description":"SMS configuration","type":"boolean"},"autoMessage":{"description":"automatic messages","type":"boolean"},"localTax":{"description":"local tax configuration","type":"boolean"},"ksef":{"description":"KSeF e-invoicing","type":"boolean"},"webbuilder":{"description":"website builder","type":"boolean"},"reviews":{"description":"OTA reviews","type":"boolean"},"locks":{"description":"door locks","type":"boolean"},"messaging":{"description":"unified inbox (messages)","type":"boolean"},"ereceipt":{"description":"e-receipts","type":"boolean"},"rooms":{"description":"Room restriction: room ids the employee may see (GET /rooms). EMPTY list = no restriction (all rooms).","type":"array","items":{"type":"integer"}}},"type":"object","additionalProperties":false},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem404":{"description":"Resource specified in the request was not found.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"404 Not Found","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]}}},"paths":{"/employees/{employeeId}":{"get":{"tags":["employees"],"summary":"Get one employee with their complete permission set","description":"Single employee of the account with the full permission object (see GET /employees), the last login / last activity and the list of the employee's sessions (`devices`: browser, system, IP, login time, last activity — the panel's Devices tab). OWNER-ONLY (employee tokens get 403). Required scope: `employees.read`.","operationId":"getEmployee","parameters":[{"name":"employeeId","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Employee","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"404":{"description":"Employee not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}}}}}}}
```

## Delete an employee (deactivate the account, remove permissions and devices)

> Soft-deletes the employee exactly like the panel: the account is deactivated (the e-mail is released and can be reused), the permission set is removed and every logged-in device is disconnected. Reservations, history entries and other data created by the employee remain untouched. This cannot be undone through the API. OWNER-ONLY (employee tokens get 403). Required scope: \`employees.delete\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"employees","description":"Employees of the account together with their permission sets (one object, 1:1)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem404":{"description":"Resource specified in the request was not found.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"404 Not Found","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]}}},"paths":{"/employees/{employeeId}":{"delete":{"tags":["employees"],"summary":"Delete an employee (deactivate the account, remove permissions and devices)","description":"Soft-deletes the employee exactly like the panel: the account is deactivated (the e-mail is released and can be reused), the permission set is removed and every logged-in device is disconnected. Reservations, history entries and other data created by the employee remain untouched. This cannot be undone through the API. OWNER-ONLY (employee tokens get 403). Required scope: `employees.delete`.","operationId":"deleteEmployee","parameters":[{"name":"employeeId","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"description":"Employee deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"404":{"description":"Employee not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}}}}}}}
```

## Update an employee and/or their permissions

> Partial update — send only what changes. Personal fields (\`forename\`, \`name\`, \`position\`, \`lang\`, \`phone\`, \`phonePrefix\`, \`phoneCountry\`) replace their values. Permission flags MERGE into the current set: only the flags present in \`permissions\` change, the rest keep their value; \`permissions.rooms\` replaces the whole room restriction when sent (empty list = lift the restriction). Changing \`email\` (409 when taken) or \`password\` additionally LOGS THE EMPLOYEE OUT of every device immediately (\`meta.devicesLoggedOut: true\`) — they must sign in again. OWNER-ONLY (employee tokens get 403). Required scope: \`employees.update\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"employees","description":"Employees of the account together with their permission sets (one object, 1:1)."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"EmployeeUpdateRequest":{"description":"Partial update — every field is optional and only the fields you send change. Permission flags MERGE into the current set (flags not listed keep their value); `permissions.rooms` replaces the whole room restriction when sent. Sending `email` or `password` immediately logs the employee out of every device, so omit them unless you really mean to change them.","properties":{"email":{"description":"Login; must be unique across ALL mobile-calendar accounts (owners and employees) — 409 otherwise.","type":"string","maxLength":100},"password":{"description":"Write-only, never returned. Min 8 characters.","type":"string","maxLength":200,"minLength":8},"forename":{"type":"string","maxLength":100},"name":{"type":"string","maxLength":100},"position":{"description":"Informational label: 0 administrator, 1 receptionist, 2 housekeeper, 3 manager, 4 owner, 5 maintenance technician, 6 F&B manager. Does NOT grant permissions by itself — set the flags explicitly.","type":"integer","default":0,"enum":[0,1,2,3,4,5,6]},"lang":{"description":"Panel language code.","type":"string","default":"en"},"phone":{"description":"Digits, spaces and dashes only.","type":"string","maxLength":20},"phonePrefix":{"type":"string","nullable":true},"phoneCountry":{"type":"string","nullable":true},"permissions":{"$ref":"#/components/schemas/EmployeePermissions"}},"type":"object"},"EmployeePermissions":{"description":"Complete permission set of an employee — 1:1 with the panel's Uprawnienia screen. Every flag defaults to false; unknown keys are rejected with 422 (a typo in a flag name must not silently mean 'no permission'). `rooms` restricts the employee to specific rooms: empty list = access to ALL rooms.","properties":{"addRoom":{"description":"add rooms","type":"boolean"},"editRoom":{"description":"edit rooms (includes room photos)","type":"boolean"},"deleteRoom":{"description":"delete rooms","type":"boolean"},"filterRoom":{"description":"filter rooms","type":"boolean"},"addReservation":{"description":"add reservations","type":"boolean"},"showReservation":{"description":"view reservations","type":"boolean"},"editReservation":{"description":"edit reservations","type":"boolean"},"deleteReservation":{"description":"delete reservations","type":"boolean"},"editDeletePastReservations":{"description":"edit/delete past reservations","type":"boolean"},"registration":{"description":"guest check-in (meldunek)","type":"boolean"},"changeReservationPaymentStatus":{"description":"change reservation payment status","type":"boolean"},"searchReservation":{"description":"search reservations","type":"boolean"},"dashboard":{"description":"calendar / arrivals-departures view","type":"boolean"},"arrivalsDeparturesReport":{"description":"arrivals & departures report","type":"boolean"},"printCalendar":{"description":"print the calendar","type":"boolean"},"widget":{"description":"dashboard widgets","type":"boolean"},"customerDatabase":{"description":"client database (full CRUD)","type":"boolean"},"statistics":{"description":"statistics","type":"boolean"},"exportReservations":{"description":"export reservations","type":"boolean"},"importReservations":{"description":"import reservations","type":"boolean"},"searchAvailableRooms":{"description":"search available rooms","type":"boolean"},"pricing":{"description":"price lists (mobile-calendar + OTA channels + rate plans)","type":"boolean"},"reservations":{"description":"reservations module","type":"boolean"},"sendConfirmation":{"description":"send confirmations to guests","type":"boolean"},"messagesTemplates":{"description":"message templates","type":"boolean"},"smtpConfiguration":{"description":"SMTP configuration","type":"boolean"},"invoicing":{"description":"invoicing (full CRUD)","type":"boolean"},"editObjectData":{"description":"property data, regulations, privacy policy","type":"boolean"},"restoreReservation":{"description":"restore deleted reservations","type":"boolean"},"changeEmail":{"description":"change own e-mail","type":"boolean"},"changePassword":{"description":"change own password","type":"boolean"},"twoFactorAuth":{"description":"two-factor authentication","type":"boolean"},"editPersonalData":{"description":"account personal/invoicing data","type":"boolean"},"meals":{"description":"meals configuration (Restaurant)","type":"boolean"},"additionalServices":{"description":"additional services (full CRUD)","type":"boolean"},"onlineBookingEngine":{"description":"online booking engine","type":"boolean"},"googleCalendar":{"description":"Google Calendar","type":"boolean"},"booking":{"description":"channel manager (Booking.com/Airbnb/Slowhop/iCal)","type":"boolean"},"reservationSource":{"description":"reservation sources","type":"boolean"},"notifications":{"description":"notifications","type":"boolean"},"settings":{"description":"account settings","type":"boolean"},"buySubscription":{"description":"buy subscription","type":"boolean"},"showNewChanges":{"description":"changelog","type":"boolean"},"iCalendar":{"description":"iCalendar sync","type":"boolean"},"addTask":{"description":"add tasks","type":"boolean"},"changeRoomStatus":{"description":"change room status (clean/dirty)","type":"boolean"},"history":{"description":"change history (audit log)","type":"boolean"},"tasks":{"description":"tasks module","type":"boolean"},"employees":{"description":"employees management (this module)","type":"boolean"},"restApi":{"description":"REST API keys","type":"boolean"},"onlineCheckIn":{"description":"online check-in","type":"boolean"},"smsConfiguration":{"description":"SMS configuration","type":"boolean"},"autoMessage":{"description":"automatic messages","type":"boolean"},"localTax":{"description":"local tax configuration","type":"boolean"},"ksef":{"description":"KSeF e-invoicing","type":"boolean"},"webbuilder":{"description":"website builder","type":"boolean"},"reviews":{"description":"OTA reviews","type":"boolean"},"locks":{"description":"door locks","type":"boolean"},"messaging":{"description":"unified inbox (messages)","type":"boolean"},"ereceipt":{"description":"e-receipts","type":"boolean"},"rooms":{"description":"Room restriction: room ids the employee may see (GET /rooms). EMPTY list = no restriction (all rooms).","type":"array","items":{"type":"integer"}}},"type":"object","additionalProperties":false},"EmployeeResponse":{"required":["data"],"properties":{"data":{"required":["employee"],"properties":{"employee":{"$ref":"#/components/schemas/EmployeeEntry"}},"type":"object"},"meta":{"properties":{"devicesLoggedOut":{"description":"PATCH only: true when the e-mail or password change logged the employee out of all devices.","type":"boolean"}},"type":"object"}},"type":"object"},"EmployeeEntry":{"required":["employeeId","email","forename","name","position","positionName","lang","phone","phonePrefix","phoneCountry","avatar","portal","lastLogin","permissions"],"properties":{"employeeId":{"type":"integer"},"email":{"description":"Employee login.","type":"string"},"forename":{"type":"string"},"name":{"type":"string"},"position":{"type":"integer","enum":[0,1,2,3,4,5,6]},"positionName":{"type":"string","enum":["ADMINISTRATOR","RECEPTIONIST","HOUSEKEEPER","MANAGER","OWNER","MAINTENANCE_TECHNICIAN","FOOD_AND_BEVERAGE_MANAGER"]},"lang":{"description":"Panel language of the employee.","type":"string"},"phone":{"type":"string"},"phonePrefix":{"type":"string","nullable":true},"phoneCountry":{"type":"string","nullable":true},"avatar":{"description":"Avatar URL; managed in the panel (not via this API).","type":"string","nullable":true},"portal":{"description":"Read-only: 0 = full panel, 1 = limited housekeeper panel.","type":"integer"},"lastLogin":{"description":"Most recent login — the newest session in the panel's Employees → employee → Devices tab (falls back to the account's login timestamp when no session is recorded).","type":"string","format":"date-time","nullable":true},"lastActivity":{"description":"Last activity of any of the employee's sessions (last sync of the app/panel).","type":"string","format":"date-time","nullable":true},"devices":{"description":"GET /employees/{employeeId} only: the employee's sessions exactly as the Devices tab shows them, newest activity first. `ipAddress` is personal data — this resource is owner-only.","type":"array","items":{"properties":{"browser":{"type":"string","nullable":true},"system":{"type":"string","nullable":true},"platform":{"description":"desktop / ios / android","type":"string","nullable":true},"ipAddress":{"type":"string","nullable":true},"loggedInAt":{"type":"string","format":"date-time","nullable":true},"lastActivityAt":{"type":"string","format":"date-time","nullable":true}},"type":"object"}},"permissions":{"$ref":"#/components/schemas/EmployeePermissions"}},"type":"object"},"ApiProblem400":{"description":"Request syntax/format error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"400 Bad Request","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem404":{"description":"Resource specified in the request was not found.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"404 Not Found","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem409":{"description":"Conflict with resource state or integrity constraints.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"409 Conflict","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblem422":{"description":"Input data validation error.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"422 Unprocessable Entity (validation)","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"description":"Map: field name → error message(s)","type":"object","additionalProperties":{"$ref":"#/components/schemas/ErrorValue"}}},"type":"object"}]},"ErrorValue":{"description":"Single error message or list of messages.","oneOf":[{"description":"Error value in error map can be:\n- single string, or\n- array of strings (multiple messages for one field).","type":"string"},{"type":"array","items":{"type":"string"}}]}}},"paths":{"/employees/{employeeId}":{"patch":{"tags":["employees"],"summary":"Update an employee and/or their permissions","description":"Partial update — send only what changes. Personal fields (`forename`, `name`, `position`, `lang`, `phone`, `phonePrefix`, `phoneCountry`) replace their values. Permission flags MERGE into the current set: only the flags present in `permissions` change, the rest keep their value; `permissions.rooms` replaces the whole room restriction when sent (empty list = lift the restriction). Changing `email` (409 when taken) or `password` additionally LOGS THE EMPLOYEE OUT of every device immediately (`meta.devicesLoggedOut: true`) — they must sign in again. OWNER-ONLY (employee tokens get 403). Required scope: `employees.update`.","operationId":"updateEmployee","parameters":[{"name":"employeeId","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeUpdateRequest"}}}},"responses":{"200":{"description":"Employee updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmployeeResponse"}}}},"400":{"description":"Malformed JSON body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem400"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}},"404":{"description":"Employee not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem404"}}}},"409":{"description":"An account with this e-mail already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem409"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem422"}}}}}}}}}
```
