Shift sequence patterns: single day shifts
Some employees work multiple shifts in a single day.
Single day shift patterns set rules about which combinations of shifts are allowed and which ones should be avoided or are prohibited altogether.
For instance, it might be preferrable to have employees work shifts that occur close together to limit the number of times they need to commute to work in a single day.
Assigning shifts that occur in the afternoon and evening to the same employee can avoid causing unnecessary disruption to the employee’s day.
Assigning shifts that are several hours apart might not be ideal, but acceptable if there are no other alternatives.
Whereas assigning shifts at opposite ends of the day and impacting the employee’s ability to rest between shifts could be prohibited.
This guide explains how to manage single day shift sequence patterns with the following examples:
Prerequisites
To run the examples in this guide, you need to authenticate with a valid API key for the Employee Shift Scheduling model:
-
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. Single day shift sequence
Single day shift sequence patterns rules are configured in contracts:
{
"contracts": [
{
"id": "splitShiftContract",
"singleDayShiftSequencePatternRules": [
{
"id": "earlyShiftFollowedByMorningShift",
"pattern": [
{
"includeShiftTags": ["Early"],
"shiftTagMatches": "ALL"
},
{
"includeShiftTags": ["Morning"],
"shiftTagMatches": "ALL"
}
],
"satisfiability": "PREFERRED",
"ordered": true,
"weight": 10
}
]
}
]
}
singleDayShiftSequencePatternRules
must include an ID.
pattern
specifies the shifts that are included or excluded in the pattern based on the shift’s tags.
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.
ordered
can be set to true
or false
.
True enforces the shifts being scheduled in the order they appear in the pattern.
weight
can be used to make the pattern more important than other patterns.
For example, setting the weight to 2 will make the reward/penalty of this pattern’s elements count twice when matched.
Each employee must specify which contracts apply to them:
{
"employees": [
{
"id": "Ann",
"contracts": [
"partTimeContract"
]
}
]
}
Shifts must include tags:
{
"id": "Mon 0300",
"start": "2027-02-01T03:00:00Z",
"end": "2027-02-01T07:00:00Z",
"tags": ["Early"]
}
satisfiability
of the pattern can be PREFERRED
, PROHIBITED
, or UNPREFERRED
.
1.1. Preferred satisfiability
When the satisfiability
of the rule is PREFERRED
, the Employee works preferred single day shift sequence pattern
soft constraint is invoked, which adds a soft reward to the run score when employees are assigned shifts that match the pattern.
Timefold is incentivized to use solutions with the best score.
In the following example, there are two singleDayShiftSequencePatternRules
:
-
Shifts tagged "Early" and "Morning" are preferrably assigned together.
-
Shifts tagged "Afternoon" and "Late" are preferrably assigned together.
Ann is assigned shifts tagged "Early" and "Morning", and Beth is assigned shifts tagged "Afternoon" and "Late".

-
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": "Single day shift pattern rules - preferred"
}
},
"modelInput": {
"contracts": [
{
"id": "splitShiftContract",
"singleDayShiftSequencePatternRules": [
{
"id": "earlyShiftFollowedByMorningShift",
"pattern": [
{
"includeShiftTags": ["Early"],
"shiftTagMatches": "ALL"
},
{
"includeShiftTags": ["Morning"],
"shiftTagMatches": "ALL"
}
],
"satisfiability": "PREFERRED",
"ordered": true,
"weight": 10
},
{
"id": "afternoonShiftFollowedByLateShift",
"pattern": [
{
"includeShiftTags": ["Afternoon"],
"shiftTagMatches": "ALL"
},
{
"includeShiftTags": ["Late"],
"shiftTagMatches": "ALL"
}
],
"satisfiability": "PREFERRED",
"ordered": true,
"weight": 10
}
]
}
],
"employees": [
{
"id": "Ann",
"contracts": [
"splitShiftContract"
]
},
{
"id": "Beth",
"contracts": [
"splitShiftContract"
]
}
],
"shifts": [
{
"id": "Mon 03",
"start": "2027-02-01T03:00:00Z",
"end": "2027-02-01T07:00:00Z",
"tags": ["Early"]
},
{
"id": "Mon 08",
"start": "2027-02-01T08:00:00Z",
"end": "2027-02-01T12:00:00Z",
"tags": ["Morning"]
},
{
"id": "Mon 12",
"start": "2027-02-01T12:00:00Z",
"end": "2027-02-01T16:00:00Z",
"tags": ["Afternoon"]
},
{
"id": "Mon 17",
"start": "2027-02-01T17:00:00Z",
"end": "2027-02-01T21:00:00Z",
"tags": ["Late"]
}
]
}
}
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": "Single day shift pattern rules - preferred",
"submitDateTime": "2025-04-14T04:00:01.1887304Z",
"startDateTime": "2025-04-14T04:00:14.959991668Z",
"activeDateTime": "2025-04-14T04:00:15.195627078Z",
"completeDateTime": "2025-04-14T04:00:46.012389803Z",
"shutdownDateTime": "2025-04-14T04:00:46.308551364Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/3840000soft",
"tags": [
"system.profile:default"
],
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"shifts": [
{
"id": "Mon 03",
"employee": "Ann"
},
{
"id": "Mon 08",
"employee": "Ann"
},
{
"id": "Mon 12",
"employee": "Beth"
},
{
"id": "Mon 17",
"employee": "Beth"
}
]
},
"inputMetrics": {
"employees": 2,
"shifts": 4,
"pinnedShifts": 0
},
"kpis": {
"assignedShifts": 4,
"unassignedShifts": 0,
"assignedShiftGroups": 0,
"unassignedShiftGroups": 0,
"workingTimeFairnessPercentage": null,
"disruptionPercentage": 0.0,
"averageDurationOfEmployeesPreferencesMet": null,
"minimumDurationOfPreferencesMetAcrossEmployees": null,
"averageDurationOfEmployeesUnpreferencesViolated": null,
"maximumDurationOfUnpreferencesViolatedAcrossEmployees": null,
"activatedEmployees": 2,
"assignedMandatoryShifts": 4,
"assignedOptionalShifts": 0,
"travelDistance": 0
}
}
modelOutput
contains the schedule with Ann assigned shifts tagged "Early" and "Morning" and Beth assigned shifts tagged "Afternoon" and "Late".
inputMetrics
provides a breakdown of the inputs in the input dataset.
KPIs
provides the KPIs for the output including:
{
"assignedShifts": 4,
"activatedEmployees": 2,
"assignedMandatoryShifts": 4
}
1.2. Unpreferred satisfiability
When the satisfiability
of the rule is UNPREFERRED
, the Employee works unpreferred single day shift sequence pattern
soft constraint is invoked.
{
"contracts": [
{
"id": "splitShiftContract",
"singleDayShiftSequencePatternRules": [
{
"id": "earlyShiftFollowedByMorningShift",
"pattern": [
{
"includeShiftTags": ["Early"],
"shiftTagMatches": "ALL"
},
{
"includeShiftTags": ["Afternoon"],
"shiftTagMatches": "ALL"
}
],
"satisfiability": "UNPREFERRED",
"ordered": true,
"weight": 10
}
]
}
]
}
This constraint adds a soft penalty to the run score when an employee is assigned shifts in a pattern that is UNPREFERRED, incentivizing Timefold to find an alternative solution.
In the following example, there is one singleDayShiftSequencePatternRules
:
-
Shifts tagged with "Early" and "Afternoon" are preferrably not assigned to individual employees.
There are only two shifts, and one employee. Ann is assigned shifts tagged "Early" and "Afternoon" and the solution is penalized with a negative soft score.
-
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": "Single day shift pattern rules - unpreferred"
}
},
"modelInput": {
"contracts": [
{
"id": "splitShiftContract",
"periodRules": [
{
"id": "Max8HoursPerDay",
"period": "DAY",
"satisfiability": "REQUIRED",
"minutesWorkedMax": 480
}
],
"singleDayShiftSequencePatternRules": [
{
"id": "earlyShiftFollowedByMorningShift",
"pattern": [
{
"includeShiftTags": ["Early"],
"shiftTagMatches": "ALL"
},
{
"includeShiftTags": ["Afternoon"],
"shiftTagMatches": "ALL"
}
],
"satisfiability": "UNPREFERRED",
"ordered": true,
"weight": 10
}
]
}
],
"employees": [
{
"id": "Ann",
"contracts": [
"splitShiftContract"
]
}
],
"shifts": [
{
"id": "Mon 03",
"start": "2027-02-01T03:00:00Z",
"end": "2027-02-01T07:00:00Z",
"tags": ["Early"]
},
{
"id": "Mon 12",
"start": "2027-02-01T12:00:00Z",
"end": "2027-02-01T16:00:00Z",
"tags": ["Afternoon"]
}
]
}
}
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": "Single day shift pattern rules - unpreferred",
"submitDateTime": "2025-04-14T05:00:32.456746712Z",
"startDateTime": "2025-04-14T05:00:43.557705033Z",
"activeDateTime": "2025-04-14T05:00:43.713611242Z",
"completeDateTime": "2025-04-14T05:01:14.53407709Z",
"shutdownDateTime": "2025-04-14T05:01:14.79050782Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/-1920000soft",
"tags": [
"system.profile:default"
],
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"shifts": [
{
"id": "Mon 03",
"employee": "Ann"
},
{
"id": "Mon 12",
"employee": "Ann"
}
]
},
"inputMetrics": {
"employees": 1,
"shifts": 2,
"pinnedShifts": 0
},
"kpis": {
"assignedShifts": 2,
"unassignedShifts": 0,
"assignedShiftGroups": 0,
"unassignedShiftGroups": 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 Ann assigned to both shifts.
inputMetrics
provides a breakdown of the inputs in the input dataset.
KPIs
provides the KPIs for the output including:
{
"assignedShifts": 2,
"activatedEmployees": 1,
"assignedMandatoryShifts": 2
}
1.3. Prohibited satisfiability
When the satisfiability
of the rule is PROHIBITED
, the Employee works prohibited single day shift sequence pattern
hard constraint is invoked.
{
"contracts": [
{
"id": "splitShiftContract",
"singleDayShiftSequencePatternRules": [
{
"id": "earlyShiftFollowedByMorningShift",
"pattern": [
{
"includeShiftTags": ["Early"],
"shiftTagMatches": "ALL"
},
{
"includeShiftTags": ["Late"],
"shiftTagMatches": "ALL"
}
],
"satisfiability": "PROHIBITED",
"ordered": true,
"weight": 10
}
]
}
]
}
Shifts will be left unassigned if assigning them would break the Employee works prohibited single day shift sequence pattern
constraint.
In the following example, there is one singleDayShiftSequencePatternRules
:
-
Shifts tagged "Early" and "Late" are prohibited from being assigned together to individual employees.
Ann is assigned the shift tagged "Early", but the shift tagged "Late" is left unassigned to avoid breaking the hard constraint.
-
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": "Single day shift pattern rules - prohibited"
}
},
"modelInput": {
"contracts": [
{
"id": "splitShiftContract",
"singleDayShiftSequencePatternRules": [
{
"id": "earlyShiftFollowedByMorningShift",
"pattern": [
{
"includeShiftTags": ["Early"],
"shiftTagMatches": "ALL"
},
{
"includeShiftTags": ["Late"],
"shiftTagMatches": "ALL"
}
],
"satisfiability": "PROHIBITED",
"ordered": true,
"weight": 10
}
]
}
],
"employees": [
{
"id": "Ann",
"contracts": [
"splitShiftContract"
]
}
],
"shifts": [
{
"id": "Mon 03",
"start": "2027-02-01T03:00:00Z",
"end": "2027-02-01T07:00:00Z",
"tags": ["Early"]
},
{
"id": "Mon 17",
"start": "2027-02-01T17:00:00Z",
"end": "2027-02-01T21:00:00Z",
"tags": ["Late"]
}
]
}
}
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": "Single day shift pattern rules - prohibited",
"submitDateTime": "2025-04-14T05:06:47.106470925Z",
"startDateTime": "2025-04-14T05:07:02.386223943Z",
"activeDateTime": "2025-04-14T05:07:02.610949643Z",
"completeDateTime": "2025-04-14T05:07:33.472871088Z",
"shutdownDateTime": "2025-04-14T05:07:33.659151333Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/-1medium/0soft",
"tags": [
"system.profile:default"
],
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"shifts": [
{
"id": "Mon 03",
"employee": "Ann"
},
{
"id": "Mon 17",
"employee": null
}
]
},
"inputMetrics": {
"employees": 1,
"shifts": 2,
"pinnedShifts": 0
},
"kpis": {
"assignedShifts": 1,
"unassignedShifts": 1,
"assignedShiftGroups": 0,
"unassignedShiftGroups": 0,
"workingTimeFairnessPercentage": null,
"disruptionPercentage": 0.0,
"averageDurationOfEmployeesPreferencesMet": null,
"minimumDurationOfPreferencesMetAcrossEmployees": null,
"averageDurationOfEmployeesUnpreferencesViolated": null,
"maximumDurationOfUnpreferencesViolatedAcrossEmployees": null,
"activatedEmployees": 1,
"assignedMandatoryShifts": 1,
"assignedOptionalShifts": 0,
"travelDistance": 0
}
}
modelOutput
contains the schedule with Ann assigned to only one shift.
inputMetrics
provides a breakdown of the inputs in the input dataset.
KPIs
provides the KPIs for the output including:
{
"assignedShifts": 1,
"unassignedShifts": 1,
"activatedEmployees": 1,
"assignedMandatoryShifts": 1
}
Next
-
Understand the constraints of the Employee Shift Scheduling model.
-
See the full API spec or try the online API.
-
Manage schedules with Time zones and Daylight Saving Time (DST) changes.
-
Working with Employee availability.