API Documentation

When submitting a schedule for solving, you're asking our AI to assign employees to shifts while respecting constraints and preferences. This guide explains the structure of that request.


Request structure

A schedule submission contains seven required fields:

{
  "employees": [],
  "shifts": [],
  "spots": [],
  "settings": {},
  "callbackUrl": "https://api.yourdomain.com/solver-callback",
  "callbackAuthenticationHeaderName": "X-API-Key",
  "callbackAuthenticationHeaderValue": "your-secret-key"
}

Additionally, you can optionally specify:

{
  "numberOfAllowedShiftCollisions": 0,
  "freePeriodRequirements": [],
  "coverageCompetencyRequirements": []
}

Core collections

Employees

The people available for scheduling. Each employee has skills, team memberships, contract rules, and preferences. See Employees in your schedule for details.

Shifts

The work periods that need to be filled. Each shift specifies when it occurs, which spot it's for, whether it's mandatory or optional, and can include employee preferences. See Shifts in your schedule for details.

Spots

Locations or roles where work happens (e.g., "Emergency Room", "Reception Desk"). Spots have skill and team requirements that constrain which employees can work there. See Spots in your schedule for details.

Solver configuration

Settings

Fine-tune how the solver weighs different constraints. Want to prioritize employee preferences over even shift distribution? Adjust the weights. See Settings in your request for the full list of configurable constraints.

Free period requirements

Use freePeriodRequirements when a rule requires duty-to-duty free intervals that should be chosen by the solver, not pre-created as fake shifts. See Free period requirements for the request and response fields.

Coverage competency requirements

Use coverageCompetencyRequirements when coverage is collective: a selected group of assigned shifts must include enough employees with a required competency. Put the requirements at the top level, next to employees, shifts, and settings.

Each requirement selects shifts explicitly with shiftIds, then requires at least minEmployeeCount distinct assigned employees with competencyId. Enable the rule with settings.coverageCompetencyCoverage.

For shifts covered by these collective requirements, set roomCompetencyPolicy to COVERAGE_WINDOW. Other shifts should omit the field or use PER_ASSIGNEE, which keeps the standard rule that each assigned employee must satisfy the spot's room competencies.

{
  "shifts": [
    {
      "id": 101,
      "spot": 5,
      "start": "2024-03-15T06:00:00Z",
      "end": "2024-03-15T14:00:00Z",
      "importance": "MANDATORY",
      "roomCompetencyPolicy": "COVERAGE_WINDOW",
      "fixed": false
    }
  ],
  "coverageCompetencyRequirements": [
    {
      "id": 1,
      "shiftIds": [101],
      "competencyId": 100,
      "minEmployeeCount": 1
    }
  ],
  "settings": {
    "coverageCompetencyCoverage": {
      "firstPriorityWeight": 20,
      "secondPriorityWeight": 0,
      "thirdPriorityWeight": 0,
      "fourthPriorityWeight": 0
    }
  }
}

Do not put coverageCompetencyCoverage at the top level. It is a setting.

Overlay shifts with explicit hosts

Use an overlay shift when a duty needs its own shift, but the person assigned to it must also be working an ordinary shift at the same time or immediately before the overlay starts. This is useful for meetings, conferences, or other named responsibilities that should be visible in the solved schedule without adding more worked minutes.

Model it with the overlay shift, the eligible host shifts, and a top-level requirement:

  • The ordinary day or evening shift carries the worked minutes.
  • The overlay shift carries the name and assignment for the extra duty. It has durationMultiplier: 0.0.
  • sameEmployeeOverlappingShiftRequirements names the overlay shiftId and the exact ordinary shift IDs that may host it.

Enable the rule with settings.sameEmployeeOverlappingShift. If the two shifts overlap in time, also allow the relevant spot collision so the same employee can hold both.

{
  "shifts": [
    {
      "id": 201,
      "name": "Day shift",
      "spot": 10,
      "start": "2024-03-20T07:00:00Z",
      "end": "2024-03-20T15:00:00Z",
      "importance": "MANDATORY",
      "fixed": false
    },
    {
      "id": 301,
      "name": "Borgerkonference",
      "spot": 25,
      "start": "2024-03-20T12:00:00Z",
      "end": "2024-03-20T13:00:00Z",
      "importance": "MANDATORY",
      "durationMultiplier": 0.0,
      "allowedCollisionSpots": [10],
      "fixed": false
    }
  ],
  "sameEmployeeOverlappingShiftRequirements": [
    {
      "id": 301,
      "shiftId": 301,
      "overlappingShiftIds": [201]
    }
  ],
  "settings": {
    "sameEmployeeOverlappingShift": {
      "firstPriorityWeight": 20,
      "secondPriorityWeight": 0,
      "thirdPriorityWeight": 0,
      "fourthPriorityWeight": 0
    }
  }
}

This is the shape used for Borgerkonference: the Borgerkonference entry is its own shift, and anyone assigned to it must also have an overlapping eligible day or evening shift.

Callback

The solver processes schedules asynchronously. When complete, it POSTs the solution to your callbackUrl. Use the authentication header fields to secure this callback; the solver will include your specified header in the callback request.

Your callback endpoint should:

  • Accept POST requests with JSON payloads
  • Return 200 OK promptly (process the solution asynchronously if needed)
  • Handle authentication using the header you specified

If your callback fails, the solver will not retry. You can retrieve results later via GET /api/v1/{id}.


Next steps