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

# Fill API Changelog

> Track new features, improvements, and updates to the Solvice Fill API

Stay updated with the latest enhancements, features, and improvements to the Solvice Fill API. Each release brings new capabilities to help you assign employees to shifts while respecting skills, availability, and labor rules.

<Update label="June 2026" description="Declarative rule engine with per-rule weights">
  ## 📋 Declarative Rule Engine

  The Fill solver now ships a full declarative rule engine. Counter rules, sequence rules, rest rules, and shift patterns are all enforced together and can each be tuned independently through the top-level `weights` object.

  ### New `MAX_CONSECUTIVE_DAYS` rule type

  A new rule `type` bounds the longest run of consecutive working days directly. Pair it with a `COUNTER` constraint and a `max`: the solver finds the longest consecutive-day streak and penalizes anything above the limit.

  ```json theme={null}
  {
    "rules": [
      {
        "constraint": "COUNTER",
        "type": "MAX_CONSECUTIVE_DAYS",
        "max": 5
      }
    ]
  }
  ```

  The full set of rule types is now: `HOURS_WORKED`, `DAYS_WORKED`, `DAYS_IDLE`, `WEEKENDS_WORKED`, `WEEKENDS_IDLE`, `SHIFT_TYPES_WORKED`, `SHIFT_TYPES_HOURS_WORKED`, and `MAX_CONSECUTIVE_DAYS`.

  ### Per-rule-type weights

  Every rule family now has its own weight, so you can decide exactly how hard the solver pushes on each one. Set them under the request's top-level `weights` object, using the `<weight><priority>` format where priority is `hard`, `medium`, or `soft`.

  <Tabs>
    <Tab title="Counter">
      Weights for `COUNTER` rules — how strongly to respect counts over a period.

      ```json theme={null}
      {
        "weights": {
          "counterDaysWorked": "10medium",
          "counterDaysIdle": "10medium",
          "counterHoursWorked": "10medium",
          "counterShiftTypesWorked": "10medium",
          "counterShiftTypesHours": "10medium",
          "counterWeekendsWorked": "10medium",
          "counterWeekendsIdle": "10medium",
          "counterMaxConsecutiveDays": "10medium"
        }
      }
      ```
    </Tab>

    <Tab title="Sequence">
      Weights for `SEQUENCE` rules — how strongly to respect consecutive runs.

      ```json theme={null}
      {
        "weights": {
          "sequenceDaysWorked": "10medium",
          "sequenceDaysIdle": "10medium",
          "sequenceHoursWorked": "10medium",
          "sequenceShiftTypesWorked": "10medium",
          "sequenceShiftTypesHours": "10medium",
          "sequenceWeekendsWorked": "10medium",
          "sequenceWeekendsIdle": "10medium",
          "sequenceMaxConsecutiveDays": "10medium"
        }
      }
      ```
    </Tab>

    <Tab title="Rest">
      Weights for `rests` — rest duration, consecutive rest, and rest before/after a shift.

      ```json theme={null}
      {
        "weights": {
          "restMinDuration": "10medium",
          "restMinConsecutive": "10medium",
          "restBeforeShift": "10medium",
          "restAfterShift": "10medium"
        }
      }
      ```
    </Tab>

    <Tab title="Pattern">
      Weights for shift `patterns`, split by how the pattern should be satisfied.

      ```json theme={null}
      {
        "weights": {
          "patternPreferred": "10medium",
          "patternUnpreferred": "5soft",
          "patternProhibited": "100hard"
        }
      }
      ```
    </Tab>
  </Tabs>

  ### Conditional rules and rolling windows

  Rules can chain with `then` to trigger a follow-up rule when a threshold is crossed, and a `period.duration` turns any rule into a sliding window.

  ```json theme={null}
  {
    "rules": [
      {
        "constraint": "COUNTER",
        "type": "HOURS_WORKED",
        "shifts": ["NIGHT"],
        "period": { "duration": "PT72H" },
        "max": 20,
        "then": {
          "constraint": "SEQUENCE",
          "type": "DAYS_IDLE",
          "min": 2
        }
      }
    ]
  }
  ```

  **Learn more:**

  * [Rules and constraints](/guides/fill/examples/rule)
  * [Rest requirements](/guides/fill/examples/rest)
  * [Patterns](/guides/fill/examples/pattern)
</Update>

<Update label="February 2026" description="Reliability and scoring fixes">
  ## 🛡️ Employee Reference Validation

  Requests that reference an employee that does not exist — in a shift's `employees` list or its `blocklist` — are now validated up front instead of failing deep inside the solver. This produces clearer errors and prevents silent mis-assignments (PRD-1247).

  <Warning>
    Every name used in a shift's `employees` list or `blocklist` must match a name declared in the top-level `employees` list. Unknown references are rejected during validation with a clear error message.
  </Warning>

  ## 💶 Wage Costs Scoring Fix

  The Wage Costs constraint could produce a negative match weight in some configurations, distorting the soft score. Match weights are now clamped so wage-based optimization behaves as expected (PRD-1243).
</Update>

<Update label="January 2026" description="Assignment control and API hardening">
  ## 🎚️ Control Solve Time with `millis`

  The solve endpoint accepts a new `millis` query parameter to cap how long the solver runs, giving you direct control over the latency/quality trade-off.

  ```bash theme={null}
  POST /v2/fill/solve?millis=5000
  ```

  ## 🔢 `max` Drives Shift Assignment Count

  The number of assignments generated for a shift is now taken from the shift `max` field, falling back to the deprecated `value` field when `max` is absent.

  <CodeGroup>
    ```json Recommended theme={null}
    {
      "shifts": [
        { "name": "morning", "from": "2026-01-05T09:00:00", "to": "2026-01-05T17:00:00", "min": 2, "max": 3 }
      ]
    }
    ```

    ```json Deprecated theme={null}
    {
      "shifts": [
        { "name": "morning", "from": "2026-01-05T09:00:00", "to": "2026-01-05T17:00:00", "value": 3 }
      ]
    }
    ```
  </CodeGroup>

  <Note>
    `value` continues to work for backward compatibility but is deprecated. Use `min` and `max` to express an exact staffing range.
  </Note>

  ## ✅ Additional API Changes

  * **Optional rule period** — `period` on a period rule is now optional and defaults to the entire planning horizon when omitted.
  * **Input hardening** — null-byte sanitization and string-list validation were added across Fill request fields, including `preference`, `employees`, and `blocklist`.
</Update>

<Update label="December 2025" description="Fill API v2 launch">
  ## 🎉 Fill API v2

  Fill API v2 is a ground-up redesign of shift filling: assign employees to shifts while respecting skills, availability, labor rules, and preferences.

  ### Endpoints

  <CodeGroup>
    ```bash Solve theme={null}
    POST /v2/fill/solve
    ```

    ```bash Evaluate theme={null}
    POST /v2/fill/evaluate
    ```

    ```bash Suggest theme={null}
    POST /v2/fill/suggest
    ```
  </CodeGroup>

  Retrieve results asynchronously with `GET /v2/fill/jobs/{id}/status`, `.../solution`, and `.../explanation`.

  ### Core capabilities

  <Tabs>
    <Tab title="Matching">
      * Multi-level skill matching (required skills as hard constraints, proficiency levels, soft-skill preferences)
      * Time-based availability windows and day-of-week restrictions
      * Locked (pre-assigned) and blocked employee–shift pairs
    </Tab>

    <Tab title="Labor rules">
      * `COUNTER` and `SEQUENCE` rules over working days, idle days, hours, weekends, and shift types
      * Mandatory `rests` between and across shifts
      * Weekend definitions via `options.idleWeekend`
    </Tab>

    <Tab title="Fairness">
      * Workload balancing across employees by hours or shift counts
      * Shift `patterns` to encourage or discourage series of shifts
      * Three-tier hard / medium / soft scoring
    </Tab>
  </Tabs>

  ### Migrating from v1

  Several v1 fields were renamed or replaced for consistency and flexibility.

  | Deprecated    | Replacement         |
  | ------------- | ------------------- |
  | `contracts`   | `rules`             |
  | `blacklist`   | `blocklist`         |
  | shift `value` | shift `min` / `max` |

  <Card title="Fill Migration Guide" icon="arrow-right-arrow-left" href="/guides/fill/migration">
    Full list of breaking changes and new features when moving to v2
  </Card>
</Update>
