> ## Documentation Index
> Fetch the complete documentation index at: https://docs.automaticrostering.visma.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Employee Utilization

> Set targets and limits for the number of hours or shifts worked by employees in specific periods.

The Employee Utilization constraint allows you to control how much work employees receive, either measured in FTE hours or in number of shifts. You can set minimum targets, ideal targets, and maximum limits for any combination of employees, shifts, and time periods.

<Card title="Constraint schema">
  <ResponseField name="employeeUtilizationConstraint" type="object">
    Used to set targets and limits for the amount of hours or shifts worked by employees within given periods.

    <Expandable title="properties">
      <ResponseField name="id" type="string" required>
        Unique identifier for the constraint.
      </ResponseField>

      <ResponseField name="labels" type="array of string">
        Labels for the constraint. Labels can be used to group constraints together. For example, if multiple constraints are related to the same shift type, they can all be labeled with the same label.
      </ResponseField>

      <ResponseField name="importance" type="string (enum: NONE | VERY_LOW | LOW | MEDIUM | HIGH | ...)">
        The importance of the constraint. The higher the importance, the more the solver will take the constraint into account.
      </ResponseField>

      <ResponseField name="filters" type="object">
        Filters to determine the scope of the constraint. Used to decide which employees and which shifts the constraint should be applied to. Filters use logical OR filtering - an employee or shift is included as long as it is targeted by any of the filters.
      </ResponseField>

      <Expandable title="filters – properties">
        <ResponseField name="employees" type="object">
          Used to filter which employees the constraint should be applied to. If not specified, the constraint applies to all employees.
        </ResponseField>

        <Expandable title="employees – properties">
          <ResponseField name="ids" type="array of string">
            List of employee ids that the constraint should be applied to.
          </ResponseField>

          <ResponseField name="labels" type="array of string">
            List of employee labels that the constraint should be applied to.
          </ResponseField>

          <ResponseField name="matchTypes" type="object" />

          <Expandable title="matchTypes – properties">
            <ResponseField name="ids" type="string (enum: NONE | ANY | ALL)">
              Used to indicate how to apply the id filters. For example, if set to NONE, entities with the specified ids will be excluded. Default: "ANY".
            </ResponseField>

            <ResponseField name="labels" type="string (enum: NONE | ANY | ALL)">
              Used to indicate how to apply the label filters. For example, if set to ANY, entities that have any of the specified labels will be included. Default: "ANY".
            </ResponseField>
          </Expandable>
        </Expandable>

        <ResponseField name="shifts" type="object">
          Used to filter which shifts the constraint should be applied to. If not specified, the constraint applies to all shifts.
        </ResponseField>

        <Expandable title="shifts – properties">
          <ResponseField name="ids" type="array of string">
            List of shift ids that the constraint should be applied to.
          </ResponseField>

          <ResponseField name="labels" type="array of string">
            List of shift labels that the constraint should be applied to.
          </ResponseField>

          <ResponseField name="matchTypes" type="object" />

          <Expandable title="matchTypes – properties">
            <ResponseField name="ids" type="string (enum: NONE | ANY | ALL)">
              Used to indicate how to apply the id filters. For example, if set to NONE, entities with the specified ids will be excluded. Default: "ANY".
            </ResponseField>

            <ResponseField name="labels" type="string (enum: NONE | ANY | ALL)">
              Used to indicate how to apply the label filters. For example, if set to ANY, entities that have any of the specified labels will be included. Default: "ANY".
            </ResponseField>
          </Expandable>
        </Expandable>

        <ResponseField name="work" type="object">
          Defines filtering for specific work that the constraint should be applied to. For example, it can be used to apply the constraint only to work carried out in specific roles.
        </ResponseField>

        <Expandable title="work – properties">
          <ResponseField name="roles" type="object">
            Used to apply the constraint only to work carried out in specific roles.
          </ResponseField>

          <Expandable title="roles – properties">
            <ResponseField name="ids" type="array of string">
              List of relevant role ids.
            </ResponseField>
          </Expandable>

          <ResponseField name="workloads" type="object">
            Used to apply the constraint only to work carried out with specific workload categories.
          </ResponseField>

          <Expandable title="workloads – properties">
            <ResponseField name="categories" type="array of string">
              If specified, the shift must have at least one of the workload categories specified in this list.
            </ResponseField>
          </Expandable>
        </Expandable>
      </Expandable>

      <ResponseField name="targets" type="object">
        Specifies the target utilization for the constraint. Targets can be specified in number of FTE hours, or in number of shifts worked during the period.
      </ResponseField>

      <Expandable title="targets – properties">
        <ResponseField name="minHours" type="number">
          The minimum number of hours that should be worked by employees on shifts that match the constraint in each period. This is treated as a target - it is not guaranteed that the number of hours worked will be greater than this value.
        </ResponseField>

        <ResponseField name="idealHours" type="number">
          The ideal number of hours that should be worked by employees on shifts that match the constraint in each period. This is treated as a target - it is not guaranteed that the number of hours worked will be exactly this value.
        </ResponseField>

        <ResponseField name="maxHours" type="number">
          The maximum number of hours that should be worked by employees on shifts that match the constraint in each period. This is treated as a hard limit - the number of hours worked will never exceed this value.
        </ResponseField>

        <ResponseField name="minShifts" type="integer">
          The minimum number of shifts that match the constraint that an employee should work in each period. This is treated as a target - it is not guaranteed that the number of shifts worked will be greater than this value.
        </ResponseField>

        <ResponseField name="idealShifts" type="integer">
          The ideal number of shifts that match the constraint that an employee should work in each period. This is treated as a target - it is not guaranteed that the number of shifts worked will be exactly this value.
        </ResponseField>

        <ResponseField name="maxShifts" type="integer">
          The maximum number of shifts that match the constraint that an employee should work in each period. This is treated as a hard limit - the number of shifts worked will never exceed this value.
        </ResponseField>
      </Expandable>

      <ResponseField name="bonusTime" type="object">
        Settings to determine if and how bonus time rules affect the constraint.
      </ResponseField>

      <Expandable title="bonusTime – properties">
        <ResponseField name="includeBonusHours" type="boolean">
          Whether or not bonus hours should be included in the calculation of an employee's total hours worked for the constraint. Default: true.
        </ResponseField>

        <ResponseField name="averageHoursThreshold" type="number">
          If a threshold is provided, bonus hours will only be included in the calculation of an employee's total hours worked if the average bonus hours per period exceed this threshold.
        </ResponseField>

        <ResponseField name="averageHoursCap" type="number">
          If a cap is provided, the average number of bonus hours per period will be capped at this value. The employee can be eligible for more bonus hours, but they will not be counted beyond this cap.
        </ResponseField>
      </Expandable>

      <ResponseField name="overlapRules" type="object">
        Specifies overlap thresholds that a shift must meet with the constraint's periods in order for it to be counted as relevant for the constraint.
      </ResponseField>

      <Expandable title="overlapRules – properties">
        <ResponseField name="minOverlapHours" type="integer">
          The minimum number of hours that a shift must overlap with the constraint in order to be counted as relevant for this constraint.
        </ResponseField>

        <ResponseField name="minOverlapPercentage" type="integer">
          The minimum percentage of the shift that must overlap with the constraint in order to be counted as relevant for this constraint.
        </ResponseField>
      </Expandable>

      <ResponseField name="periods" type="object">
        List of periods in the schedule. Periods can either be defined explicitly using custom definitions, or through a recurrent definition. A recurrent definition can be used to easily generate a list of similar periods (such as weeks, months, etc.).
      </ResponseField>

      <Expandable title="periods – properties">
        <ResponseField name="days" type="object">
          List of days in the schedule. Each day will become one period. By default, each period will last the entire day. If a startTime and/or endTime are specified, these will apply to each period.
        </ResponseField>

        <Expandable title="days – properties">
          <ResponseField name="dates" type="array of date (date)">
            List of dates in the schedule. Only allowed in CALENDAR payloads.
          </ResponseField>

          <ResponseField name="dayIndices" type="array of dayIndex">
            List of day indices in the schedule. Only allowed in RECURRING payloads.
          </ResponseField>

          <ResponseField name="daysOfWeek" type="array of dayOfWeek">
            List of days of the week. Will apply to all days in the schedule that match any of the specified weekdays.
          </ResponseField>

          <ResponseField name="startTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="endTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>
        </Expandable>

        <ResponseField name="customDefinitions" type="array of object">
          List of custom period definitions. Each custom period definition defines one period in the schedule.
        </ResponseField>

        <Expandable title="customDefinitions – item structure">
          <ResponseField name="startDay" type="object">
            Describes one day in the schedule. Can be defined as a date (in CALENDAR payloads) or as a day index (in RECURRING payloads).
          </ResponseField>

          <Expandable title="startDay – properties">
            <ResponseField name="date" type="string (date)">
              Date is specified in ISO8601 format YYYY-MM-DD. Can only be used when schedule type is CALENDAR.
            </ResponseField>

            <ResponseField name="dayIndex" type="integer">
              Day index relative to the first day of the period (starts at 0). Can only be used when schedule type is RECURRING.
            </ResponseField>
          </Expandable>

          <ResponseField name="endDay" type="object">
            Describes one day in the schedule. Can be defined as a date (in CALENDAR payloads) or as a day index (in RECURRING payloads).
          </ResponseField>

          <Expandable title="endDay – properties">
            <ResponseField name="date" type="string (date)">
              Date is specified in ISO8601 format YYYY-MM-DD. Can only be used when schedule type is CALENDAR.
            </ResponseField>

            <ResponseField name="dayIndex" type="integer">
              Day index relative to the first day of the period (starts at 0). Can only be used when schedule type is RECURRING.
            </ResponseField>
          </Expandable>

          <ResponseField name="startTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="endTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="applyTimeToAllDays" type="boolean">
            If true, the startTime and endTime will be applied to each individual day in the period. If false, the startTime will apply to the first day and the endTime will apply to the last day. Default: false.
          </ResponseField>
        </Expandable>

        <ResponseField name="recurrentDefinition" type="object">
          A recurrent definition to easily create a set of similar periods.
        </ResponseField>

        <Expandable title="recurrentDefinition – properties">
          <ResponseField name="daysPerPeriod" type="integer" required>
            The number of days in each period.
          </ResponseField>

          <ResponseField name="daysBetweenStarts" type="integer">
            The number of days between the start of each period. If not specified, this defaults to the value of daysPerPeriod, creating non-overlapping consecutive periods. Setting daysBetweenStarts to 1 will create a sliding window of periods.
          </ResponseField>

          <ResponseField name="startDay" type="object">
            Describes one day in the schedule. Can be defined as a date (in CALENDAR payloads) or as a day index (in RECURRING payloads).
          </ResponseField>

          <Expandable title="startDay – properties">
            <ResponseField name="date" type="string (date)">
              Date is specified in ISO8601 format YYYY-MM-DD. Can only be used when schedule type is CALENDAR.
            </ResponseField>

            <ResponseField name="dayIndex" type="integer">
              Day index relative to the first day of the period (starts at 0). Can only be used when schedule type is RECURRING.
            </ResponseField>
          </Expandable>

          <ResponseField name="endDay" type="object">
            Describes one day in the schedule. Can be defined as a date (in CALENDAR payloads) or as a day index (in RECURRING payloads).
          </ResponseField>

          <Expandable title="endDay – properties">
            <ResponseField name="date" type="string (date)">
              Date is specified in ISO8601 format YYYY-MM-DD. Can only be used when schedule type is CALENDAR.
            </ResponseField>

            <ResponseField name="dayIndex" type="integer">
              Day index relative to the first day of the period (starts at 0). Can only be used when schedule type is RECURRING.
            </ResponseField>
          </Expandable>

          <ResponseField name="startTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="endTime" type="string (time)">
            TIME ISO 8601 format hh:mm. Equivalent to the 24h format of a single day. Use 00:00 to represent midnight.
          </ResponseField>

          <ResponseField name="applyTimeToAllDays" type="boolean">
            If true, the startTime and endTime will be applied to each individual day in the period. If false, the startTime will apply to the first day and the endTime will apply to the last day. Default: false.
          </ResponseField>
        </Expandable>

        <ResponseField name="labels" type="array of string">
          Provide labels to re-use periods that were defined in the configuration.
        </ResponseField>
      </Expandable>
    </Expandable>
  </ResponseField>
</Card>

## How targets work

The constraint supports three types of targets for both hours and shifts:

* **Minimum targets** (`minHours`, `minShifts`): The solver will try to ensure employees work at least this amount. These are treated as soft targets and may not always be met if other constraints conflict.
* **Ideal targets** (`idealHours`, `idealShifts`): The solver will try to assign exactly this amount. This is useful when you want employees to work a specific number of hours or shifts.
* **Maximum limits** (`maxHours`, `maxShifts`): These are hard limits that will never be exceeded. The solver will strictly enforce these bounds.

<Info>
  You don't need to specify all targets - only include the ones relevant to your
  use case. For example, you can set only `maxHours` to cap the total hours, or
  only `idealShifts` to target a specific number of shifts.
</Info>

## Global utilization targets

Set utilization targets for the entire planning horizon. This is useful for ensuring employees receive a fair distribution of work across the entire schedule.

<Tip>
  The constraint below sets targets for `employee-1` across the entire planning horizon:

  * The employee should work at least 80 hours (soft target)
  * The employee should ideally work exactly 120 hours
  * The employee may work no more than 160 hours (hard limit)

  ```json theme={null}
  {
    "id": "euc-total-hours",
    "targets": {
      "minHours": 80,
      "idealHours": 120,
      "maxHours": 160
    },
    "filters": {
      "employees": {
        "ids": ["employee-1"]
      }
    }
  }
  ```
</Tip>

## Period-based utilization targets

All targets are applied to each period separately. By defining periods, you can create constraints that apply to specific time windows, such as weekly or monthly targets.

<Tip>
  The constraint below sets a weekly target for all employees. Each employee should ideally work 40 hours per week, with a minimum of 32 hours and a maximum of 48 hours.

  ```json theme={null}
  {
    "id": "euc-weekly-hours",
    "targets": {
      "minHours": 32,
      "idealHours": 40,
      "maxHours": 48
    },
    "periods": {
      "recurrentDefinition": {
        "daysPerPeriod": 7
      }
    }
  }
  ```
</Tip>

## Shift-based limits

You can limit the number of shifts of a specific type that employees can work. This is particularly useful for controlling undesirable shifts like night shifts or weekend work.

<Tip>
  The constraint below sets a strict upper bound of 2 night shifts per week for all employees. After an employee has worked 2 night shifts in a week, they cannot be assigned any more night shifts that week.

  ```json theme={null}
  {
    "id": "euc-night-shifts-per-week",
    "targets": {
      "maxShifts": 2
    },
    "filters": {
      "shifts": {
        "labels": ["night"]
      }
    },
    "periods": {
      "recurrentDefinition": {
        "daysPerPeriod": 7
      }
    }
  }
  ```
</Tip>

## Minimum shift requirements

You can also set minimum shift requirements to ensure employees receive a certain amount of work.

<Tip>
  The constraint below ensures that each employee works at least 3 shifts per week, with an ideal target of 5 shifts. This helps prevent employees from being underutilized.

  ```json theme={null}
  {
    "id": "euc-min-shifts-per-week",
    "targets": {
      "minShifts": 3,
      "idealShifts": 5
    },
    "periods": {
      "recurrentDefinition": {
        "daysPerPeriod": 7
      }
    }
  }
  ```
</Tip>

## Combining hours and shifts targets

You can combine both hours and shifts targets in a single constraint to create more nuanced requirements.

<Tip>
  The constraint below ensures employees work between 3-5 shifts per week, with each shift ideally being around 8 hours. This creates a balanced schedule where employees get enough shifts but not too many.

  ```json theme={null}
  {
    "id": "euc-balanced-weekly",
    "targets": {
      "minShifts": 3,
      "idealShifts": 4,
      "maxShifts": 5,
      "minHours": 24,
      "idealHours": 32,
      "maxHours": 40
    },
    "periods": {
      "recurrentDefinition": {
        "daysPerPeriod": 7
      }
    }
  }
  ```
</Tip>

## Setting limits on specific roles

You can set limits on the number of hours or shifts that employees can be assigned to specific roles.

<Tip>
  The constraint below limits employees to a maximum of 50 hours per week worked with role `role-1`, while aiming for them to work at least 35 hours.

  ```json theme={null}
  {
    "id": "euc-role-1-max-50-hours",
    "targets": {
      "minHours": 35,
      "idealHours": 40,
      "maxHours": 50
    },
    "filters": {
      "work": {
        "roleIds": ["role-1"]
      }
    },
    "periods": {
      "recurrentDefinition": {
        "daysPerPeriod": 7
      }
    }
  }
  ```
</Tip>

<Tip>
  The constraint below ensures that employees work at least 2 weekend shifts per month, helping to distribute weekend work fairly.

  ```json theme={null}
  {
    "id": "euc-weekend-shifts",
    "targets": {
      "minShifts": 2,
      "idealShifts": 3
    },
    "filters": {
      "shifts": {
        "labels": ["weekend"]
      }
    },
    "periods": {
      "recurrentDefinition": {
        "daysPerPeriod": 30
      }
    }
  }
  ```
</Tip>
