Overlapping shifts
There are situations where employees need to be assigned to multiple shifts that occur at the same time, for instance, their regular shift and an on call shift that overlaps their regular shift.
Prerequisites
Learn how to configure an API Key to run the examples in this guide:
-
Log in to Timefold Platform: app.timefold.ai
-
From the Dashboard, click your tenant, and from the drop-down menu select Tenant Settings, then choose API Keys.
-
Create a new API key or use an existing one. Ensure the list of models for the API key contains the Employee Shift Scheduling model.
In the examples, replace <API_KEY> with the API Key you just copied.
1. Defining overlapping shift rules
Overlapping shifts rules are defined in contracts.
{
"contracts": [
{
"id": "fullTimeContract",
"allowOverlappingShiftsRules": [
{
"id": "allowOverlapWithOnCallShift",
"includeShiftTags": [
"On call"
],
"shiftTagMatches": "ALL"
}
]
}
]
}
An allowOverlappingShiftsRules must include an id.
The Overlapping shifts hard constraint makes sure only shifts with tags defined by the rule’s includeShiftTags can overlap with other shifts.
Alternatively, only shifts without tags defined by the rule’s excludeShiftTags can overlap with other shifts.
Further information about including or excluding shifts with shift tags:
Shifts with specific tags can be included or excluded by the rule. Tags are defined in shifts:
{
"shifts": [
{
"id": "2027-02-01",
"start": "2027-02-01T09:00:00Z",
"end": "2027-02-01T17:00:00Z",
"tags": ["Part-time"]
}
]
}
Use includeShiftTags to include shifts with specific tags or excludeShiftTags to exclude shifts with specific tags.
shiftTagMatches can be set to ALL or ANY.
The default behavior for shiftTagMatches is ALL, and if omitted, the default ALL will be used.
The rule can define either includeShiftTags or excludeShiftTags, but not both.
{
"includeShiftTags": ["Part-time", "Weekend"],
"shiftTagMatches": "ALL"
}
With shiftTagMatches set to ALL, all tags defined by the rule’s includeShiftTags attribute must be present in the shift. With shiftTagMatches set to ANY, at least one tag defined by the rule’s includeShiftTags attribute must be present in the shift.
{
"excludeShiftTags": ["Part-time", "Weekend"],
"shiftTagMatches": "ALL"
}
With shiftTagMatches set to ALL, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
This is useful when you want to exclude things in combination with each other.
For instance, excluding the shift tags Part-time and Weekend with shiftTagMatches set to All, will exclude shifts that include the tags Part-time and Weekend from the rule.
Shifts tagged only Part-time or only Weekend will not be excluded.
With shiftTagMatches set to ANY, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
This is useful when you need to exclude tags regardless of their relationship to other tags.
For instance, excluding the shift tags Part-time and Weekend with shiftTagMatches set to ANY, will exclude any shift that includes the tags Part-time or Weekend, whether they occur together or not.
2. Overlapping shift rules example
In the following example, Carl is assigned to a 24 hour on call shift that overlaps with his regular 8 hour 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": "Overlapping shifts rules example"
}
},
"modelInput": {
"contracts": [
{
"id": "fullTimeContract",
"allowOverlappingShiftsRules": [
{
"id": "allowOverlapWithOnCallShift",
"includeShiftTags": [
"On call"
],
"shiftTagMatches": "ALL"
}
]
}
],
"employees": [
{
"id": "Carl",
"contracts": [
"fullTimeContract"
]
}
],
"shifts": [
{
"id": "Mon on-call",
"start": "2027-02-01T00:00:00Z",
"end": "2027-02-02T00:00:00Z",
"tags": ["On call"]
},
{
"id": "Mon regular shift",
"start": "2027-02-01T09:00:00Z",
"end": "2027-02-01T17: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>
{
"metadata": {
"id": "ID",
"name": "Overlapping shifts rules example",
"submitDateTime": "2025-03-21T04:48:22.193823297Z",
"startDateTime": "2025-03-21T04:48:33.625081572Z",
"activeDateTime": "2025-03-21T04:48:33.773882421Z",
"completeDateTime": "2025-03-21T04:53:34.494085854Z",
"shutdownDateTime": "2025-03-21T04:53:34.766113937Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/0soft",
"tags": [
"system.profile:default"
],
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"shifts": [
{
"id": "Mon on-call",
"employee": "Carl"
},
{
"id": "Mon regular shift",
"employee": "Carl"
}
]
},
"inputMetrics": {
"employees": 1,
"shifts": 2,
"pinnedShifts": 0
},
"kpis": {
"assignedShifts": 2,
"unassignedShifts": 0,
"workingTimeFairnessPercentage": null,
"disruptionPercentage": 0.0,
"averageDurationOfEmployeesPreferencesMet": null,
"minimumDurationOfPreferencesMetAcrossEmployees": null,
"averageDurationOfEmployeesUnpreferencesViolated": null,
"maximumDurationOfUnpreferencesViolatedAcrossEmployees": null,
"activatedEmployees": 1,
"assignedMandatoryShifts": 2,
"assignedOptionalShifts": 0,
"travelDistance": 0
}
}
modelOutput contains the schedule with overlapping shifts assigned to Carl.
inputMetrics provides a breakdown of the inputs in the input dataset.
KPIs provides the KPIs for the output including:
{
"assignedShifts": 2,
"unassignedShifts": 0
}
Next
-
See the full API spec or try the online API.
-
Learn more about employee shift scheduling from our YouTube playlist.
-
See other options for Shift rotations and patterns.