User work shifts
Create a user work shift
/a/UserWorkShift_createData
Append a work-shift definition to a user’s effective shift rows and save the resulting version-2 schedule in user metadata.
When to use this endpoint
Use UserWorkShift_createData for CRM2’s Work Shifts create form. For replacing an entire schedule or restoring the company default, use the related user-level setter.
Authentication and permissions
The request must authenticate with signed API-key fields or a logged-in CRM session, and the tenant’s disableHREnhancements feature must not be enabled.
The handler does not check pageUserWorkShifts_add, Users edit permission, target ownership, or whether the target user is active. UI access controls are not server enforcement.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
userID / user_id | Integer string | Yes | Target tenant user. userID takes precedence and must integer-convert above zero. |
days | Native array, JSON array text, comma text, or scalar | Yes in practice | Weekday numbers 0 Sunday through 6 Saturday. Values are integer-converted, de-duplicated, range-filtered, and retain first-seen order. At least one must remain. |
start / end | HH:MM text or numeric seconds after midnight | Yes | Shift bounds. Text accepts one/two-digit hours and two-digit minutes at the start of the value. Numeric input is treated as seconds, not hours. Equal bounds are invalid; end before start represents an overnight shift. |
lunchDuration / lunch_duration | Integer minutes | No | Positive values enable a lunch window and are stored as seconds. Negative values become zero. Camel-case takes precedence. |
lunchEarliest / lunch_earliest | HH:MM text or numeric seconds | When lunch duration is positive | Earliest lunch start within the possibly overnight shift. Camel-case takes precedence. |
lunchLatest / lunch_latest | HH:MM text or numeric seconds | When lunch duration is positive | Latest lunch start; the wrapped window must fit the duration and remain within the shift. |
Example request
$created = FM_api('UserWorkShift_createData', [
'userID' => '18',
'days' => ['1', '2', '3', '4', '5'],
'start' => '08:30',
'end' => '17:00',
'lunchDuration' => '30',
'lunchEarliest' => '12:00',
'lunchLatest' => '14:00',
]);
Example response
{
"ok": 1,
"id": 18002
}
Errors and unusual responses
| Response | Condition |
|---|---|
{"error":"not logged in"} | No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs. |
{"error":"HR enhancements are disabled"} | The controlling parent-employer/session feature flag equals 1. |
{"error":"missing or invalid parameter: userID"} | Neither user alias resolves above zero. |
{"error":"user does not exist"} | No tenant user has the target ID. |
{"error":"invalid shift start/end time"} | A bound cannot be parsed or the resulting schedule has an invalid/equal bound. |
{"error":"each shift must include at least one day"} | No valid weekday remains on the new or existing normalized shift. |
{"error":"invalid lunch time"} | A positive lunch has an unparseable/out-of-range window bound. |
{"error":"lunch window must fit within the shift"} | The wrapped lunch window lies outside the shift or is shorter than the requested duration. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- The returned ID is synthetic:
userID * 1000 + zeroBasedIndex + 1. It is not a database primary key and can change when earlier rows are deleted. - Schedules are saved as
{"version":2,"shifts":[...]}. Multiple shifts may cover the same day or overlap; validation does not reject those combinations. - When lunch duration is zero, lunch-bound parameters are ignored and no lunch fields are stored. End value
86400is permitted but renders as00:00, making a later display round-trip ambiguous. - Company fallback derives from
work-day-start/work-day-endminute settings andweek-days-off. Shift consumers apply the tenanttimezone, falling back to UTC for blank/invalid zones.
Side effects
- Replaces the user’s complete
meta.work_hours, preserving other metadata, sets currentlast_edited, setsedited_uuid="UserWorkShift", and invalidates the users cache. - Does not create generic audit history. The metadata read/replace/write is not protected against concurrent changes.
See it in Fieldmotion
CRM1
No direct CRM1 caller was found.
CRM2
Open a user and select Work Shifts → Create. The shared display widget calls this route.
Related endpoints
UserWorkShifts_getDataTablelists effective rows and their synthetic IDs.User_setWorkShiftsreplaces/clears the whole schedule and returns explicit fallback metadata.