Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
  • Platform
Try models
  • Field Service Routing
  • Upgrading to the latest versions

Field Service Routing

    • Introduction
    • Planning AI concepts
    • Metrics and optimization goals
    • Getting started with field service routing
    • Understanding the API
    • Constraints
    • Vehicle resource constraints
      • Shift hours and overtime
      • Lunch breaks and personal appointments
      • Fairness
      • Technician costs
    • Visit service constraints
      • Time windows and opening hours
      • Skills
      • Visit dependencies
      • Visit requirements
      • Multi-vehicle visits
      • Priority visits and optional visits
    • Real-time planning
      • Real-time planning
      • Real-time planning: extended visit
      • Real-time planning: reassignment
      • Real-time planning: emergency visit
      • Real-time planning: no show
      • Real-time planning: technician ill
      • Real-time planning: pinning visits
    • Recommendations
      • Recommendations
      • Visit time window recommendations
      • Visit group time window recommendations
    • Time zones and daylight-saving time (DST)
    • New and noteworthy
    • Upgrading to the latest versions
    • Feature requests
    • Reference guide

Upgrading to the latest versions

From 0.39.0 to 0.40.0

In order to avoid confusion around the fixed and floating breaks, the API has been simplified for breaks. Instead of using minStartTime and maxStartTime to determine if a break is a fixed/floating break, there is now a field type which can be set to either FIXED or FLOATING.

Before:

{
"requiredBreaks":[
  {
   "id": "requiredBreak",
   "minStartTime": "2024-01-01T08:00:00Z",
   "maxStartTime": "2024-01-01T08:00:00Z",
   "maxEndTime": "2024-01-01T12:00:00Z",
   "location": [
     49.190922,
     16.624466
   ],
   "costImpact": "PAID",
  },
  {
   "id": "floatingBreak",
   "minStartTime": "2024-01-01T08:00:00Z",
   "duration": "PT1H",
   "costImpact": "PAID",
  }
 ]
}

After:

{
"requiredBreaks":[
  {
   "id": "requiredBreak",
   "type": "FIXED",
   "startTime": "2024-01-01T08:00:00Z",
   "endTime": "2024-01-01T12:00:00Z",
   "location": [
     49.190922,
     16.624466
   ],
   "costImpact": "PAID",
  },
  {
   "id": "floatingBreak",
   "type": "FLOATING",
   "minStartTime": "2024-01-01T08:00:00Z",
   "duration": "PT1H",
   "costImpact": "PAID",
  }
 ]
}

Affected endpoints:

  • GET: /v1/demo-data/{demoDataId}

  • GET: /v1/demo-data/{demoDataId}/input

  • POST: /v1/route-plans

  • POST: /v1/route-plans/recommendations/visit-recommend-time-windows

  • POST: /v1/route-plans/score-analysis

  • GET: /v1/route-plans/{id}/input

  • GET: /v1/route-plans/{id}/model-request

  • POST: /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

  • POST: /v1/route-plans/recommendations/visit-group-recommend-time-windows

  • POST: /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

From 0.38.0 to 0.39.0

When submitting a new route plan with an unspecified unimprovedSpentLimit in the run termination configuration, the run will use the new diminished returns termination.

Diminished returns termination is enabled by default when unimprovedSpentLimit isn’t present. For existing datasets, remove unimprovedSpentLimit to enable diminished returns termination.

Before:

{
  "config": {
    "run": {
      "name": "My run",
      "termination": {
        "spentLimit": "PT30M",
        "unimprovedSpentLimit": "PT1M"
    }
  }
}

After:

{
  "config": {
    "run": {
      "name": "My run",
      "termination": {
        "spentLimit": "PT30M"
    }
  }
}

If you were not setting the unimprovedSpentLimit and you need to keep the old behaviour, set the unimprovedSpentLimit to the value of spentLimit:

Before:

{
  "config": {
    "run": {
      "name": "My run",
      "termination": {
        "spentLimit": "PT30M"
    }
  }
}

After (only if you want to keep the old behaviour):

{
  "config": {
    "run": {
      "name": "My run",
      "termination": {
        "spentLimit": "PT30M",
        "unimprovedSpentLimit": "PT30M"
    }
  }
}

Affects the following REST endpoints:

  • POST /v1/route-plan

From 0.31.0 to 0.32.0

Recommendation time windows now has the fields minStartTime, maxStartTime, and maxEndTime. They replace the now deprecated startTime and endTime. Adding maxStartTime opens the possibility to get recommendations for fixed-start visits (these are visits where minStartTime equals maxStartTime).

Visually this can be represented by the following diagram.

RecommendationTimeWindow ---> RecommendationTimeWindow
|- startTime ----------------> minStartTime
|- endTime ----------|      ++ maxStartTime
                     |-------> maxEndTime

before:

{
    "startTime": "2024-01-01T08:00:00Z",
    "endTime": "2024-01-01T12:00:00Z"
}

after (assuming that the start time is not fixed):

{
    "minStartTime": "2024-01-01T08:00:00Z",
    "maxStartTime": null,
    "maxEndTime": "2024-01-01T12:00:00Z"
}

Affects the following REST endpoints:

  • POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

From 0.29.0 to 0.30.0

Fine-grained priority

Priority is now defined as a number between 1 and 10 (both included), with 10 being the lowest priority and 1 being the highest priority. The default priority is "6". The former values LOW, NORMAL, HIGH and CRITICAL are now deprecated. They are internally mapped to: 10, 6, 5 and 1.

Affects the following REST endpoints:

  • POST /v1/route-plan

  • POST /v1/route-plans/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/score-analysis

  • POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

From 0.25.0 to 0.26.2

Justifications retrieved for a completed run are limited to 100 per constraint

The number of justifications that is stored and can be retrieved for a completed run has been limited to 100 per each constraint.

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}/score-analysis?includeJustifications=true

To get the full list of justifications, use the following endpoint:

  • POST /v1/route-plans/score-analysis?includeJustifications=true

From 0.24.0 to 0.25.0

0.25.0 is backward compatible with 0.24.0 and no migration is required.

From 0.23.0 to 0.24.0

0.24.0 is backward compatible with 0.23.0 and no migration is required.

From 0.22.0 to 0.23.0

0.23.0 is backward compatible with 0.22.0 and no migration is required.

From 0.21.0 to 0.22.0

0.22.0 is backward compatible with 0.21.0 and no migration is required.

From 0.20.0 to 0.21.0

0.21.0 is backward compatible with 0.20.0 and no migration is required.

From 0.19.0 to 0.20.0

Visit serviceDurationAdjustment is now deprecated

The attribute Visit.serviceDurationAdjustment is now deprecated and will be removed in the next version.

In the case you have been using positive serviceDurationAdjustment, please increase the Visit.serviceDuration value and keep the Visit.serviceDurationBreakdown values. This way the adjustment will not be affected by the skill multipliers, achieving the same behavior as before. For example:

serviceDuration serviceDurationBreakdown serviceDurationAdjustment

OLD

"PT1H30M"

"electrician": "PT30M", "plumber": "PT30M"

"PT10M"

NEW

"PT1H40M"

"electrician": "PT30M", "plumber": "PT30M"

null

By removing the serviceDurationAdjustment, you can have full control of how the skill multipliers will be affecting the result.

In the case you have been using negative serviceDurationAdjustment, you already had to modify the serviceDurationBreakdown as well:

serviceDuration serviceDurationBreakdown serviceDurationAdjustment

OLD

"PT1H"

"electrician": "PT30M", "plumber": "PT30M"

"PT-10M"

NEW

"PT50M"

"electrician": "PT25M", "plumber": "PT25M"

null

From 0.18.0 to 0.19.0

0.19.0 is backward compatible with 0.18.0 and no migration is required.

From 0.17.0 to 0.18.0

The version 0.18.0 introduces changes to the API. The changes are not backward compatible and require changes to the client code.

Local date time replaced by date time with offset to UTC

All ISO 8601 local date time types have been replaced by ISO 8601 local date time with offset to UTC (Coordinated Universal Time) to support multiple time zones.

Affects all REST endpoints starting with /v1/route-plans.

before (start and end are just examples, all datetime attributes are affected):

{
    "start": "2024-01-01T08:00:00",
    "end": "2024-01-01T12:00:00"
}

after (assuming the original local date time values are in UTC):

{
    "start": "2024-01-01T08:00:00Z",
    "end": "2024-01-01T12:00:00Z"
}

From 0.16.0 to 0.17.0

No migration needed.

From 0.15.0 to 0.16.0

No migration needed.

From 0.14.0 to 0.15.0

The version 0.15.0 introduces changes to the API. The changes are not backward compatible and require changes to the client code.

Unavailability and floating break is replaced by a break

Both unavailability and floating break have been replaced by a single concept of a break in the model input.

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/

  • POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-group-recommend-time-windows

before:

{
  "vehicles": [
    {
      "id": "vehicle1",
      "shifts": [
        {
          "id": "shift1",
          "unavailabilities": [
            {
              "id": "un1",
              "start": "2024-01-01T08:00:00",
              "end": "2024-01-01T12:00:00",
              "location": [49.288087,16.562172]
            }
          ],
          "floatingBreaks": [
            {
              "id": "fb1",
              "triggerTime": "2024-01-01T08:00:00",
              "duration": "PT1H"
            }
          ]
        }
      ]
    }
  ]
}

after:

{
  "vehicles": [
    {
      "id": "vehicle1",
      "shifts": [
        {
          "id": "shift1",
          "requiredBreaks": [
            {
              "id": "un1",
              "minStartTime": "2024-01-01T08:00:00",
              "maxStartTime": "2024-01-01T08:00:00",
              "duration": "PT4H",
              "location": [49.288087,16.562172]
            },
            {
              "id": "fb1",
              "minStartTime": "2024-01-01T08:00:00",
              "duration": "PT1H"
            }
          ]
        }
      ]
    }
  ]
}

Vehicle shift itinerary contains also breaks

The vehicle shift in both the model input and output now contains itinerary. The itinerary is a list of visits and breaks in the order they are visited or taken.

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/

  • POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-group-recommend-time-windows

before (model output):

{
  "vehicles": [
    {
      "id": "vehicle1",
      "shifts": [
        {
          "id": "shift1",
          "itinerary": [
            {
              "id": "visit1",
              "arrivalTime": "2024-03-21T08:00:00",
              ...
            },
            {
              "id": "visit2",
              "arrivalTime": "2024-03-21T10:00:00",
              ...
            }
          ]
        }
      ]
    }
  ]
}

after (model output):

{
  "vehicles": [
    {
      "id": "vehicle1",
      "shifts": [
        {
          "id": "shift1",
          "itinerary": [
            {
              "id": "visit1",
              "kind": "VISIT",
              "arrivalTime": "2024-03-21T08:00:00",
                ...
            },
            {
              "id": "break1",
              "kind": "BREAK",
              "startTime": "2024-03-21T08:00:00",
              "endTime": "2024-03-21T10:00:00",
              ...
            },
            {
              "id": "visit2",
              "kind": "VISIT",
              "arrivalTime": "2024-03-21T10:00:00",
              ...
            }
          ]
        }
      ]
    }
  ]
}

Similarly, the itinerary is used in the model input when specifying already assigned visits or breaks:

before (model input):

{
  "vehicles": [
    {
      "id": "vehicle1",
      "shifts": [
        {
          "id": "shift1",
          "visits": [
            "visit1",
            "visit2"
          ]
        }
      ]
    }
  ]
}

after (model input):

{
  "vehicles": [
    {
      "id": "vehicle1",
      "shifts": [
        {
          "id": "shift1",
          "itinerary": [
            {
              "id": "visit1",
              "kind": "VISIT"
            },
            {
              "id": "break1",
              "kind": "BREAK"
            },
            {
              "id": "visit2",
              "kind": "VISIT"
            }
          ]
        }
      ]
    }
  ]
}

Tags related to skills/trade are superseded by skills

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/

  • POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-group-recommend-time-windows

Using the tags mechanism for vehicle shifts' skills or trades is deprecated and users should switch to skills (the items in bold break backward compatibility):

  • global skills attribute has been added for declaration of all used skill names (validation purposes),

  • a visit can specify required skills and their levels in requiredSkills attribute, see Skill Requirement for details,

  • a shift can declare the skills, their levels and service duration multipliers in skills attribute, see Skill Definition for details,

  • the visit.serviceDurationBreakdown[].tag attribute has been replaced by skill attribute, see Service Duration Breakdown for details,

  • the shift.serviceDurationMultipliers array has been removed and is replaced by skills[].multiplier attribute, see Skill Definition for details,

  • a shift can declare temporarySkillSets in addition to temporaryTagSets, please see Temporary Skill Sets for details.

Before:

{
  "tags": [
    {"name":"plumber"},
    {"name":"electrician"},
    {"name":"north"},
    {"name":"emergency"}
  ],
  "visits": [
    {
      "id":"1",
      "requiredTags": ["plumber","north"],
      "serviceDurationBreakdown": [
        {
          "tag": "plumber",
          "duration": "PT1H"
        }
      ]
      ...
    },
    ...
  ],
  "vehicles": [
    "id": "vehicle1",
    "shifts": [
      {
        "id": "shift1",
        "tags": ["plumber", "north"],
        "serviceDurationMultipliers": [
          {
            "tag": "plumber",
            "multiplier": 0.5
          }
        ],
        "temporaryTagSets": [
          {
            "start": "2024-01-01T08:00:00",
            "end": "2024-01-01T12:00:00",
            "tags": [
              "electrician", "emergency"
            ]
          }
        ],
    ...
  ],
  ...
}

After:

{
  "skills": ["plumber", "electrician"],
  "tags": [
    {"name":"north"},
    {"name":"emergency"}
  ],
  "visits": [
    {
      "id":"1",
      "requiredSkills": [
        {
          "name": "plumber"
        }
      ],
      "requiredTags": ["north"],
      "serviceDurationBreakdown": [
        {
          "skill": "plumber",
          "duration": "PT1H"
        }
      ]
    },
    ...
  ],
  "vehicles": [
    {
      "id": "vehicle1",
      "shifts": [
        {
          "id": "shift1",
          "skills": [
            {
              "name": "plumber",
              "multiplier": 0.5
            }
          "temporarySkillSets": [
            {
              "start": "2024-01-01T08:00:00",
              "end": "2024-01-01T12:00:00",
              "skills": [
                {
                  "name": "electrician"
                }
              ]
            }
          ],
          "tags": ["north"],
          "temporaryTagSets": [
            {
              "start": "2024-01-01T08:00:00",
              "end": "2024-01-01T12:00:00",
              "tags": [
                "emergency"
              ]
            }
          ],
      ...
  ],
  ...
}

From 0.13.1 to 0.14.0

The version 0.14.0 introduces changes to the API. The changes are not backward compatible and require changes to the client code.

Route plan request format changed

The request format is now different from the response format. The request format now brings more structure in terms of separating the input data from the configuration data.

Affects the following REST endpoints:

  • POST /v1/route-plans/

Before:

{
  "constraintConfiguration" : {
    "maxSoftShiftEndTimeWeight" : 1
  },
  "vehicles": [
    ...
  ],
  "visits": [
    ...
  ],
  ...
}

After:

{
  "config": {
    "model" : {
      "overrides" : {
        "maxSoftShiftEndTimeWeight" : 1
      }
    }
  },
  "modelInput" : {
    "vehicles": [
      ...
    ],
    "visits": [
      ...
    ],
    ...
  }
}

Route plan response format changed

Similarly to the request format, the response format now brings more structure in the data and some attribute renaming as well. Importantly, the response no longer repeats the input data, but contains only vehicle shift itineraries grouped by vehicles.

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

Before:

{
  "constraintConfiguration" : {
    "maxSoftShiftEndTimeWeight" : 1
  },
  "vehicles": [
    "id": "vehicle1",
    "shifts": [
      {
        "id": "shift1",
        "visits": [
          "visit1",
          "visit2"
        ],
        "statistics": {
          "totalTravelTime": "PT3H",
          ...
        },
        ...
      }
    ],
  ],
  "visits": [
    {
      "id": "visit1",
      "arrivalTime": "2024-03-21T08:00:00",
      ...
    },
    {
      "id": "visit2",
      "arrivalTime": "2024-03-21T10:00:00",
      ...
    }
  ],
  "status" : {
    "id" : "model-run-id",
    "solverStatus" : "COMPLETED",
    ...
  }
  ...
}

After:

{
  "run": {
    "id" : "model-run-id",
    "solverStatus" : "COMPLETED",
    ...
  },
  "modelOutput" : {
    "vehicles": [{
      "id": "vehicle1",
      "shifts": [{
          "id": "shift1",
          "itinerary": [
            {
              "visit": "visit1",
              "arrivalTime": "2024-03-21T08:00:00",
              ...
            },
            {
              "visit": "visit2",
              "arrivalTime": "2024-03-21T10:00:00",
              ...
            }
          ],
          "metrics": {
            "totalTravelTime": "PT3H",
            ...
          }
        }
      ]
      ...
    }
    ]
  },
  "kpis": {
    "totalTravelTime": "PT30H",
    ...
  }
}

Route plan status request replaced by run request

The route plan status request has been replaced by the run request.

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}/status

Before:

  • GET /v1/route-plans/{id}/status

After:

  • GET /v1/route-plans/{id}/run

Recommendations request format has changed

The recommend time windows request format for both visits and visit groups reflects the changes to the request format of the route plan:

  • the attribute routePlan has been renamed to modelInput

  • the attribute constraintConfiguration has been moved from the routePlan to config.model.overrides

Affects the following REST endpoints:

POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

POST /v1/route-plans/recommendations/visit-recommend-time-windows

POST /v1/route-plans/recommendations/visit-group-recommend-time-windows

Before:

{
  "maxNumberOfRecommendationsPerTimeWindow": 3,
  "timeWindows": [
  ...
  ],
  "fitVisitId": "visit999",
  "routePlan": {
    "constraintConfiguration" : {
      "maxSoftShiftEndTimeWeight" : 1
    },
    "vehicles": [
      ...
    ],
    "visits": [
      ...
    ],
    ...
  }
}

After:

{
  "maxNumberOfRecommendationsPerTimeWindow": 3,
  "timeWindows": [
  ...
  ],
  "fitVisitId": "visit999",
  "config": {
    "model" : {
      "overrides" : {
        "maxSoftShiftEndTimeWeight" : 1
      }
    }
  },
  "modelInput": {
    "vehicles": [
      ...
    ],
    "visits": [
      ...
    ],
    ...
  }
}

Vehicle shifts moved under VehicleRoutePlan.vehicles, start and end attributes changed

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/

  • POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-group-recommend-time-windows

All vehicle shifts have been moved from VehicleRoutePlan.vehicleShifts to Vehicle.shifts of the corresponding vehicle in VehicleRoutePlan.vehicles. The attribute vehicle has been removed from VehicleShift.

The VehicleShift attribute shiftStartsFrom has been removed. The following VehicleShift attributes have been replaced as follows:

Attribute Replacement Description

shiftStartTime

minStartTime and minFirstArrivalTime

For vehicle shifts starting from the shift’s start location, set minStartTime.

For vehicle shifts starting from the shift’s first assigned visit, set minFirstVisitArrivalTime.

Both attributes can be set to ensure a lower bound for the vehicle shift start to avoid potential very-early shift start due to a long travel time to the first visit.

At least one of minStartTime and minFirstVisitArrivalTime attributes has to be set.

endLocationMaxArrivalTimeHardLimit

maxEndTime

endLocationMaxArrivalTimeSoftLimit

maxSoftEndTime

lastVisitMaxDepartureTimeHardLimit

maxLastVisitDepartureTime

lastVisitMaxDepartureTimeSoftLimit

maxSoftLastVisitDepartureTime

Before:

{
  "vehicles": [
    {"id": "Ann", "vehicleType": "VAN"}
  ],
  "vehicleShifts": [
    {"id":"Ann-1","startLocation":[49.288087,16.562172],"shiftStartTime":"2024-03-21T08:00:00", "endLocationMaxArrivalTimeHardLimit": "2024-03-21T20:00:00", "endLocationMaxArrivalTimeSoftLimit": "2024-03-21T18:00:00", "lastVisitMaxDepartureTimeHardLimit": "2024-03-21T19:00:00", "lastVisitMaxDepartureTimeSoftLimit": "2024-03-21T17:00:00", ...},
    {"id":"Ann-2","startLocation":[49.288087,16.562172],"shiftStartTime":"2024-03-22T08:00:00", "shiftStartsFrom": "FIRST_VISIT", ...},
    ...
  ],
  ...
}

After:

{
  "vehicles":[
    {"id":"Ann",
     "vehicleType":"VAN",
     "shifts":[
       {"id":"Ann-1","startLocation":[49.288087,16.562172],"minStartTime":"2024-03-21T08:00:00", "maxEndTime": "2024-03-21T20:00:00", "maxSoftEndTime": "2024-03-21T18:00:00", "maxLastVisitDepartureTime": "2024-03-21T19:00:00", "maxSoftLastVisitDepartureTime": "2024-03-21T17:00:00", ...},
       {"id":"Ann-2","startLocation":[49.288087,16.562172],"minFirstVisitArrivalTime":"2024-03-22T08:00:00", ...},
       ...
     ]
    },
  ],
}

VehicleRoutePlan statistics moved under VehicleRoutePlan.statistics

The following VehicleRoutePlan properties have been moved under VehicleRoutePlan.statistics:

  • totalTravelTime

  • totalTravelDistanceMeters

  • totalUnassignedVisits

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

If you send any of the 3 properties (totalTravelTime, totalTravelDistanceMeters, totalUnassignedVisits) in the requests (which is redundant and will not work in a future version), the following endpoints are affected as well:

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/

  • POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-group-recommend-time-windows

Before:

{
  "totalTravelTime": "PT3H",
  "totalTravelDistanceMeters": 3000,
  "totalUnassignedVisits": 0,
  ...
}

After:

{
  "statistics": {
    "totalTravelTime": "PT3H",
    "travelTimeFromStartLocationToFirstVisit": "PT1H",
    "travelTimeBetweenVisits": "PT1H",
    "travelTimeFromLastVisitToEndLocation": "PT1H",
    "totalTravelDistanceMeters": 3000,
    "travelDistanceFromStartLocationToFirstVisitMeters": 1000,
    "travelDistanceBetweenVisitsMeters": 1000,
    "travelDistanceFromLastVisitToEndLocationMeters": 1000,
    "totalUnassignedVisits": 0
  },
  ...
}

Visit supports multiple time windows

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/

  • POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/{id}/recommendations/visit-group-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-recommend-time-windows

  • POST /v1/route-plans/recommendations/visit-group-recommend-time-windows

The Visit attributes minimumStartTime, maximumStartTime and maximumEndTime have been replaced by Visit.timeWindows array of JSON objects with minStartTime, maxStartTime and maxEndTime attributes.

The Visit attribute minimumStartTravelTime has been renamed to minStartTravelTime.

Please note that visit’s time windows must not overlap. See Visit Time Window for additional details.

Before:

{
  "visits": [
    {"id":"1","name":"A single-resource visit","location":[33.67749834423416,-84.32354038529364],"minimumStartTime":"2024-02-23T08:00:00","maximumEndTime":"2024-02-23T18:00:00","minimumStartTravelTime":"2024-02-23T08:00:00","serviceDuration":"PT1H30M","requiredTags":["electrician","north"],"priority":"NORMAL", ...},
    ...
  ],
  "visitGroups": [
    {"id":"VG Ivy Fox 1",
     "serviceDurationStrategy": "INDIVIDUAL",
     "visits": [
            {"id":"2a","name":"Ivy Fox (1/2)","location":[33.67749834423416,-84.32354038529364],"minimumStartTime":"2024-02-23T08:00:00","maximumStartTime":"2024-02-23T09:00:00","maximumEndTime":"2024-02-23T12:00:00","serviceDuration":"PT1H30M","requiredTags":["electrician","north"],"priority":"NORMAL", ...},
             ...
        ]
    }
    ...
  ],
  ...
}

After:

{
  "visits": [
    {"id":"1","name":"A single-resource visit","location":[33.67749834423416,-84.32354038529364], "timeWindows": [{ "minStartTime":"2024-02-23T08:00:00","maxEndTime":"2024-02-23T18:00:00"}],"minStartTravelTime":"2024-02-23T08:00:00","serviceDuration":"PT1H30M","requiredTags":["electrician","north"],"priority":"NORMAL", ...},
    ...
  ],
  "visitGroups": [
    {"id":"VG Ivy Fox 1",
     "serviceDurationStrategy": "INDIVIDUAL",
     "visits": [
            {"id":"2a","name":"Ivy Fox (1/2)","location":[33.67749834423416,-84.32354038529364], "timeWindows": [{"minStartTime":"2024-02-23T08:00:00","maxStartTime":"2024-02-23T09:00:00","maxEndTime":"2024-02-23T12:00:00"}],"serviceDuration":"PT1H30M","requiredTags":["electrician","north"],"priority":"NORMAL", ...},
             ...
        ]
    }
    ...
  ],
  ...
}

From 0.12.0 to 0.13.0

The version 0.13.0 introduces changes to the API. The changes are not backward compatible and require changes to the client code.

Recommend time windows endpoint changes its URL

Affects the following REST endpoints:

  • POST /v1/route-plans/{id}/recommendations/recommend-time-windows

Before:

POST /v1/route-plans/{id}/recommendations/recommend-time-windows

After:

POST /v1/route-plans/{id}/recommendations/visit-recommend-time-windows

From 0.11.0 to 0.12.0

The version 0.12.0 does not introduce any breaking changes to the API requiring migration.

From 0.10.0 to 0.11.0

The version 0.11.0 introduces changes to the API. The changes are not backward compatible and require changes to the client code.

Visits belonging to a visit group moved under VehicleRoutePlan.visitGroups

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/{id}/recommendations/recommend-time-windows

The visits which are members of a visit group have been moved from VehicleRoutePlan.visits under individual visit groups at VehicleRoutePlan.visitGroups. Other (non-multi-vehicle) visits remain at VehicleRoutePlan.visits.

Before:

{
  "visits": [
    {"id":"1","name":"A single-resource visit","location":[33.67749834423416,-84.32354038529364],"minimumStartTime":"2024-02-23T08:00:00","maximumEndTime":"2024-02-23T18:00:00","serviceDuration":"PT1H30M","requiredTags":["electrician","north"],"priority":"NORMAL", ...},
    {"id":"2a","name":"Ivy Fox (1/2)","location":[33.67749834423416,-84.32354038529364],"minimumStartTime":"2024-02-23T08:00:00","maximumEndTime":"2024-02-23T18:00:00","serviceDuration":"PT1H30M","requiredTags":["electrician","north"],"priority":"NORMAL", "visitGroup": "VG Ivy Fox 1", ...},
    {"id":"2b","name":"Ivy Fox (2/2)","location":[33.67749834423416,-84.32354038529364],"minimumStartTime":"2024-02-23T08:00:00","maximumEndTime":"2024-02-23T18:00:00","serviceDuration":"PT1H","requiredTags":["electrician","north"],"priority":"NORMAL", "visitGroup": "VG Ivy Fox 1", ...},
    ...
  ],
  ...
}

After:

{
  "visits": [
    {"id":"1","name":"A single-resource visit","location":[33.67749834423416,-84.32354038529364],"minimumStartTime":"2024-02-23T08:00:00","maximumEndTime":"2024-02-23T18:00:00","serviceDuration":"PT1H30M","requiredTags":["electrician","north"],"priority":"NORMAL", ...},
    ...
  ],
  "visitGroups": [
    {"id":"VG Ivy Fox 1",
     "serviceDurationStrategy": "INDIVIDUAL",
     "visits": [
            {"id":"2a","name":"Ivy Fox (1/2)","location":[33.67749834423416,-84.32354038529364],"minimumStartTime":"2024-02-23T08:00:00","maximumEndTime":"2024-02-23T18:00:00","serviceDuration":"PT1H30M","requiredTags":["electrician","north"],"priority":"NORMAL", ...},
            {"id":"2b","name":"Ivy Fox (2/2)","location":[33.67749834423416,-84.32354038529364],"minimumStartTime":"2024-02-23T08:00:00","maximumEndTime":"2024-02-23T18:00:00","serviceDuration":"PT1H","requiredTags":["electrician","north"],"priority":"NORMAL", ...}
        ]
    }
    ...
  ],
  ...
}

From 0.9.0 to 0.10.0

The version 0.10.0 introduces changes to the API. The changes are not backward compatible and require changes to the client code.

totalDrivingTime changes to totalTravelTime

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/{id}/recommendations/recommend-time-windows

Before:

{
  "totalDrivingTime": "PT1H",
  ...
}

After:

{
  "totalTravelTime": "PT1H",
  ...
}

VehicleShift startDateTime changes to shiftStartTime

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • POST /v1/route-plans

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/{id}/recommendations/recommend-time-windows

Before:

"vehicleShifts": [
  {
    "startDateTime": "2019-01-01T00:00:00",
    ...
  }
]

After:

"vehicleShifts": [
  {
    "shiftStartTime": "2019-01-01T00:00:00",
    ...
  }
]

VehicleShift totalDrivingTime and endLocationArrivalTime change to statistics.totalTravelTime and statistics.endLocationArrivalTime

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/{id}/recommendations/recommend-time-windows

Before:

"vehicleShifts": [
  {
    "totalDrivingTime": "PT1H",
    "endLocationArrivalTime": "2019-01-01T00:00:00",
    ...
  }
]

After:

"vehicleShifts": [
  {
    "statistics": {
      "totalTravelTime": "PT1H",
      "endLocationArrivalTime": "2019-01-01T00:00:00",
      ...
    }
  }
]

Visit drivingTimeFromPreviousStandstill changes to travelTimeFromPreviousStandstill

Affects the following REST endpoints:

  • GET /v1/route-plans/{id}

  • DELETE /v1/route-plans/{id}

  • POST /v1/route-plans/{id}/recommendations/recommend-time-windows

Before:

"visits": [
  {
    "drivingTimeFromPreviousStandstill": "PT1H",
    ...
  }
]

After:

"visits": [
  {
    "travelTimeFromPreviousStandstill": "PT1H",
    ...
  }
]
  • © 2025 Timefold BV
  • Timefold.ai
  • Documentation
  • Changelog
  • Send feedback
  • Privacy
  • Legal
    • Light mode
    • Dark mode
    • System default