Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
  • Platform
Try models
  • Employee Shift Scheduling
  • Shift service constraints
  • Alternative shifts

Employee Shift Scheduling

    • Introduction
    • Planning AI concepts
    • Metrics and optimization goals
    • Getting started with employee shift scheduling
    • Understanding the API
    • Employee shift scheduling user guide
    • Employee resource constraints
      • Employee availability
      • Employee contracts
      • Employee contracts: period rules
      • Employee contracts: shift rules
      • Fairness
      • Pairing employees
      • Shift travel and locations
    • Shift service constraints
      • Alternative shifts
      • Demand and supply
      • Mandatory and optional visits
      • Shift assignments
      • Shift sequence patterns: single day shifts
      • Shift sequence patterns: multi-day shifts
      • Shift sequence patterns: daily shift pairings
      • Skills and risk factors
    • Recommendations
    • Real-time planning
    • Time zones and Daylight Saving Time (DST)
    • New and noteworthy
    • Upgrading to the latest versions
    • Feature requests

Alternative shifts

Some shifts are more flexible than others and can be scheduled at different times. For instance, a product demonstration could occur at 09:00, 11:00, 13:00, or 15:00.

The product demonstration could happen at any of those 4 times, but it should only happen once.

With alternative shifts you can define a range of timeslots for a shift where only a single timeslot is scheduled.

This guide explains how to manage alternative shifts with the following examples:

  • Create a shift group and assign one shift

  • Create two shift groups and assign one shift to each group

  • Control when different shift group rules apply

Prerequisites

To run the examples in this guide, you need to authenticate with a valid API key for the Employee Shift Scheduling model:

  1. Log in to Timefold Platform: app.timefold.ai

  2. From the Dashboard, click your tenant, and from the drop-down menu select Tenant Settings, then choose API Keys.

  3. 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. Create a shift group and assign one shift

Shift group rules control how many alternative shifts are scheduled.

Shift group rules are defined as global rules.

{
  "globalRules": {
    "shiftGroupRules": [
      {
        "id": "singleShiftPerGroup",
        "assignmentMode": {
          "type": "SINGLE_SHIFT"
        }
      }
    ]
  }
}

shiftGroupRules must include an ID.

assignmentMode supports the type SINGLE_SHIFT which ensures only one of the alternative shifts within a shift group is assigned.

The shifts that will be part of the shift group must be defined:

{
  "shifts": [
    {
      "id": "product-demo-2027-02-01-1",
      "start": "2027-02-01T09:00:00Z",
      "end": "2027-02-01T11:00:00Z"
    },
    {
      "id": "product-demo-2027-02-01-2",
      "start": "2027-02-01T11:00:00Z",
      "end": "2027-02-01T13:00:00Z"
    },
    {
      "id": "product-demo-2027-02-01-3",
      "start": "2027-02-01T13:00:00Z",
      "end": "2027-02-010T15:00:00Z"
    },
    {
      "id": "product-demo-2027-02-01-4",
      "start": "2027-02-01T15:00:00Z",
      "end": "2027-02-010T17:00:00Z"
    }
  ]
}

Alternative shifts must be added to a shift group, which references the shift ID of every alternative shift in the group.

{
  "shiftGroups": [
    {
      "id": "product-demo",
      "shifts": [
        "product-demo-2027-02-01-1",
        "product-demo-2027-02-01-2",
        "product-demo-2027-02-01-3",
        "product-demo-2027-02-01-4"
      ]
    }
  ]
}

The Required shift group assignment mode not met hard constraint makes sure only the required number of alternative shifts are assigned.

In the following example there are 4 alternative shifts that could be assigned. 1 shift is assigned, and the other 3 are left unassigned.

  • 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": "Alternative shifts example"
    }
  },
  "modelInput": {
    "globalRules": {
      "shiftGroupRules": [
        {
          "id": "singleShiftPerGroup",
          "assignmentMode": {
            "type": "SINGLE_SHIFT"
          }
        }
      ]
    },
    "employees": [
      {
        "id": "Carl"
      }
    ],
    "shifts": [
      {
        "id": "product-demo-2027-02-01-1",
        "start": "2027-02-01T09:00:00Z",
        "end": "2027-02-01T11:00:00Z"
      },
      {
        "id": "product-demo-2027-02-01-2",
        "start": "2027-02-01T11:00:00Z",
        "end": "2027-02-01T13:00:00Z"
      },
      {
        "id": "product-demo-2027-02-01-3",
        "start": "2027-02-01T13:00:00Z",
        "end": "2027-02-01T15:00:00Z"
      },
      {
        "id": "product-demo-2027-02-01-4",
        "start": "2027-02-01T15:00:00Z",
        "end": "2027-02-01T17:00:00Z"
      }
    ],
    "shiftGroups": [
      {
        "id": "product-demo",
        "shifts": [
          "product-demo-2027-02-01-1",
          "product-demo-2027-02-01-2",
          "product-demo-2027-02-01-3",
          "product-demo-2027-02-01-4"
        ]
      }
    ]
  }
}
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": "Alternative shifts example",
    "submitDateTime": "2025-03-14T06:35:07.464546025Z",
    "startDateTime": "2025-03-14T06:35:23.244545483Z",
    "activeDateTime": "2025-03-14T06:35:23.390859877Z",
    "completeDateTime": "2025-03-14T06:40:24.004567395Z",
    "shutdownDateTime": "2025-03-14T06:40:24.317964262Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/-3medium/0soft",
    "tags": [
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "shifts": [
      {
        "id": "product-demo-2027-02-01-1",
        "employee": "Carl"
      },
      {
        "id": "product-demo-2027-02-01-2",
        "employee": null
      },
      {
        "id": "product-demo-2027-02-01-3",
        "employee": null
      },
      {
        "id": "product-demo-2027-02-01-4",
        "employee": null
      }
    ]
  },
  "inputMetrics": {
    "employees": 1,
    "shifts": 4,
    "pinnedShifts": 0
  },
  "kpis": {
    "assignedShifts": 1,
    "unassignedShifts": 3,
    "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 one of the alternative shifts assigned.

inputMetrics provides a breakdown of the inputs in the input dataset.

KPIs provides the KPIs for the output.

2. Create two shift groups and assign one shift to each group

In the following example, there are 2 shift groups with 4 alternative shifts in each group.

1 shift from each shift group is assigned and the other alternative shifts are left unassigned.

  • 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": "Alternative shifts with multiple groups example"
    }
  },
  "modelInput": {
    "globalRules": {
      "shiftGroupRules": [
        {
          "id": "singleShiftPerGroup",
          "assignmentMode": {
            "type": "SINGLE_SHIFT"
          }
        }
      ]
    },
    "employees": [
      {
        "id": "Beth"
      },
      {
        "id": "Carl"
      }
    ],
    "shifts": [
      {
        "id": "product-demo-a-2027-02-01-1",
        "start": "2027-02-01T09:00:00Z",
        "end": "2027-02-01T11:00:00Z"
      },
      {
        "id": "product-demo-a-2027-02-01-2",
        "start": "2027-02-01T11:00:00Z",
        "end": "2027-02-01T13:00:00Z"
      },
      {
        "id": "product-demo-a-2027-02-01-3",
        "start": "2027-02-01T13:00:00Z",
        "end": "2027-02-01T15:00:00Z"
      },
      {
        "id": "product-demo-a-2027-02-01-4",
        "start": "2027-02-01T15:00:00Z",
        "end": "2027-02-01T17:00:00Z"
      },
      {
        "id": "product-demo-b-2027-02-01-1",
        "start": "2027-02-01T09:00:00Z",
        "end": "2027-02-01T11:00:00Z"
      },
      {
        "id": "product-demo-b-2027-02-01-2",
        "start": "2027-02-01T11:00:00Z",
        "end": "2027-02-01T13:00:00Z"
      },
      {
        "id": "product-demo-b-2027-02-01-3",
        "start": "2027-02-01T13:00:00Z",
        "end": "2027-02-01T15:00:00Z"
      },
      {
        "id": "product-demo-b-2027-02-01-4",
        "start": "2027-02-01T15:00:00Z",
        "end": "2027-02-01T17:00:00Z"
      }
    ],
    "shiftGroups": [
      {
        "id": "product-demo-a",
        "shifts": [
          "product-demo-a-2027-02-01-1",
          "product-demo-a-2027-02-01-2",
          "product-demo-a-2027-02-01-3",
          "product-demo-a-2027-02-01-4"
        ]
      },
      {
        "id": "product-demo-b",
        "shifts": [
          "product-demo-b-2027-02-01-1",
          "product-demo-b-2027-02-01-2",
          "product-demo-b-2027-02-01-3",
          "product-demo-b-2027-02-01-4"
        ]
      }
    ]
  }
}
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": "Alternative shifts with multiple groups example",
    "submitDateTime": "2025-03-14T06:34:54.514130204Z",
    "startDateTime": "2025-03-14T06:35:06.355765979Z",
    "activeDateTime": "2025-03-14T06:35:06.510548625Z",
    "completeDateTime": "2025-03-14T06:40:07.227952802Z",
    "shutdownDateTime": "2025-03-14T06:40:07.460807925Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/-6medium/0soft",
    "tags": [
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "shifts": [
      {
        "id": "product-demo-a-2027-02-01-1",
        "employee": "Beth"
      },
      {
        "id": "product-demo-a-2027-02-01-2",
        "employee": null
      },
      {
        "id": "product-demo-a-2027-02-01-3",
        "employee": null
      },
      {
        "id": "product-demo-a-2027-02-01-4",
        "employee": null
      },
      {
        "id": "product-demo-b-2027-02-01-1",
        "employee": "Carl"
      },
      {
        "id": "product-demo-b-2027-02-01-2",
        "employee": null
      },
      {
        "id": "product-demo-b-2027-02-01-3",
        "employee": null
      },
      {
        "id": "product-demo-b-2027-02-01-4",
        "employee": null
      }
    ]
  },
  "inputMetrics": {
    "employees": 2,
    "shifts": 8,
    "pinnedShifts": 0
  },
  "kpis": {
    "assignedShifts": 2,
    "unassignedShifts": 6,
    "workingTimeFairnessPercentage": null,
    "disruptionPercentage": 0.0,
    "averageDurationOfEmployeesPreferencesMet": null,
    "minimumDurationOfPreferencesMetAcrossEmployees": null,
    "averageDurationOfEmployeesUnpreferencesViolated": null,
    "maximumDurationOfUnpreferencesViolatedAcrossEmployees": null,
    "activatedEmployees": 2,
    "assignedMandatoryShifts": 2,
    "assignedOptionalShifts": 0,
    "travelDistance": 0
  }
}

modelOutput contains the schedule with one alternative shift from each shift group assigned.

inputMetrics provides a breakdown of the inputs in the input dataset.

KPIs provides the KPIs for the output.

3. Control when different shift group rules apply

Shift groups with specific tags can be included by the rule, while shift groups without the tag are ignored by the rule. Tags are defined in shifts groups:

{
  "shiftGroups": [
    {
      "id": "product-demo",
      "tags": ["product a"],
      "shifts": [
        "product-demo-2027-02-01-1",
        "product-demo-2027-02-01-2"
      ]
    }
  ]
}

Use includeShiftGroupTags to include shift groups with a specific tags.

3.1. Example include shift groups tags

{
  "globalRules": {
    "shiftGroupRules": [
      {
        "id": "singleShiftPerGroup",
        "includeGroupTags": ["product a"],
        "assignmentMode": {
          "type": "SINGLE_SHIFT"
        }
      }
    ]
  }
}

Next

  • See the Employee shift scheduling user guide

  • 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.

  • © 2025 Timefold BV
  • Timefold.ai
  • Documentation
  • Changelog
  • Send feedback
  • Privacy
  • Legal
    • Light mode
    • Dark mode
    • System default