Job time window recommendations
Recommendations are a useful way of populating a draft plan.
This guide explains recommendations with the following examples:
1. Recommendations for unsolved route plans
Learn how to configure an API Key to run the examples in this guide:
In the examples, replace |
Continuous planning includes four stages:
-
Historic
The historic stage includes schedules that have already been executed and cannot be changed. -
Published
The published stage includes schedules that have been shared with your customers and drivers and should only be changed in special circumstances. -
Draft
The draft stage includes schedules that can change without impacting customers or drivers. At some point, draft schedules will be solved and moved to the published stage. -
Unplanned
The unplanned stage is too far away to start planning schedules.
When customers request work during a time period that is still in the draft phase, you can use recommendations to provide the customer with time windows to choose from. The customer’s chosen time window can be added to the draft schedule, which will be optimized before being published.
1.1. The recommendation input dataset
A recommendation input dataset includes the following:
1.1.1. Max number of recommendations per time window
The maximum number of recommendations to make per time window is specified in the input dataset.
The recommendation will consider the drivers whose shifts overlap with the specified time window and make the number of recommendations specified in maxNumberOfRecommendationsPerTimeWindow.
Each recommendation relates to a driver shift.
If there are five drivers and the maxNumberOfRecommendationsPerTimeWindow is set to 2, up to two driver shifts will be included in the recommendations per time window.
{
"maxNumberOfRecommendationsPerTimeWindow": 2
}
1.1.2. Fit job ID
The ID of the job to make the recommendations for.
The provided fitJobId must match an ID from a job in the modelInput.
{
"fitJobId": "Job A"
}
1.1.3. Time windows
The time windows to be considered for the recommendation. For instance, 09:00 to 13:00 on February 1, 2027, and 13:00 to 17:00 on February 1, 2027.
Time windows can cover an entire day or even longer, but as time windows get longer, you reduce the number of recommendations and the customer’s options.
The time windows indicate the potential periods in which the whole job needs to be scheduled, i.e. all of the stops of the job must fit within the time window.
{
"timeWindows": [
{
"startTime": "2027-02-01T09:00:00Z",
"endTime": "2027-02-01T13:00:00Z"
},
{
"startTime": "2027-02-01T13:00:00Z",
"endTime": "2027-02-01T17:00:00Z"
}
]
}
1.1.4. Model input
The model input must include the drivers and shifts and the job the recommendations are for.
To learn more about driver shifts and stops, see Shift hours and overtime.
{
"modelInput": {
"drivers": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
},
{
"id": "Beth",
"shifts": [
{
"id": "Beth-2027-02-01",
"startLocation": [33.70474, -84.06508],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
}
],
"jobs": [
{
"id": "Job A",
"stops": [
{
"id": "stop-1",
"location": [33.84475, -84.63649],
"serviceDuration": "PT10M"
},
{
"id": "stop-2",
"location": [33.57448, -84.94636],
"serviceDuration": "PT10M",
"stopDependencies": [
{
"id": "prev-stop-2",
"precedingStop": "stop-1"
}
]
}
]
}
]
}
}
1.2. Submit the input dataset
Submit the recommendations input dataset to the API endpoint: /v1/route-plans/recommendations/job-recommend-time-windows.
If you want individual constraint match justifications included in the response, you can specify an optional boolean includeJustifications query parameter:
/v1/route-plans/recommendations/job-recommend-time-windows?includeJustifications=true.
The HTTP response provides the recommendations.
-
Input
-
Output (without justifications)
-
Output (with justifications)
Try this example in Timefold Platform by saving this JSON into a file called sample.json and make the following API call:
|
To get recommendations without constraint match justifications (default):
curl -X POST -H "Content-type: application/json" -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/pickup-delivery-routing/v1/route-plans/recommendations/job-recommend-time-windows [email protected]
To get recommendations with constraint match justifications:
curl -X POST -H "Content-type: application/json" -H 'X-API-KEY: <API_KEY>' https://app.timefold.ai/api/models/pickup-delivery-routing/v1/route-plans/recommendations/job-recommend-time-windows?includeJustifications=true [email protected]
{
"maxNumberOfRecommendationsPerTimeWindow": 2,
"fitJobId": "Job A",
"timeWindows": [
{
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
{
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
],
"modelInput": {
"drivers": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startLocation": [
33.68786,
-84.18487
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
},
{
"id": "Beth",
"shifts": [
{
"id": "Beth-2027-02-01",
"startLocation": [
33.70474,
-84.06508
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
}
],
"jobs": [
{
"id": "Job A",
"stops": [
{
"id": "stop-1",
"location": [
33.84475,
-84.63649
],
"duration": "PT10M"
},
{
"id": "stop-2",
"location": [
33.57448,
-84.94636
],
"duration": "PT10M",
"stopDependencies": [
{
"id": "prev-stop-2",
"precedingStop": "stop-1"
}
]
}
]
}
]
}
}
{
"recommendations": [
{
"scoreDiff": "0hard/20000medium/-11405soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-11405soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:54:18Z",
"startServiceTime": "2027-02-01T09:54:18Z",
"departureTime": "2027-02-01T10:04:18Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:54:08Z",
"startServiceTime": "2027-02-01T10:54:08Z",
"departureTime": "2027-02-01T11:04:08Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H10M5S",
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"totalTravelDistanceMeters": 158394,
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619,
"endLocationArrivalTime": "2027-02-01T12:30:05Z"
}
},
"kpis": {
"totalTravelTime": "PT3H10M5S",
"totalTravelDistanceMeters": 158394,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619
}
},
{
"scoreDiff": "0hard/20000medium/-11405soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-11405soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:54:18Z",
"startServiceTime": "2027-02-01T13:00:00Z",
"departureTime": "2027-02-01T13:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:59:50Z",
"startServiceTime": "2027-02-01T13:59:50Z",
"departureTime": "2027-02-01T14:09:50Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H10M5S",
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"totalTravelDistanceMeters": 158394,
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619,
"endLocationArrivalTime": "2027-02-01T15:35:47Z"
}
},
"kpis": {
"totalTravelTime": "PT3H10M5S",
"totalTravelDistanceMeters": 158394,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619
}
},
{
"scoreDiff": "0hard/20000medium/-12920soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-12920soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
"driverShift": {
"id": "Beth-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:06:04Z",
"startServiceTime": "2027-02-01T10:06:04Z",
"departureTime": "2027-02-01T10:16:04Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H6M4S",
"travelDistanceMetersFromPreviousStandstill": 55061,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:05:54Z",
"startServiceTime": "2027-02-01T11:05:54Z",
"departureTime": "2027-02-01T11:15:54Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H35M20S",
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H39M26S",
"totalTravelDistanceMeters": 179450,
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 82859,
"endLocationArrivalTime": "2027-02-01T12:55:20Z"
}
},
"kpis": {
"totalTravelTime": "PT3H35M20S",
"totalTravelDistanceMeters": 179450,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H39M26S",
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 82859
}
},
{
"scoreDiff": "0hard/20000medium/-12920soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-12920soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
},
"driverShift": {
"id": "Beth-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:06:04Z",
"startServiceTime": "2027-02-01T13:00:00Z",
"departureTime": "2027-02-01T13:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H6M4S",
"travelDistanceMetersFromPreviousStandstill": 55061,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:59:50Z",
"startServiceTime": "2027-02-01T13:59:50Z",
"departureTime": "2027-02-01T14:09:50Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H35M20S",
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H39M26S",
"totalTravelDistanceMeters": 179450,
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 82859,
"endLocationArrivalTime": "2027-02-01T15:49:16Z"
}
},
"kpis": {
"totalTravelTime": "PT3H35M20S",
"totalTravelDistanceMeters": 179450,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H39M26S",
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 82859
}
}
]
}
{
"recommendations": [
{
"scoreDiff": "0hard/20000medium/-11405soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-11405soft",
"constraintName": "Minimize travel time",
"matchesDiff": [
{
"score": "0hard/0medium/-8147soft",
"justification": {
"stopId": "stop-2",
"travelTime": "PT2H15M47S",
"description": "Stop (stop-2) has travel time of 'PT2H15M47S'."
}
},
{
"score": "0hard/0medium/-3258soft",
"justification": {
"stopId": "stop-1",
"travelTime": "PT54M18S",
"description": "Stop (stop-1) has travel time of 'PT54M18S'."
}
}
],
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchesDiff": [
{
"score": "0hard/10000medium/0soft",
"justification": {
"stopId": "stop-1",
"description": "Mandatory stop (stop-1) has been left unassigned."
}
},
{
"score": "0hard/10000medium/0soft",
"justification": {
"stopId": "stop-2",
"description": "Mandatory stop (stop-2) has been left unassigned."
}
}
],
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:54:18Z",
"startServiceTime": "2027-02-01T09:54:18Z",
"departureTime": "2027-02-01T10:04:18Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:54:08Z",
"startServiceTime": "2027-02-01T10:54:08Z",
"departureTime": "2027-02-01T11:04:08Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H10M5S",
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"totalTravelDistanceMeters": 158394,
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619,
"endLocationArrivalTime": "2027-02-01T12:30:05Z"
}
},
"kpis": {
"totalTravelTime": "PT3H10M5S",
"totalTravelDistanceMeters": 158394,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619
}
},
{
"scoreDiff": "0hard/20000medium/-11405soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-11405soft",
"constraintName": "Minimize travel time",
"matchesDiff": [
{
"score": "0hard/0medium/-8147soft",
"justification": {
"stopId": "stop-2",
"travelTime": "PT2H15M47S",
"description": "Stop (stop-2) has travel time of 'PT2H15M47S'."
}
},
{
"score": "0hard/0medium/-3258soft",
"justification": {
"stopId": "stop-1",
"travelTime": "PT54M18S",
"description": "Stop (stop-1) has travel time of 'PT54M18S'."
}
}
],
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchesDiff": [
{
"score": "0hard/10000medium/0soft",
"justification": {
"stopId": "stop-1",
"description": "Mandatory stop (stop-1) has been left unassigned."
}
},
{
"score": "0hard/10000medium/0soft",
"justification": {
"stopId": "stop-2",
"description": "Mandatory stop (stop-2) has been left unassigned."
}
}
],
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:54:18Z",
"startServiceTime": "2027-02-01T13:00:00Z",
"departureTime": "2027-02-01T13:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:59:50Z",
"startServiceTime": "2027-02-01T13:59:50Z",
"departureTime": "2027-02-01T14:09:50Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H10M5S",
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"totalTravelDistanceMeters": 158394,
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619,
"endLocationArrivalTime": "2027-02-01T15:35:47Z"
}
},
"kpis": {
"totalTravelTime": "PT3H10M5S",
"totalTravelDistanceMeters": 158394,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619
}
},
{
"scoreDiff": "0hard/20000medium/-12920soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-12920soft",
"constraintName": "Minimize travel time",
"matchesDiff": [
{
"score": "0hard/0medium/-3964soft",
"justification": {
"stopId": "stop-1",
"travelTime": "PT1H6M4S",
"description": "Stop (stop-1) has travel time of 'PT1H6M4S'."
}
},
{
"score": "0hard/0medium/-8956soft",
"justification": {
"stopId": "stop-2",
"travelTime": "PT2H29M16S",
"description": "Stop (stop-2) has travel time of 'PT2H29M16S'."
}
}
],
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchesDiff": [
{
"score": "0hard/10000medium/0soft",
"justification": {
"stopId": "stop-1",
"description": "Mandatory stop (stop-1) has been left unassigned."
}
},
{
"score": "0hard/10000medium/0soft",
"justification": {
"stopId": "stop-2",
"description": "Mandatory stop (stop-2) has been left unassigned."
}
}
],
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
"driverShift": {
"id": "Beth-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:06:04Z",
"startServiceTime": "2027-02-01T10:06:04Z",
"departureTime": "2027-02-01T10:16:04Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H6M4S",
"travelDistanceMetersFromPreviousStandstill": 55061,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:05:54Z",
"startServiceTime": "2027-02-01T11:05:54Z",
"departureTime": "2027-02-01T11:15:54Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H35M20S",
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H39M26S",
"totalTravelDistanceMeters": 179450,
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 82859,
"endLocationArrivalTime": "2027-02-01T12:55:20Z"
}
},
"kpis": {
"totalTravelTime": "PT3H35M20S",
"totalTravelDistanceMeters": 179450,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H39M26S",
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 82859
}
},
{
"scoreDiff": "0hard/20000medium/-12920soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-12920soft",
"constraintName": "Minimize travel time",
"matchesDiff": [
{
"score": "0hard/0medium/-3964soft",
"justification": {
"stopId": "stop-1",
"travelTime": "PT1H6M4S",
"description": "Stop (stop-1) has travel time of 'PT1H6M4S'."
}
},
{
"score": "0hard/0medium/-8956soft",
"justification": {
"stopId": "stop-2",
"travelTime": "PT2H29M16S",
"description": "Stop (stop-2) has travel time of 'PT2H29M16S'."
}
}
],
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchesDiff": [
{
"score": "0hard/10000medium/0soft",
"justification": {
"stopId": "stop-1",
"description": "Mandatory stop (stop-1) has been left unassigned."
}
},
{
"score": "0hard/10000medium/0soft",
"justification": {
"stopId": "stop-2",
"description": "Mandatory stop (stop-2) has been left unassigned."
}
}
],
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
},
"driverShift": {
"id": "Beth-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:06:04Z",
"startServiceTime": "2027-02-01T13:00:00Z",
"departureTime": "2027-02-01T13:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H6M4S",
"travelDistanceMetersFromPreviousStandstill": 55061,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:59:50Z",
"startServiceTime": "2027-02-01T13:59:50Z",
"departureTime": "2027-02-01T14:09:50Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H35M20S",
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H39M26S",
"totalTravelDistanceMeters": 179450,
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 82859,
"endLocationArrivalTime": "2027-02-01T15:49:16Z"
}
},
"kpis": {
"totalTravelTime": "PT3H35M20S",
"totalTravelDistanceMeters": 179450,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H39M26S",
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 82859
}
}
]
}
1.3. The recommendations
In this example, there are a maximum of two recommendations per time window. Each recommendation relates to a driver shift. We have two time windows for a total of four recommendations for the job.
Each recommendation includes the following:
1.3.1. ScoreDiff
The score diff is based on the difference before the new job has been scheduled and after the new job has been scheduled.
{
"scoreDiff": "0hard/20000medium/-11405soft"
}
1.3.2. Constraint scores without justifications
The score for each constraint that has changed, for instance:
{
"score": "0hard/0medium/-11405soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
}
1.3.3. Constraint scores with justifications
The score and justification for each constraint that has changed, for instance:
{
"score": "0hard/0medium/-12920soft",
"constraintName": "Minimize travel time",
"matchesDiff": [
{
"score": "0hard/0medium/-3964soft",
"justification": {
"stopId": "stop-1",
"travelTime": "PT1H6M4S",
"description": "Stop (stop-1) has travel time of 'PT1H6M4S'."
}
},
{
"score": "0hard/0medium/-8956soft",
"justification": {
"stopId": "stop-2",
"travelTime": "PT2H29M16S",
"description": "Stop (stop-2) has travel time of 'PT2H29M16S'."
}
}
],
"matchCountDiff": 2
}
1.3.4. The time window
The time window the recommendation is for:
{
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
}
}
1.3.5. The driver shift
The driver shift the recommendation applies to and the shift itinerary, metrics, and KPIs.
{
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:54:18Z",
"startServiceTime": "2027-02-01T09:54:18Z",
"departureTime": "2027-02-01T10:04:18Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:54:08Z",
"startServiceTime": "2027-02-01T10:54:08Z",
"departureTime": "2027-02-01T11:04:08Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H10M5S",
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"totalTravelDistanceMeters": 158394,
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619,
"endLocationArrivalTime": "2027-02-01T12:30:05Z"
}
},
"kpis": {
"totalTravelTime": "PT3H10M5S",
"totalTravelDistanceMeters": 158394,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 1,
"assignedMandatoryJobs": 1,
"totalUnassignedStops": 0,
"totalAssignedStops": 2,
"assignedMandatoryStops": 2,
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT49M50S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 41530,
"travelDistanceFromLastStopToEndLocationMeters": 71619
}
}
1.4. Implementing the recommendation
The recommendation output for this example includes four recommendations:
-
Between 09:00 and 13:00 on February 1st with driver Ann.
-
Between 13:00 and 17:00 on February 1st with driver Ann.
-
Between 09:00 and 13:00 on February 1st with driver Beth.
-
Between 13:00 and 17:00 on February 1st with driver Beth.
| The recommendations include specific times, however, the plan is still a draft and those times will likely change as additional jobs are added to the plan. |
If the customer agrees to one of the time windows, it must be added to the recommendation input dataset (the draft plan).
In this instance, the customer accepted the second recommendation:
-
Between 13:00 and 17:00 on February 1st with driver Ann.
First, add the job to Ann’s itinerary:
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP"
},
{
"id": "stop-2",
"kind": "STOP"
}
]
}
]
}
Next, add the time window to the stops of the job:
{
"id": "Job A",
"stops": [
{
"id": "stop-1",
"location": [
33.84475,
-84.63649
],
"duration": "PT10M",
"timeWindows": [
{
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
},
{
"id": "stop-2",
"location": [
33.57448,
-84.94636
],
"duration": "PT10M",
"stopDependencies": [
{
"id": "prev-stop-2",
"precedingStop": "stop-1"
}
],
"timeWindows": [
{
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
}
]
}
| It is important to decide how to manage concurrent requests. If multiple requests are made for recommendations, which recommendation is added to the input dataset and what happens to other recommendations? |
2. Recommendations for unsolved route plans with existing jobs
When additional customers call to request drivers for pick-up and delivery jobs, their requests can be added to the recommendation input dataset.
In the following example, a customer has called and needs a time window for Job B:
-
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/pickup-delivery-routing/v1/route-plans/recommendations/job-recommend-time-windows [email protected]
{
"maxNumberOfRecommendationsPerTimeWindow": 2,
"fitJobId": "Job B",
"timeWindows": [
{
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
{
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
],
"modelInput": {
"drivers": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startLocation": [
33.68786,
-84.18487
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP"
},
{
"id": "stop-2",
"kind": "STOP"
}
]
}
]
},
{
"id": "Beth",
"shifts": [
{
"id": "Beth-2027-02-01",
"startLocation": [
33.70474,
-84.06508
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
}
],
"jobs": [
{
"id": "Job A",
"stops": [
{
"id": "stop-1",
"location": [
33.84475,
-84.63649
],
"duration": "PT10M"
},
{
"id": "stop-2",
"location": [
33.57448,
-84.94636
],
"duration": "PT10M",
"stopDependencies": [
{
"id": "prev-stop-2",
"precedingStop": "stop-1"
}
]
}
]
},
{
"id": "Job B",
"stops": [
{
"id": "stop-3",
"location": [
33.48574,
-84.36969
],
"duration": "PT10M"
},
{
"id": "stop-4",
"location": [
33.78463,
-84.35816
],
"duration": "PT10M",
"stopDependencies": [
{
"id": "prev-stop-4",
"precedingStop": "stop-3"
}
]
}
]
}
]
}
}
{
"recommendations": [
{
"scoreDiff": "0hard/20000medium/-2541soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-2541soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:54:18Z",
"startServiceTime": "2027-02-01T09:54:18Z",
"departureTime": "2027-02-01T10:04:18Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:54:08Z",
"startServiceTime": "2027-02-01T10:54:08Z",
"departureTime": "2027-02-01T11:04:08Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
},
{
"id": "stop-3",
"kind": "STOP",
"arrivalTime": "2027-02-01T12:09:22Z",
"startServiceTime": "2027-02-01T13:00:00Z",
"departureTime": "2027-02-01T13:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H5M14S",
"travelDistanceMetersFromPreviousStandstill": 54356,
"load": []
},
{
"id": "stop-4",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:49:54Z",
"startServiceTime": "2027-02-01T13:49:54Z",
"departureTime": "2027-02-01T13:59:54Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT39M54S",
"travelDistanceMetersFromPreviousStandstill": 33252,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT3H52M26S",
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT2H34M58S",
"travelTimeFromLastStopToEndLocation": "PT23M10S",
"totalTravelDistanceMeters": 193685,
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 129138,
"travelDistanceFromLastStopToEndLocationMeters": 19302,
"endLocationArrivalTime": "2027-02-01T14:23:04Z"
}
},
"kpis": {
"totalTravelTime": "PT3H52M26S",
"totalTravelDistanceMeters": 193685,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 2,
"assignedMandatoryJobs": 2,
"totalUnassignedStops": 0,
"totalAssignedStops": 4,
"assignedMandatoryStops": 4,
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT2H34M58S",
"travelTimeFromLastStopToEndLocation": "PT23M10S",
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 129138,
"travelDistanceFromLastStopToEndLocationMeters": 19302
}
},
{
"scoreDiff": "0hard/20000medium/-3083soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-3083soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-3",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:33:54Z",
"startServiceTime": "2027-02-01T09:33:54Z",
"departureTime": "2027-02-01T09:43:54Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT33M54S",
"travelDistanceMetersFromPreviousStandstill": 28253,
"load": []
},
{
"id": "stop-4",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:23:48Z",
"startServiceTime": "2027-02-01T10:23:48Z",
"departureTime": "2027-02-01T10:33:48Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT39M54S",
"travelDistanceMetersFromPreviousStandstill": 33252,
"load": []
},
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:05:41Z",
"startServiceTime": "2027-02-01T11:05:41Z",
"departureTime": "2027-02-01T11:15:41Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT31M53S",
"travelDistanceMetersFromPreviousStandstill": 26568,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T12:05:31Z",
"startServiceTime": "2027-02-01T12:05:31Z",
"departureTime": "2027-02-01T12:15:31Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M50S",
"travelDistanceMetersFromPreviousStandstill": 41530,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT4H1M28S",
"travelTimeFromStartLocationToFirstStop": "PT33M54S",
"travelTimeBetweenStops": "PT2H1M37S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"totalTravelDistanceMeters": 201222,
"travelDistanceFromStartLocationToFirstStopMeters": 28253,
"travelDistanceBetweenStopsMeters": 101350,
"travelDistanceFromLastStopToEndLocationMeters": 71619,
"endLocationArrivalTime": "2027-02-01T13:41:28Z"
}
},
"kpis": {
"totalTravelTime": "PT4H1M28S",
"totalTravelDistanceMeters": 201222,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 2,
"assignedMandatoryJobs": 2,
"totalUnassignedStops": 0,
"totalAssignedStops": 4,
"assignedMandatoryStops": 4,
"travelTimeFromStartLocationToFirstStop": "PT33M54S",
"travelTimeBetweenStops": "PT2H1M37S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"travelDistanceFromStartLocationToFirstStopMeters": 28253,
"travelDistanceBetweenStopsMeters": 101350,
"travelDistanceFromLastStopToEndLocationMeters": 71619
}
},
{
"scoreDiff": "0hard/20000medium/-7049soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-7049soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:54:18Z",
"startServiceTime": "2027-02-01T09:54:18Z",
"departureTime": "2027-02-01T10:04:18Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-3",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:00:38Z",
"startServiceTime": "2027-02-01T11:00:38Z",
"departureTime": "2027-02-01T11:10:38Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT56M20S",
"travelDistanceMetersFromPreviousStandstill": 46939,
"load": []
},
{
"id": "stop-4",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:50:32Z",
"startServiceTime": "2027-02-01T11:50:32Z",
"departureTime": "2027-02-01T12:00:32Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT39M54S",
"travelDistanceMetersFromPreviousStandstill": 33252,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:11:37Z",
"startServiceTime": "2027-02-01T13:11:37Z",
"departureTime": "2027-02-01T13:21:37Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H11M5S",
"travelDistanceMetersFromPreviousStandstill": 59231,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT5H7M34S",
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT2H47M19S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"totalTravelDistanceMeters": 256286,
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 139422,
"travelDistanceFromLastStopToEndLocationMeters": 71619,
"endLocationArrivalTime": "2027-02-01T14:47:34Z"
}
},
"kpis": {
"totalTravelTime": "PT5H7M34S",
"totalTravelDistanceMeters": 256286,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 2,
"assignedMandatoryJobs": 2,
"totalUnassignedStops": 0,
"totalAssignedStops": 4,
"assignedMandatoryStops": 4,
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT2H47M19S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 139422,
"travelDistanceFromLastStopToEndLocationMeters": 71619
}
},
{
"scoreDiff": "0hard/20000medium/-7049soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-7049soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:54:18Z",
"startServiceTime": "2027-02-01T09:54:18Z",
"departureTime": "2027-02-01T10:04:18Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-3",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:00:38Z",
"startServiceTime": "2027-02-01T13:00:00Z",
"departureTime": "2027-02-01T13:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT56M20S",
"travelDistanceMetersFromPreviousStandstill": 46939,
"load": []
},
{
"id": "stop-4",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:49:54Z",
"startServiceTime": "2027-02-01T13:49:54Z",
"departureTime": "2027-02-01T13:59:54Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT39M54S",
"travelDistanceMetersFromPreviousStandstill": 33252,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T15:10:59Z",
"startServiceTime": "2027-02-01T15:10:59Z",
"departureTime": "2027-02-01T15:20:59Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H11M5S",
"travelDistanceMetersFromPreviousStandstill": 59231,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT5H7M34S",
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT2H47M19S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"totalTravelDistanceMeters": 256286,
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 139422,
"travelDistanceFromLastStopToEndLocationMeters": 71619,
"endLocationArrivalTime": "2027-02-01T16:46:56Z"
}
},
"kpis": {
"totalTravelTime": "PT5H7M34S",
"totalTravelDistanceMeters": 256286,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 2,
"assignedMandatoryJobs": 2,
"totalUnassignedStops": 0,
"totalAssignedStops": 4,
"assignedMandatoryStops": 4,
"travelTimeFromStartLocationToFirstStop": "PT54M18S",
"travelTimeBetweenStops": "PT2H47M19S",
"travelTimeFromLastStopToEndLocation": "PT1H25M57S",
"travelDistanceFromStartLocationToFirstStopMeters": 45245,
"travelDistanceBetweenStopsMeters": 139422,
"travelDistanceFromLastStopToEndLocationMeters": 71619
}
}
]
}
The recommendation output for this example includes four recommendations:
-
Between 13:00 and 17:00 on February 1st with driver Ann.
-
Between 09:00 and 13:00 on February 1st with driver Ann.
-
Between 09:00 and 13:00 on February 1st with driver Ann.
-
Between 13:00 and 17:00 on February 1st with driver Ann.
3. Recommendations for solved route plans
If a customer job needs to be added to a published schedule, the process for requesting recommendations is the same as above.
The following input dataset generated the schedule that is currently being executed:
-
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/pickup-delivery-routing/v1/route-plans [email protected]
{
"config": {
"run": {
"name": "Recommendations sample schedule"
}
},
"modelInput": {
"drivers": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startLocation": [
33.68786,
-84.18487
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
},
{
"id": "Beth",
"shifts": [
{
"id": "Beth-2027-02-01",
"startLocation": [
33.70474,
-84.06508
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
}
],
"jobs": [
{
"id": "Job A",
"stops": [
{
"id": "jobA-pickup",
"name": "jobA-pickup",
"location": [
33.70701327565276,
-84.32533338611672
],
"duration": "PT10M"
},
{
"id": "jobA-delivery",
"name": "jobA-delivery",
"location": [
33.71731006962202,
-84.37791873718393
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobA-delivery_dep1",
"precedingStop": "jobA-pickup"
}
]
}
]
},
{
"id": "Job B",
"stops": [
{
"id": "jobB-pickup",
"name": "jobB-pickup",
"location": [
33.76284855890686,
-84.30035807391094
],
"duration": "PT10M"
},
{
"id": "jobB-delivery",
"name": "jobB-delivery",
"location": [
33.66913690724926,
-84.40131814080493
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobB-delivery_dep1",
"precedingStop": "jobB-pickup"
}
]
}
]
},
{
"id": "Job C",
"stops": [
{
"id": "jobC-pickup",
"name": "jobC-pickup",
"location": [
33.710952545550136,
-84.32995136580453
],
"duration": "PT10M"
},
{
"id": "jobC-delivery",
"name": "jobC-delivery",
"location": [
33.75503881265245,
-84.41532534997714
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobC-delivery_dep1",
"precedingStop": "jobC-pickup"
}
]
}
]
},
{
"id": "Job D",
"stops": [
{
"id": "jobD-pickup",
"name": "jobD-pickup",
"location": [
33.67152243761529,
-84.25467147287567
],
"duration": "PT10M"
},
{
"id": "jobD-delivery",
"name": "jobD-delivery",
"location": [
33.71070292968887,
-84.42189409559566
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobD-delivery_dep1",
"precedingStop": "jobD-pickup"
}
]
}
]
}
]
}
}
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/pickup-delivery-routing/v1/route-plans/<ID>
{
"metadata": {
"id": "ID",
"originId": "ID",
"name": "Recommendations sample schedule",
"submitDateTime": "2026-02-03T14:37:18.647402+01:00",
"startDateTime": "2026-02-03T14:37:18.717498+01:00",
"activeDateTime": "2026-02-03T14:37:18.718545+01:00",
"completeDateTime": "2026-02-03T14:37:48.737812+01:00",
"shutdownDateTime": "2026-02-03T14:37:48.737817+01:00",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/-4678soft",
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"drivers": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "jobD-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:08:03Z",
"startServiceTime": "2027-02-01T09:08:03Z",
"departureTime": "2027-02-01T09:18:03Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT8M3S",
"travelDistanceMetersFromPreviousStandstill": 6709,
"load": []
},
{
"id": "jobB-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:31:15Z",
"startServiceTime": "2027-02-01T09:31:15Z",
"departureTime": "2027-02-01T09:41:15Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT13M12S",
"travelDistanceMetersFromPreviousStandstill": 10999,
"load": []
},
{
"id": "jobA-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:49:12Z",
"startServiceTime": "2027-02-01T09:49:12Z",
"departureTime": "2027-02-01T09:59:12Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT7M57S",
"travelDistanceMetersFromPreviousStandstill": 6624,
"load": []
},
{
"id": "jobC-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:59:56Z",
"startServiceTime": "2027-02-01T09:59:56Z",
"departureTime": "2027-02-01T10:09:56Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT44S",
"travelDistanceMetersFromPreviousStandstill": 612,
"load": []
},
{
"id": "jobA-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:15:19Z",
"startServiceTime": "2027-02-01T10:15:19Z",
"departureTime": "2027-02-01T10:20:19Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT5M23S",
"travelDistanceMetersFromPreviousStandstill": 4493,
"load": []
},
{
"id": "jobC-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:26:50Z",
"startServiceTime": "2027-02-01T10:26:50Z",
"departureTime": "2027-02-01T10:31:50Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M31S",
"travelDistanceMetersFromPreviousStandstill": 5437,
"load": []
},
{
"id": "jobD-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:37:48Z",
"startServiceTime": "2027-02-01T10:37:48Z",
"departureTime": "2027-02-01T10:42:48Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT5M58S",
"travelDistanceMetersFromPreviousStandstill": 4967,
"load": []
},
{
"id": "jobB-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:48:48Z",
"startServiceTime": "2027-02-01T10:48:48Z",
"departureTime": "2027-02-01T10:53:48Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M",
"travelDistanceMetersFromPreviousStandstill": 4999,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT1H17M58S",
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT45M45S",
"travelTimeFromLastStopToEndLocation": "PT24M10S",
"totalTravelDistanceMeters": 64976,
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 38131,
"travelDistanceFromLastStopToEndLocationMeters": 20136,
"endLocationArrivalTime": "2027-02-01T11:17:58Z"
}
}
]
},
{
"id": "Beth",
"shifts": [
{
"id": "Beth-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [],
"metrics": {
"totalTravelTime": "PT0S",
"travelTimeFromStartLocationToFirstStop": "PT0S",
"travelTimeBetweenStops": "PT0S",
"travelTimeFromLastStopToEndLocation": "PT0S",
"totalTravelDistanceMeters": 0,
"travelDistanceFromStartLocationToFirstStopMeters": 0,
"travelDistanceBetweenStopsMeters": 0,
"travelDistanceFromLastStopToEndLocationMeters": 0
}
}
]
}
],
"unassignedJobs": []
},
"inputMetrics": {
"jobs": 4,
"stops": 8,
"drivers": 2,
"driverShifts": 2
},
"kpis": {
"totalTravelTime": "PT1H17M58S",
"totalTravelDistanceMeters": 64976,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 4,
"assignedMandatoryJobs": 4,
"totalUnassignedStops": 0,
"totalAssignedStops": 8,
"assignedMandatoryStops": 8,
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT45M45S",
"travelTimeFromLastStopToEndLocation": "PT24M10S",
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 38131,
"travelDistanceFromLastStopToEndLocationMeters": 20136
}
}
modelOutput contains Ann’s and Beth’s itineraries.
If a customer calls to request a driver on the same day, the following recommendations input dataset will return time window recommendations for the request (Job E):
-
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/pickup-delivery-routing/v1/route-plans/recommendations/job-recommend-time-windows [email protected]
{
"maxNumberOfRecommendationsPerTimeWindow": 2,
"fitJobId": "Job E",
"timeWindows": [
{
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
{
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
],
"modelInput": {
"drivers": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startLocation": [
33.68786,
-84.18487
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"itinerary": [
{
"id": "jobD-pickup",
"kind": "STOP"
},
{
"id": "jobB-pickup",
"kind": "STOP"
},
{
"id": "jobA-pickup",
"kind": "STOP"
},
{
"id": "jobC-pickup",
"kind": "STOP"
},
{
"id": "jobA-delivery",
"kind": "STOP"
},
{
"id": "jobC-delivery",
"kind": "STOP"
},
{
"id": "jobD-delivery",
"kind": "STOP"
},
{
"id": "jobB-delivery",
"kind": "STOP"
}
]
}
]
},
{
"id": "Beth",
"shifts": [
{
"id": "Beth-2027-02-01",
"startLocation": [
33.70474,
-84.06508
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
}
]
}
],
"jobs": [
{
"id": "Job A",
"stops": [
{
"id": "jobA-pickup",
"name": "jobA-pickup",
"location": [
33.70701327565276,
-84.32533338611672
],
"duration": "PT10M"
},
{
"id": "jobA-delivery",
"name": "jobA-delivery",
"location": [
33.71731006962202,
-84.37791873718393
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobA-delivery_dep1",
"precedingStop": "jobA-pickup"
}
]
}
]
},
{
"id": "Job B",
"stops": [
{
"id": "jobB-pickup",
"name": "jobB-pickup",
"location": [
33.76284855890686,
-84.30035807391094
],
"duration": "PT10M"
},
{
"id": "jobB-delivery",
"name": "jobB-delivery",
"location": [
33.66913690724926,
-84.40131814080493
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobB-delivery_dep1",
"precedingStop": "jobB-pickup"
}
]
}
]
},
{
"id": "Job C",
"stops": [
{
"id": "jobC-pickup",
"name": "jobC-pickup",
"location": [
33.710952545550136,
-84.32995136580453
],
"duration": "PT10M"
},
{
"id": "jobC-delivery",
"name": "jobC-delivery",
"location": [
33.75503881265245,
-84.41532534997714
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobC-delivery_dep1",
"precedingStop": "jobC-pickup"
}
]
}
]
},
{
"id": "Job D",
"stops": [
{
"id": "jobD-pickup",
"name": "jobD-pickup",
"location": [
33.67152243761529,
-84.25467147287567
],
"duration": "PT10M"
},
{
"id": "jobD-delivery",
"name": "jobD-delivery",
"location": [
33.71070292968887,
-84.42189409559566
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobD-delivery_dep1",
"precedingStop": "jobD-pickup"
}
]
}
]
},
{
"id": "Job E",
"stops": [
{
"id": "jobE-pickup",
"name": "jobE-pickup",
"location": [
33.76320212102979,
-84.44574867672038
],
"duration": "PT10M"
},
{
"id": "jobE-delivery",
"name": "jobE-delivery",
"location": [
33.68909752717026,
-84.27707020988122
],
"duration": "PT5M",
"stopDependencies": [
{
"id": "jobE-delivery_dep1",
"precedingStop": "jobE-pickup"
}
]
}
]
}
]
}
}
{
"recommendations": [
{
"scoreDiff": "0hard/20000medium/-1243soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-1243soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "jobD-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:08:03Z",
"startServiceTime": "2027-02-01T09:08:03Z",
"departureTime": "2027-02-01T09:18:03Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT8M3S",
"travelDistanceMetersFromPreviousStandstill": 6709,
"load": []
},
{
"id": "jobB-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:31:15Z",
"startServiceTime": "2027-02-01T09:31:15Z",
"departureTime": "2027-02-01T09:41:15Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT13M12S",
"travelDistanceMetersFromPreviousStandstill": 10999,
"load": []
},
{
"id": "jobA-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:49:12Z",
"startServiceTime": "2027-02-01T09:49:12Z",
"departureTime": "2027-02-01T09:59:12Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT7M57S",
"travelDistanceMetersFromPreviousStandstill": 6624,
"load": []
},
{
"id": "jobC-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:59:56Z",
"startServiceTime": "2027-02-01T09:59:56Z",
"departureTime": "2027-02-01T10:09:56Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT44S",
"travelDistanceMetersFromPreviousStandstill": 612,
"load": []
},
{
"id": "jobA-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:15:19Z",
"startServiceTime": "2027-02-01T10:15:19Z",
"departureTime": "2027-02-01T10:20:19Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT5M23S",
"travelDistanceMetersFromPreviousStandstill": 4493,
"load": []
},
{
"id": "jobC-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:26:50Z",
"startServiceTime": "2027-02-01T10:26:50Z",
"departureTime": "2027-02-01T10:31:50Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M31S",
"travelDistanceMetersFromPreviousStandstill": 5437,
"load": []
},
{
"id": "jobD-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:37:48Z",
"startServiceTime": "2027-02-01T10:37:48Z",
"departureTime": "2027-02-01T10:42:48Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT5M58S",
"travelDistanceMetersFromPreviousStandstill": 4967,
"load": []
},
{
"id": "jobB-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:48:48Z",
"startServiceTime": "2027-02-01T10:48:48Z",
"departureTime": "2027-02-01T10:53:48Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M",
"travelDistanceMetersFromPreviousStandstill": 4999,
"load": []
},
{
"id": "jobE-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:07:17Z",
"startServiceTime": "2027-02-01T11:07:17Z",
"departureTime": "2027-02-01T11:17:17Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT13M29S",
"travelDistanceMetersFromPreviousStandstill": 11238,
"load": []
},
{
"id": "jobE-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:38:27Z",
"startServiceTime": "2027-02-01T11:38:27Z",
"departureTime": "2027-02-01T11:43:27Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT21M10S",
"travelDistanceMetersFromPreviousStandstill": 17642,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT1H38M41S",
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT1H20M24S",
"travelTimeFromLastStopToEndLocation": "PT10M14S",
"totalTravelDistanceMeters": 82252,
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 67011,
"travelDistanceFromLastStopToEndLocationMeters": 8532,
"endLocationArrivalTime": "2027-02-01T11:53:41Z"
}
},
"kpis": {
"totalTravelTime": "PT1H38M41S",
"totalTravelDistanceMeters": 82252,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 5,
"assignedMandatoryJobs": 5,
"totalUnassignedStops": 0,
"totalAssignedStops": 10,
"assignedMandatoryStops": 10,
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT1H20M24S",
"travelTimeFromLastStopToEndLocation": "PT10M14S",
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 67011,
"travelDistanceFromLastStopToEndLocationMeters": 8532
}
},
{
"scoreDiff": "0hard/20000medium/-1243soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-1243soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "jobD-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:08:03Z",
"startServiceTime": "2027-02-01T09:08:03Z",
"departureTime": "2027-02-01T09:18:03Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT8M3S",
"travelDistanceMetersFromPreviousStandstill": 6709,
"load": []
},
{
"id": "jobB-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:31:15Z",
"startServiceTime": "2027-02-01T09:31:15Z",
"departureTime": "2027-02-01T09:41:15Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT13M12S",
"travelDistanceMetersFromPreviousStandstill": 10999,
"load": []
},
{
"id": "jobA-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:49:12Z",
"startServiceTime": "2027-02-01T09:49:12Z",
"departureTime": "2027-02-01T09:59:12Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT7M57S",
"travelDistanceMetersFromPreviousStandstill": 6624,
"load": []
},
{
"id": "jobC-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:59:56Z",
"startServiceTime": "2027-02-01T09:59:56Z",
"departureTime": "2027-02-01T10:09:56Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT44S",
"travelDistanceMetersFromPreviousStandstill": 612,
"load": []
},
{
"id": "jobA-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:15:19Z",
"startServiceTime": "2027-02-01T10:15:19Z",
"departureTime": "2027-02-01T10:20:19Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT5M23S",
"travelDistanceMetersFromPreviousStandstill": 4493,
"load": []
},
{
"id": "jobC-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:26:50Z",
"startServiceTime": "2027-02-01T10:26:50Z",
"departureTime": "2027-02-01T10:31:50Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M31S",
"travelDistanceMetersFromPreviousStandstill": 5437,
"load": []
},
{
"id": "jobD-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:37:48Z",
"startServiceTime": "2027-02-01T10:37:48Z",
"departureTime": "2027-02-01T10:42:48Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT5M58S",
"travelDistanceMetersFromPreviousStandstill": 4967,
"load": []
},
{
"id": "jobB-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:48:48Z",
"startServiceTime": "2027-02-01T10:48:48Z",
"departureTime": "2027-02-01T10:53:48Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M",
"travelDistanceMetersFromPreviousStandstill": 4999,
"load": []
},
{
"id": "jobE-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:07:17Z",
"startServiceTime": "2027-02-01T13:00:00Z",
"departureTime": "2027-02-01T13:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT13M29S",
"travelDistanceMetersFromPreviousStandstill": 11238,
"load": []
},
{
"id": "jobE-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:31:10Z",
"startServiceTime": "2027-02-01T13:31:10Z",
"departureTime": "2027-02-01T13:36:10Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT21M10S",
"travelDistanceMetersFromPreviousStandstill": 17642,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT1H38M41S",
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT1H20M24S",
"travelTimeFromLastStopToEndLocation": "PT10M14S",
"totalTravelDistanceMeters": 82252,
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 67011,
"travelDistanceFromLastStopToEndLocationMeters": 8532,
"endLocationArrivalTime": "2027-02-01T13:46:24Z"
}
},
"kpis": {
"totalTravelTime": "PT1H38M41S",
"totalTravelDistanceMeters": 82252,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 5,
"assignedMandatoryJobs": 5,
"totalUnassignedStops": 0,
"totalAssignedStops": 10,
"assignedMandatoryStops": 10,
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT1H20M24S",
"travelTimeFromLastStopToEndLocation": "PT10M14S",
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 67011,
"travelDistanceFromLastStopToEndLocationMeters": 8532
}
},
{
"scoreDiff": "0hard/20000medium/-2105soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-2105soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T13:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "jobD-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:08:03Z",
"startServiceTime": "2027-02-01T09:08:03Z",
"departureTime": "2027-02-01T09:18:03Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT8M3S",
"travelDistanceMetersFromPreviousStandstill": 6709,
"load": []
},
{
"id": "jobB-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:31:15Z",
"startServiceTime": "2027-02-01T09:31:15Z",
"departureTime": "2027-02-01T09:41:15Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT13M12S",
"travelDistanceMetersFromPreviousStandstill": 10999,
"load": []
},
{
"id": "jobA-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:49:12Z",
"startServiceTime": "2027-02-01T09:49:12Z",
"departureTime": "2027-02-01T09:59:12Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT7M57S",
"travelDistanceMetersFromPreviousStandstill": 6624,
"load": []
},
{
"id": "jobC-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:59:56Z",
"startServiceTime": "2027-02-01T09:59:56Z",
"departureTime": "2027-02-01T10:09:56Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT44S",
"travelDistanceMetersFromPreviousStandstill": 612,
"load": []
},
{
"id": "jobA-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:15:19Z",
"startServiceTime": "2027-02-01T10:15:19Z",
"departureTime": "2027-02-01T10:20:19Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT5M23S",
"travelDistanceMetersFromPreviousStandstill": 4493,
"load": []
},
{
"id": "jobC-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:26:50Z",
"startServiceTime": "2027-02-01T10:26:50Z",
"departureTime": "2027-02-01T10:31:50Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M31S",
"travelDistanceMetersFromPreviousStandstill": 5437,
"load": []
},
{
"id": "jobE-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:35:23Z",
"startServiceTime": "2027-02-01T10:35:23Z",
"departureTime": "2027-02-01T10:45:23Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT3M33S",
"travelDistanceMetersFromPreviousStandstill": 2955,
"load": []
},
{
"id": "jobE-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:06:33Z",
"startServiceTime": "2027-02-01T11:06:33Z",
"departureTime": "2027-02-01T11:11:33Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT21M10S",
"travelDistanceMetersFromPreviousStandstill": 17642,
"load": []
},
{
"id": "jobD-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:27:53Z",
"startServiceTime": "2027-02-01T11:27:53Z",
"departureTime": "2027-02-01T11:32:53Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT16M20S",
"travelDistanceMetersFromPreviousStandstill": 13611,
"load": []
},
{
"id": "jobB-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:38:53Z",
"startServiceTime": "2027-02-01T11:38:53Z",
"departureTime": "2027-02-01T11:43:53Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M",
"travelDistanceMetersFromPreviousStandstill": 4999,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT1H53M3S",
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT1H20M50S",
"travelTimeFromLastStopToEndLocation": "PT24M10S",
"totalTravelDistanceMeters": 94217,
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 67372,
"travelDistanceFromLastStopToEndLocationMeters": 20136,
"endLocationArrivalTime": "2027-02-01T12:08:03Z"
}
},
"kpis": {
"totalTravelTime": "PT1H53M3S",
"totalTravelDistanceMeters": 94217,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 5,
"assignedMandatoryJobs": 5,
"totalUnassignedStops": 0,
"totalAssignedStops": 10,
"assignedMandatoryStops": 10,
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT1H20M50S",
"travelTimeFromLastStopToEndLocation": "PT24M10S",
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 67372,
"travelDistanceFromLastStopToEndLocationMeters": 20136
}
},
{
"scoreDiff": "0hard/20000medium/-2105soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-2105soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"timeWindow": {
"minStartTime": "2027-02-01T13:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z"
},
"driverShift": {
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "jobD-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:08:03Z",
"startServiceTime": "2027-02-01T09:08:03Z",
"departureTime": "2027-02-01T09:18:03Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT8M3S",
"travelDistanceMetersFromPreviousStandstill": 6709,
"load": []
},
{
"id": "jobB-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:31:15Z",
"startServiceTime": "2027-02-01T09:31:15Z",
"departureTime": "2027-02-01T09:41:15Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT13M12S",
"travelDistanceMetersFromPreviousStandstill": 10999,
"load": []
},
{
"id": "jobA-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:49:12Z",
"startServiceTime": "2027-02-01T09:49:12Z",
"departureTime": "2027-02-01T09:59:12Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT7M57S",
"travelDistanceMetersFromPreviousStandstill": 6624,
"load": []
},
{
"id": "jobC-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:59:56Z",
"startServiceTime": "2027-02-01T09:59:56Z",
"departureTime": "2027-02-01T10:09:56Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT44S",
"travelDistanceMetersFromPreviousStandstill": 612,
"load": []
},
{
"id": "jobA-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:15:19Z",
"startServiceTime": "2027-02-01T10:15:19Z",
"departureTime": "2027-02-01T10:20:19Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT5M23S",
"travelDistanceMetersFromPreviousStandstill": 4493,
"load": []
},
{
"id": "jobC-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:26:50Z",
"startServiceTime": "2027-02-01T10:26:50Z",
"departureTime": "2027-02-01T10:31:50Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M31S",
"travelDistanceMetersFromPreviousStandstill": 5437,
"load": []
},
{
"id": "jobE-pickup",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:35:23Z",
"startServiceTime": "2027-02-01T13:00:00Z",
"departureTime": "2027-02-01T13:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT3M33S",
"travelDistanceMetersFromPreviousStandstill": 2955,
"load": []
},
{
"id": "jobE-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:31:10Z",
"startServiceTime": "2027-02-01T13:31:10Z",
"departureTime": "2027-02-01T13:36:10Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT21M10S",
"travelDistanceMetersFromPreviousStandstill": 17642,
"load": []
},
{
"id": "jobD-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:52:30Z",
"startServiceTime": "2027-02-01T13:52:30Z",
"departureTime": "2027-02-01T13:57:30Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT16M20S",
"travelDistanceMetersFromPreviousStandstill": 13611,
"load": []
},
{
"id": "jobB-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T14:03:30Z",
"startServiceTime": "2027-02-01T14:03:30Z",
"departureTime": "2027-02-01T14:08:30Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT6M",
"travelDistanceMetersFromPreviousStandstill": 4999,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT1H53M3S",
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT1H20M50S",
"travelTimeFromLastStopToEndLocation": "PT24M10S",
"totalTravelDistanceMeters": 94217,
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 67372,
"travelDistanceFromLastStopToEndLocationMeters": 20136,
"endLocationArrivalTime": "2027-02-01T14:32:40Z"
}
},
"kpis": {
"totalTravelTime": "PT1H53M3S",
"totalTravelDistanceMeters": 94217,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 5,
"assignedMandatoryJobs": 5,
"totalUnassignedStops": 0,
"totalAssignedStops": 10,
"assignedMandatoryStops": 10,
"travelTimeFromStartLocationToFirstStop": "PT8M3S",
"travelTimeBetweenStops": "PT1H20M50S",
"travelTimeFromLastStopToEndLocation": "PT24M10S",
"travelDistanceFromStartLocationToFirstStopMeters": 6709,
"travelDistanceBetweenStopsMeters": 67372,
"travelDistanceFromLastStopToEndLocationMeters": 20136
}
}
]
}
The recommendation output for this example includes four recommendations for Job E:
-
Between 09:00 and 13:00 on February 1st with driver Ann
-
Between 13:00 and 17:00 on February 1st with driver Ann
-
Between 09:00 and 13:00 on February 1st with driver Ann
-
Between 13:00 and 17:00 on February 1st with driver Ann
As configured with maxNumberOfRecommendationsPerTimeWindow there are two recommendations for each requested time window.
By looking at the actual routes, the differences between these recommendations become noticeable:
-
Recommendation 1
-
Recommendation 2
-
Recommendation 3
-
Recommendation 4
Route of recommendation 1 with the start service time and the stop ID:
09:08:03 jobD-pickup 09:31:15 jobB-pickup 09:49:12 jobA-pickup 09:59:56 jobC-pickup 10:15:19 jobA-delivery 10:26:50 jobC-delivery 10:37:48 jobD-delivery 10:48:48 jobB-delivery 11:07:17 jobE-pickup 11:38:27 jobE-delivery
Route of recommendation 2 with the start service time and the stop ID:
09:08:03 jobD-pickup 09:31:15 jobB-pickup 09:49:12 jobA-pickup 09:59:56 jobC-pickup 10:15:19 jobA-delivery 10:26:50 jobC-delivery 10:37:48 jobD-delivery 10:48:48 jobB-delivery 13:00:00 jobE-pickup 13:31:10 jobE-delivery
Route of recommendation 3 with the start service time and the stop ID:
09:08:03 jobD-pickup 09:31:15 jobB-pickup 09:49:12 jobA-pickup 09:59:56 jobC-pickup 10:15:19 jobA-delivery 10:26:50 jobC-delivery 10:35:23 jobE-pickup 11:06:33 jobE-delivery 11:27:53 jobD-delivery 11:38:53 jobB-delivery
Route of recommendation 4 with the start service time and the stop ID:
09:08:03 jobD-pickup 09:31:15 jobB-pickup 09:49:12 jobA-pickup 09:59:56 jobC-pickup 10:15:19 jobA-delivery 10:26:50 jobC-delivery 13:00:00 jobE-pickup 13:31:10 jobE-delivery 13:52:30 jobD-delivery 14:03:30 jobB-delivery
After the customer has accepted one of the time windows, include the job in the optimized plan for the day as shown above. Failure to update the real-time plan will lead to errors with Job E not being included if there are further updates to the plan throughout the day.
Next
-
See the full API spec or try the online API.
-
Learn about Stop time window recommendations.