Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
    • Pick-up and Delivery Routing
  • Platform
Try models
  • Employee Shift Scheduling
  • Employee resource constraints
  • Employee availability and preferences
  • Employee availability
  • latest
    • latest
    • 1.24.x

Employee Shift Scheduling

    • Introduction
    • Getting started: Hello world
    • User guide
      • Terminology
      • Use case guide
      • Planning AI concepts
      • Integration
      • Constraints
      • Understanding the API
      • Demo datasets
      • Input datasets
        • Model configuration
        • Model input
        • Planning window
      • Planning window
      • Time zones and Daylight Saving Time (DST)
      • Tags and tag types
      • Input validation
      • Output datasets
        • Metadata
        • Model output
        • Input metrics
        • Key performance indicators (KPIs)
      • Metrics and optimization goals
      • Score analysis
      • Visualizations
    • Employee resource constraints
      • Employee availability and preferences
        • Employee availability
        • Employee preferences
      • Employee contracts
      • Employee priority
      • Pairing employees
      • Shift travel and locations
      • Shift Breaks
      • Employee activation
      • Work limits
        • Minutes worked per period
        • Minutes worked in a rolling window
        • Minutes logged per period
        • Days worked per period
        • Days worked in a rolling window
        • Consecutive days worked
        • Shifts worked per period
        • Shifts worked in a rolling window
        • Weekend minutes worked per period
        • Weekends worked per period
        • Weekends worked in a rolling window
        • Consecutive weekends worked
        • Consecutive shifts worked
      • Time off
        • Days off per period
        • Consecutive days off per period
        • Consecutive days off in a rolling window
        • Consecutive minutes off in a rolling window
        • Shifts to avoid close to day off requests
        • Consecutive weekends off per period
      • Shift rotations and patterns
        • Shift rotations
        • Single day shift sequence patterns
        • Minimize gaps between shifts
        • Multi-day shift sequence patterns
        • Daily shift pairings
        • Overlapping shifts
        • Shift start times differences
        • Minutes between shifts
      • Shift type diversity
        • Shift tag types
        • Shift types worked per period
        • Unique tags per period
      • Fairness
        • Balance time worked
        • Balance shift count
    • Shift service constraints
      • Alternative shifts
      • Cost management
        • Cost groups
        • Employee rates
      • Demand-based scheduling
      • Mandatory and optional shifts
      • Skills and risk factors
      • Shift assignments
        • Shift selection
        • Employee selection
    • Manual intervention
    • Recommendations
    • Real-time planning
    • Real-time planning (preview)
    • Scenarios
      • Configuring labor law compliance
      • Configuring employee well-being
    • Changelog
    • Upgrade to the latest version
    • Feature requests

Employee availability

Employee availability defines when employees are available and unavailable for work.

This guide explains employee availability with the following:

  • Defining employee availability
  • Employee unavailability times
  • Employee availability times
  • Filtering availability with tags

Defining employee availability

Learn how to configure an API Key to run the examples in this guide:
  1. Log in to Timefold Platform: app.timefold.ai

  2. From the Dashboard, click your tenant, and from the drop-down menu select Manage tenant, 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.

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.

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.

employee unavailability

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 (exclusive) 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>
{
  "metadata": {
    "id": "ID",
    "name": "Unavailability example",
    "submitDateTime": "2024-09-12T09:45:46.822999677Z",
    "startDateTime": "2024-09-12T09:45:52.628925423Z",
    "activeDateTime": "2024-09-12T09:45:52.728925423Z",
    "completeDateTime": "2024-09-12T09:50:53.058023049Z",
    "shutdownDateTime": "2024-09-12T09:50:53.158023049Z",
    "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 the Employee works during unavailable time hard constraint and make the plan infeasible. Leaving the shift unassigned breaks the Unassigned mandatory shift medium constraint but the plan is still feasible.

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.

employee availability

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 (exclusive) in ISO 8601 with date time offset to UTC for the end of the period the employee is available.

  • 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>
{
  "metadata": {
    "id": "ID",
    "name": "Availability example",
    "submitDateTime": "2024-09-12T09:55:53.15634866Z",
    "startDateTime": "2024-09-12T09:55:58.934451453Z",
    "activeDateTime": "2024-09-12T09:55:59.034451453Z",
    "completeDateTime": "2024-09-12T10:00:59.512605369Z",
    "shutdownDateTime": "2024-09-12T10:00:59.612605369Z",
    "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 Beth’s unavailableTimeSpans and Carl’s availableTimeSpans.

Filtering availability 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 can’t be used in combination. That is, because Carl’s availableTimeSpans uses includeShiftTags, it can’t also use excludeShiftTags. Similarly, because Ann’s availableTimeSpans uses excludeShiftTags, it can’t 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.

employee availability with tags

  • 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>
{
  "metadata": {
    "id": "ID",
    "name": "Availability with Tags example",
    "submitDateTime": "2024-09-24T05:10:39.287389671Z",
    "startDateTime": "2024-09-24T05:10:47.173446864Z",
    "activeDateTime": "2024-09-24T05:10:47.273446864Z",
    "completeDateTime": "2024-09-24T05:15:47.71357411Z",
    "shutdownDateTime": "2024-09-24T05:15:47.81357411Z",
    "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

  • See the full API spec or try the online API.

  • Learn more about employee shift scheduling from our YouTube playlist.

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