# User

A user: one member of the organisation, as plnnrly's people list shows them. Read-only: the API creates, updates and deletes no user, because password setting belongs to the invitation and reset flows and because roles, permissions and teams are out of scope as resources and as writable relations. Service accounts are never returned: a system user is absent from the collection and `404` by id. A soft-deleted user stays readable with `trashed=with`, which is how a sync client learns an employee left.

## Used by
- GET /api/v2/me: Read the token owner (User)
- GET /api/v2/users: List users (UserList)
- GET /api/v2/users/{user}: Read a user (User)

## User fields
- id (integer, required): Unique identifier.
- name (string ≤ 255, required): Full name as shown throughout plnnrly. Searchable with `?q=`.
- email (string ≤ 255, required): Work email address, unique within the organisation. Searchable with `?q=`, which is the practical way to resolve a person to an id.
- color (string ≤ 255, required): The user's identifying colour, as a CSS colour string. Used by plnnrly's calendars and avatars; render it or ignore it.
- job_title (string ≤ 255, required): Job title, e.g. Project Manager.
- phone_number (string or null ≤ 255, required): Phone number as entered, in no normalised format.
- timezone (string or null ≤ 255, required): The user's own IANA timezone, e.g. Europe/Amsterdam. Null means the organisation's default applies. Every timestamp in this API is UTC regardless; this is the zone a client renders them in for this person.
- date_employed (date (YYYY-MM-DD) or null, required): First day of employment, or `null` where it was never recorded. A calendar date with no clock, so it is never converted to UTC.
- birthday (date (YYYY-MM-DD) or null, required): Date of birth, or `null` where it was never recorded.
- profitability_target_percentage (integer or null, required): Share of available hours this person is expected to bill, 1 to 100, or `null` where no target is set. Read by the profitability report; a user without a target is still reported on, just not judged against one.
- working_hours (array of object or null, required, detail only): The contracted working week, one entry per shift, in week order. A weekday may carry several entries (a split day is two ranges), and a weekday that is not worked simply has none. Null or empty means no schedule has been recorded.
  - day (string or null ≤ 9, optional): Weekday the shift falls on: one of monday, tuesday, wednesday, thursday, friday, saturday, sunday.
  - start_time (string or null ≤ 5, optional): Shift start as `HH:MM`.
  - end_time (string or null ≤ 5, optional): Shift end as `HH:MM`, always after the start. A shift never wraps past midnight: a night shift is two entries, 22:00-24:00 on one day and 00:00-06:00 on the next.
- work_locations (object, required, detail only): Where the user usually works on each weekday, keyed monday through sunday. The stored pattern lists only the days away from the office, so a weekday it does not name reads as office here. A single day's override from the agenda is not reflected.
  - monday (string, required): Monday.
  - tuesday (string, required): Tuesday.
  - wednesday (string, required): Wednesday.
  - thursday (string, required): Thursday.
  - friday (string, required): Friday.
  - saturday (string, required): Saturday.
  - sunday (string, required): Sunday.
- created_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): Creation timestamp.
- updated_at (timestamp (YYYY-MM-DDThh:mm:ssZ), required): Last-write timestamp; use for incremental sync.
- deleted_at (timestamp (YYYY-MM-DDThh:mm:ssZ) or null, required): Soft-delete timestamp, `null` while the user is active.
- links (UserLinks, required)
  - self (url, required): The canonical URI of this record.

Only on `?view=detail`: working_hours, work_locations

## Variants

### UserList

What a collection returns, and what `?view=summary` returns on a single record.

14 fields.
Omits: working_hours, work_locations

### UserSummary

The embedded form: what you get when another resource carries this one and you did not `include` it.

2 fields.
Omits: email, color, job_title, phone_number, timezone, date_employed, birthday, profitability_target_percentage, working_hours, work_locations, created_at, updated_at, deleted_at, links

### UserLinks

The `links` object on this resource.

Keys: self

## Columns deliberately not published
- infoscreen: The user's info screen choice in plnnrly; meaningless to an API client.
- settings: Per-user display preferences of the plnnrly app, with no meaning for an API client.

## Example
```json
{
  "id": 1,
  "name": "…",
  "email": "…",
  "color": "…",
  "job_title": "…",
  "phone_number": "…",
  "timezone": "…",
  "date_employed": "2026-03-04",
  "birthday": "2026-03-04",
  "profitability_target_percentage": 1,
  "working_hours": [
    {
      "…": "3 optional fields left out"
    }
  ],
  "work_locations": {
    "monday": "office",
    "tuesday": "office",
    "wednesday": "office",
    "thursday": "office",
    "friday": "office",
    "saturday": "office",
    "sunday": "office"
  },
  "created_at": "2026-03-04T09:15:00Z",
  "updated_at": "2026-03-04T09:15:00Z",
  "deleted_at": "2026-03-04T09:15:00Z",
  "links": {
    "self": "https://<your-url>/api/v2/work-items/1"
  }
}
```
