Employee availability
Employee availability determines when employees can and cannot be scheduled for shifts. Employees may need days off (or parts of days) when they have other commitments, such as medical appointments or caring for family members. Employees also have vacation days (or PTO), public holidays, and other paid days off.
Contractors might only be required or available for certain periods of time.
For an employee shift schedule to be feasible, the employee shift scheduling solution must include this availability information.
This guide explains how to manage employee availability with the following examples:
Prerequisites
To run the examples in this guide, you need to authenticate with a valid API key:
-
Log in to Timefold Platform: app.timefold.ai
-
From the Dashboard, click your username, and from the drop-down menu select API Keys.
-
Copy the default API key.
In the examples, replace <API_KEY>
with the API Key you just copied.
The times displayed in the visualizations are approximates only. |
1. Employee unavailability times
Employees are considered to be available for any shifts in the schedule unless unavailable time spans are defined.
Beth is a full-time employee and is generally available for any shift, however, on Friday she has a commitment that means she is not available to cover a shift.
An employee’s unavailability is defined by adding an unavailableTimeSpans
array to the employee with a start
and an end
time for the period they are unavailable.
Unavailable periods can span multiple days.
"employees": [
{
"id": "Beth",
"unavailableTimeSpans": [
{
"start": "2027-02-05T00:00:00Z",
"end": "2027-02-06T00:00:00Z"
}
]
}
]
-
start
is a date and time (in ISO 8601 date time with offset to UTC format) for the start of the period the employee is unavailable. -
end
is a date and time in ISO 8601 with date time offset to UTC for the end of the period the employee is unavailable.
-
Input
-
Output
Try this example in Timefold Platform by saving this JSON into a file called sample.json and make the following API call:
|
curl -X POST -H "Content-type: application/json" -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/employee-scheduling/v1/schedules [email protected]
{
"config": {
"run": {
"name": "Unavailability example"
}
},
"modelInput": {
"employees": [
{
"id": "Beth",
"unavailableTimeSpans": [
{
"start": "2027-02-05T00:00:00Z",
"end": "2027-02-06T00:00:00Z"
}
]
}
],
"shifts": [
{
"id": "2027-02-01",
"start": "2027-02-01T09:00:00Z",
"end": "2027-02-01T17:00:00Z"
},
{
"id": "2027-02-02",
"start": "2027-02-02T09:00:00Z",
"end": "2027-02-02T17:00:00Z"
},
{
"id": "2027-02-03",
"start": "2027-02-03T09:00:00Z",
"end": "2027-02-03T17:00:00Z"
},
{
"id": "2027-02-04",
"start": "2027-02-04T09:00:00Z",
"end": "2027-02-04T17:00:00Z"
},
{
"id": "2027-02-05",
"start": "2027-02-05T09:00:00Z",
"end": "2027-02-05T17:00:00Z"
}
]
}
}
To request the solution, locate the 'ID' from the response to the post operation and append it to the following API call: |
curl -X GET -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/employee-scheduling/v1/schedules/<ID>
{
"run": {
"id": ID,
"name": "Unavailability example",
"submitDateTime": "2024-09-12T09:45:46.822999677Z",
"startDateTime": "2024-09-12T09:45:52.628925423Z",
"completeDateTime": "2024-09-12T09:50:53.058023049Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/-10000medium/0soft",
"tags": null,
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"shifts": [
{
"id": "2027-02-01",
"employee": "Beth"
},
{
"id": "2027-02-02",
"employee": "Beth"
},
{
"id": "2027-02-03",
"employee": "Beth"
},
{
"id": "2027-02-04",
"employee": "Beth"
},
{
"id": "2027-02-05",
"employee": null
}
]
},
"kpis": {
"unassignedShifts": 1
}
}
modelOutput
contains the employee shift schedule with Beth assigned to the shifts when she is available.
In this example, the Friday shift is left unassigned. Timefold will assign shifts to employees who are available, however, assigning the shift to Beth would break a hard constraint and make the plan infeasible. Leaving the shift unassigned breaks a medium constraint but the plan is still feasible.
Learn about the hard, medium, and soft constraints in Employee Shift Scheduling model. |
2. Employee availability times
Not all employees work full time for a company. Contractors might only be required or are only available for certain periods of time.
Carl is a contractor who works when Beth is unavailable.
An employee’s availability can be defined by adding an availableTimeSpans
array to the employee with a start
and an end
time for the period they are available.
Available periods can span multiple days.
"employees": [
{
"id": "Carl",
"availableTimeSpans": [
{
"start": "2027-02-02T00:00:00Z",
"end": "2027-02-06T00:00:00Z"
}
]
}
]
-
start
is a date and time (in ISO 8601 date time with offset to UTC format) for the start of the period the employee is available. -
end
is a date and time in ISO 8601 with date time offset to UTC for the end of the period the employee is available.
Defining either availableTimeSpans
or unavailableTimeSpans
results in times when an employee is both available and also unavailable. With availableTimeSpans
any time that is not included is time when the employee is unavailable, and with unavailableTimeSpans
any time that is not included is time when the employee is available.
We recommend using:
-
unavailableTimeSpans
for full-time employees who are usually available for any shift and have occasional periods of unavailability. -
availableTimeSpans
for contractors who are only available for specific periods of time.
-
Input
-
Output
Try this example in Timefold Platform by saving this JSON into a file called sample.json and make the following API call:
|
curl -X POST -H "Content-type: application/json" -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/employee-scheduling/v1/schedules [email protected]
{
"config": {
"run": {
"name": "Availability example"
}
},
"modelInput": {
"employees": [
{
"id": "Beth",
"unavailableTimeSpans": [
{
"start": "2027-02-02T00:00:00Z",
"end": "2027-02-08T00:00:00Z"
}
]
},
{
"id": "Carl",
"availableTimeSpans": [
{
"start": "2027-02-02T00:00:00Z",
"end": "2027-02-06T00:00:00Z"
}
]
}
],
"shifts": [
{
"id": "2027-02-01",
"start": "2027-02-01T09:00:00Z",
"end": "2027-02-01T17:00:00Z"
},
{
"id": "2027-02-02",
"start": "2027-02-02T09:00:00Z",
"end": "2027-02-02T17:00:00Z"
},
{
"id": "2027-02-03",
"start": "2027-02-03T09:00:00Z",
"end": "2027-02-03T17:00:00Z"
},
{
"id": "2027-02-04",
"start": "2027-02-04T09:00:00Z",
"end": "2027-02-04T17:00:00Z"
},
{
"id": "2027-02-05",
"start": "2027-02-05T09:00:00Z",
"end": "2027-02-05T17:00:00Z"
}
]
}
}
To request the solution, locate the 'ID' from the response to the post operation and append it to the following API call: |
curl -X GET -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/employee-scheduling/v1/schedules/<ID>
{
"run": {
"id": ID,
"name": "Availability example",
"submitDateTime": "2024-09-12T09:55:53.15634866Z",
"startDateTime": "2024-09-12T09:55:58.934451453Z",
"completeDateTime": "2024-09-12T10:00:59.512605369Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/0soft",
"tags": null,
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"shifts": [
{
"id": "2027-02-01",
"employee": "Beth"
},
{
"id": "2027-02-02",
"employee": "Carl"
},
{
"id": "2027-02-03",
"employee": "Carl"
},
{
"id": "2027-02-04",
"employee": "Carl"
},
{
"id": "2027-02-05",
"employee": "Carl"
}
]
},
"kpis": {
"unassignedShifts": 0
}
}
modelOutput
contains the employee shift schedule with Beth and Carl assigned to shifts that match their availability as defined by Ann’s unavailableTimeSpan
and Carl’s availableTimeSpan
.
3. Filtering shift assignments with tags
Tags can be added to availableTimeSpans
and unavailableTimeSpans
to control which shifts the availability time spans apply to.
For instance, Beth is unavailable for a week, and her shifts must be assigned to a contractor to avoid assigning another full-time employee (and leaving that employee’s regular shifts unassigned).
The contractor who is assigned the shifts must be able to travel to the company’s central office.
Beth’s regular shifts are tagged with "location central"
:
"shifts": [
{
"id": "2027-02-01",
"start": "2027-02-01T09:00:00Z",
"end": "2027-02-01T17:00:00Z",
"tags": [
"location central"
]
}
Carl and Ann are both available.
Carl can travel to the central office and his availability includes "includeShiftTags": [ "location central" ]
.
Ann is also available, but she cannot travel to the central office, so her availability includes "excludeShiftTags": [ "location central" ]
.
includeShiftTags and excludeShiftTags can both be used in the same dataset, but they cannot be used in combination. ie, because Carl’s availableTimeSpans uses includeShiftTags it cannot also use excludeShiftTags . Similarly, because Ann’s availableTimeSpans uses excludeShiftTags it cannot also use includeShiftTags .
|
"employees": [
{
"id": "Beth",
"unavailableTimeSpans": [
{
"start": "2027-02-01T00:00:00Z",
"end": "2027-02-06T00:00:00Z"
}
]
},
{
"id": "Carl",
"availableTimeSpans": [
{
"start": "2027-02-02T00:00:00Z",
"end": "2027-02-06T00:00:00Z",
"includeShiftTags": [ "location central" ]
}
]
},
{
"id": "Ann",
"availableTimeSpans": [
{
"start": "2027-02-02T00:00:00Z",
"end": "2027-02-06T00:00:00Z",
"excludeShiftTags": [ "location central" ]
}
]
}
]
In this instance, Carl is assigned the shifts because he can travel to the central office, however, Carl isn’t available for the Monday shift. Even though Ann is available on Monday, she cannot travel to the central office, and she is not assigned the shift.
-
Input
-
Output
Try this example in Timefold Platform by saving this JSON into a file called sample.json and make the following API call:
|
curl -X POST -H "Content-type: application/json" -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/employee-scheduling/v1/schedules [email protected]
{
"config": {
"run": {
"name": "Availability with Tags example"
}
},
"modelInput": {
"employees": [
{
"id": "Beth",
"unavailableTimeSpans": [
{
"start": "2027-02-01T00:00:00Z",
"end": "2027-02-08T00:00:00Z"
}
]
},
{
"id": "Carl",
"availableTimeSpans": [
{
"start": "2027-02-02T00:00:00Z",
"end": "2027-02-06T00:00:00Z",
"includeShiftTags": [ "location central" ]
}
]
},
{
"id": "Ann",
"availableTimeSpans": [
{
"start": "2027-02-01T00:00:00Z",
"end": "2027-02-06T00:00:00Z",
"excludeShiftTags": [ "location central" ]
}
]
}
],
"shifts": [
{
"id": "2027-02-01",
"start": "2027-02-01T09:00:00Z",
"end": "2027-02-01T17:00:00Z",
"tags": [
"location central"
]
},
{
"id": "2027-02-02",
"start": "2027-02-02T09:00:00Z",
"end": "2027-02-02T17:00:00Z",
"tags": [
"location central"
]
},
{
"id": "2027-02-03",
"start": "2027-02-03T09:00:00Z",
"end": "2027-02-03T17:00:00Z",
"tags": [
"location central"
]
},
{
"id": "2027-02-04",
"start": "2027-02-04T09:00:00Z",
"end": "2027-02-04T17:00:00Z",
"tags": [
"location central"
]
},
{
"id": "2027-02-05",
"start": "2027-02-05T09:00:00Z",
"end": "2027-02-05T17:00:00Z",
"tags": [
"location central"
]
}
]
}
}
To request the solution, locate the 'ID' from the response to the post operation and append it to the following API call: |
curl -X GET -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/employee-scheduling/v1/schedules/<ID>
{
"run": {
"id": ID,
"name": "Availability with Tags example",
"submitDateTime": "2024-09-24T05:10:39.287389671Z",
"startDateTime": "2024-09-24T05:10:47.173446864Z",
"completeDateTime": "2024-09-24T05:15:47.71357411Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/-1medium/0soft",
"tags": null,
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"shifts": [
{
"id": "2027-02-01",
"employee": null
},
{
"id": "2027-02-02",
"employee": "Carl"
},
{
"id": "2027-02-03",
"employee": "Carl"
},
{
"id": "2027-02-04",
"employee": "Carl"
},
{
"id": "2027-02-05",
"employee": "Carl"
}
]
},
"kpis": {
"unassignedShifts": 1
}
}
modelOutput
contains the employee shift schedule with Carl assigned to the shifts when he is available, and the Monday shift left unassigned because Beth is unavailable and Ann’s availability isn’t for shifts tagged "location central".
If shifts have multiple tags, you decide whether to match ALL or ANY of the tags based on employee availability by including shiftTagMatches
.
"availableTimeSpans": [
{
"start": "2027-02-01T00:00:00Z",
"end": "2027-02-03T00:00:00Z",
"includeShiftTags": [
"department a",
"location central"
],
"shiftTagMatches": "ALL"
}
]
With shiftTagMatches
set to "ALL", a shift must include all the tags defined by the employee to match.
With shiftTagMatches
set to "ANY", a shift must include at least one of the tags defined by the employee to match.
If shiftTagMatches
is not included in the modelInput, all tags must match.
Next
-
Understand the constraints of the Employee Shift Scheduling model.
-
See the full API spec or try the online API.
-
Manage schedules with Timezones and Daylight Saving Time (DST) changes.
-
Understand how to include Employee preferences in your schedules.