Stop time window recommendations
When requesting recommendations for a pick-up and deliver job, it is sometimes required to provide more precise information about time windows for the individual stops than just one large time window for the whole job.
Recommendations for stop time windows provide a range of recommendations for a single job where one or more stops have individual time windows to consider.
This guide explains stops recommendations with the following examples:
1. Stop 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 schedules to choose from.
The customer’s chosen recommendation 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
The maximum number of recommendations to make for this request.
The recommendation will consider driver shifts that overlap with the specified stop time windows.
{
"maxNumberOfRecommendations": 2
}
1.1.2. Fit job ID
This recommendation request will try to fit the whole job with all its stops into the schedule.
Therefore, the ID of the job to make the recommendations for is part of the request.
The provided fitJobId must match an ID from a job in the modelInput.
{
"fitJobId": "Job A"
}
1.1.3. Stop time windows
While creating recommendations for the given job, these time windows for specific stops will be considered.
For every stop of a job, time windows can be provided to indicate the potential periods in which the stop can be scheduled.
For instance, 09:00 to 13:00 on February 1, 2027, and 13:00 to 17:00 on February 1, 2027.
{
"fitStops": [
{
"fitStopId": "stop-1",
"timeWindows": [
{
"minStartTime": "2027-02-01T11:00:00Z",
"maxEndTime": "2027-02-01T14: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/stops-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/stops-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/stops-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/stops-recommend-time-windows?includeJustifications=true [email protected]
{
"maxNumberOfRecommendations": 2,
"fitJobId": "Job A",
"fitStops": [
{
"fitStopId": "stop-1",
"timeWindows": [
{
"minStartTime": "2027-02-01T11:00:00Z",
"maxEndTime": "2027-02-01T14: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
}
],
"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-01T11:00:00Z",
"departureTime": "2027-02-01T11:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:59:50Z",
"startServiceTime": "2027-02-01T11:59:50Z",
"departureTime": "2027-02-01T12: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-01T13: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
}
],
"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-01T11:00:00Z",
"departureTime": "2027-02-01T11:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H6M4S",
"travelDistanceMetersFromPreviousStandstill": 55061,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:59:50Z",
"startServiceTime": "2027-02-01T11:59:50Z",
"departureTime": "2027-02-01T12: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-01T13: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
}
],
"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-01T11:00:00Z",
"departureTime": "2027-02-01T11:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:59:50Z",
"startServiceTime": "2027-02-01T11:59:50Z",
"departureTime": "2027-02-01T12: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-01T13: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
}
],
"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-01T11:00:00Z",
"departureTime": "2027-02-01T11:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H6M4S",
"travelDistanceMetersFromPreviousStandstill": 55061,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:59:50Z",
"startServiceTime": "2027-02-01T11:59:50Z",
"departureTime": "2027-02-01T12: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-01T13: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 two recommendations.
-
Assign Job A to driver Ann such that stop-1 starts at 11:00.
-
Assign Job A to driver Beth such that stop-1 starts at 11:00.
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 justifications for each constraint that has changed, for instance:
{
"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
}
1.3.4. The driver shifts
The driver shift the recommendation applies to and the shift itinerary and metrics.
{
"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-01T11:00:00Z",
"departureTime": "2027-02-01T11:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT54M18S",
"travelDistanceMetersFromPreviousStandstill": 45245,
"load": []
},
{
"id": "stop-2",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:59:50Z",
"startServiceTime": "2027-02-01T11:59:50Z",
"departureTime": "2027-02-01T12: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-01T13:35:47Z"
}
}
}
1.4. Implementing the recommendation
The recommendation output for this example includes two recommendations:
-
Assign Job A to driver Ann such that stop-1 starts at 11:00.
-
Assign Job A to driver Beth such that stop-1 starts at 11:00.
| 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 recommendations, it must be added to the recommendation input dataset (the draft plan).
In this instance, the customer accepted the second recommendation:
-
Assign Job A to driver Beth such that stop-1 starts at 11:00.
First, add the stops of Job A to Beth’s itineraries:
| Where there are multiple stops to include in the itinerary, they must be included in the order they occur in the recommendation response. |
{
"id": "Beth",
"shifts": [
{
"id": "Beth-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 matching time windows to the stops of Job A:
{
"jobs": [
{
"id": "Job A",
"stops": [
{
"id": "stop-1",
"location": [
33.84475,
-84.63649
],
"duration": "PT10M",
"timeWindows": [
{
"minStartTime": "2027-02-01T11:00:00Z",
"maxEndTime": "2027-02-01T14:00:00Z"
}
]
},
{
"id": "stop-2",
"location": [
33.57448,
-84.94636
],
"duration": "PT10M",
"stopDependencies": [
{
"id": "prev-stop-2",
"precedingStop": "stop-1"
}
],
"timeWindows": [
{
"minStartTime": "2027-02-01T11:00:00Z",
"maxEndTime": "2027-02-01T14: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. Stop recommendations for unsolved route plans with existing jobs
When additional customers call to request drivers to complete a pick-up and delivery job, their requests can be added to the recommendation input dataset.
In the following example, a customer has called and needs a driver for a pick-up and delivery job (Job B) with two stops (stop-3 and stop-4), where stop-4 has a specific time window to consider.
-
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/stops-recommend-time-windows [email protected]
{
"maxNumberOfRecommendations": 2,
"fitJobId": "Job B",
"fitStops": [
{
"fitStopId": "stop-4",
"timeWindows": [
{
"minStartTime": "2027-02-01T13:30:00Z",
"maxEndTime": "2027-02-01T15: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",
"itinerary": [
{
"id": "stop-1",
"kind": "STOP"
},
{
"id": "stop-2",
"kind": "STOP"
}
]
}
]
}
],
"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/-2395soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-2395soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"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": []
},
{
"id": "stop-3",
"kind": "STOP",
"arrivalTime": "2027-02-01T12:21:08Z",
"startServiceTime": "2027-02-01T12:21:08Z",
"departureTime": "2027-02-01T12:31:08Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT1H5M14S",
"travelDistanceMetersFromPreviousStandstill": 54356,
"load": []
},
{
"id": "stop-4",
"kind": "STOP",
"arrivalTime": "2027-02-01T13:11:02Z",
"startServiceTime": "2027-02-01T13:30:00Z",
"departureTime": "2027-02-01T13:40:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT39M54S",
"travelDistanceMetersFromPreviousStandstill": 33252,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT4H15M15S",
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT2H34M58S",
"travelTimeFromLastStopToEndLocation": "PT34M13S",
"totalTravelDistanceMeters": 212716,
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 129138,
"travelDistanceFromLastStopToEndLocationMeters": 28517,
"endLocationArrivalTime": "2027-02-01T14:14:13Z"
}
},
"kpis": {
"totalTravelTime": "PT4H15M15S",
"totalTravelDistanceMeters": 212716,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 2,
"assignedMandatoryJobs": 2,
"totalUnassignedStops": 0,
"totalAssignedStops": 4,
"assignedMandatoryStops": 4,
"travelTimeFromStartLocationToFirstStop": "PT1H6M4S",
"travelTimeBetweenStops": "PT2H34M58S",
"travelTimeFromLastStopToEndLocation": "PT34M13S",
"travelDistanceFromStartLocationToFirstStopMeters": 55061,
"travelDistanceBetweenStopsMeters": 129138,
"travelDistanceFromLastStopToEndLocationMeters": 28517
}
},
{
"scoreDiff": "0hard/20000medium/-5818soft",
"constraintDiffs": [
{
"score": "0hard/0medium/-5818soft",
"constraintName": "Minimize travel time",
"matchCountDiff": 2
},
{
"score": "0hard/20000medium/0soft",
"constraintName": "Require scheduling mandatory stops",
"matchCountDiff": -2
}
],
"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-01T13:30:00Z",
"departureTime": "2027-02-01T13:40:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT39M54S",
"travelDistanceMetersFromPreviousStandstill": 33252,
"load": []
}
],
"metrics": {
"totalTravelTime": "PT1H36M58S",
"travelTimeFromStartLocationToFirstStop": "PT33M54S",
"travelTimeBetweenStops": "PT39M54S",
"travelTimeFromLastStopToEndLocation": "PT23M10S",
"totalTravelDistanceMeters": 80807,
"travelDistanceFromStartLocationToFirstStopMeters": 28253,
"travelDistanceBetweenStopsMeters": 33252,
"travelDistanceFromLastStopToEndLocationMeters": 19302,
"endLocationArrivalTime": "2027-02-01T14:03:10Z"
}
},
"kpis": {
"totalTravelTime": "PT5H12M18S",
"totalTravelDistanceMeters": 260257,
"totalActivatedDrivers": 2,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 2,
"assignedMandatoryJobs": 2,
"totalUnassignedStops": 0,
"totalAssignedStops": 4,
"assignedMandatoryStops": 4,
"travelTimeFromStartLocationToFirstStop": "PT1H39M58S",
"travelTimeBetweenStops": "PT1H29M44S",
"travelTimeFromLastStopToEndLocation": "PT2H2M36S",
"travelDistanceFromStartLocationToFirstStopMeters": 83314,
"travelDistanceBetweenStopsMeters": 74782,
"travelDistanceFromLastStopToEndLocationMeters": 102161
}
}
]
}
The recommendation output for this example includes two recommendations:
-
Assign Job B to driver Beth such that stop-4 starts at 13:30.
-
Assign Job B to driver Ann such that stop-4 starts at 13:30.
3. Stop recommendations for published route plans
If a customer’s 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 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/stops-recommend-time-windows [email protected]
{
"maxNumberOfRecommendations": 2,
"fitJobId": "Job E",
"fitStops": [
{
"fitStopId": "jobE-pickup",
"timeWindows": [
{
"minStartTime": "2027-02-01T11:00:00Z",
"maxEndTime": "2027-02-01T14:00:00Z"
}
]
},
{
"fitStopId": "jobE-delivery",
"timeWindows": [
{
"minStartTime": "2027-02-01T15: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
}
],
"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-01T15:00:00Z",
"departureTime": "2027-02-01T15:05:00Z",
"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-01T15:15:14Z"
}
},
"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
}
],
"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-01T11:00:00Z",
"departureTime": "2027-02-01T11:10:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT3M33S",
"travelDistanceMetersFromPreviousStandstill": 2955,
"load": []
},
{
"id": "jobE-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T11:31:10Z",
"startServiceTime": "2027-02-01T15:00:00Z",
"departureTime": "2027-02-01T15:05:00Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT21M10S",
"travelDistanceMetersFromPreviousStandstill": 17642,
"load": []
},
{
"id": "jobD-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T15:21:20Z",
"startServiceTime": "2027-02-01T15:21:20Z",
"departureTime": "2027-02-01T15:26:20Z",
"effectiveServiceDuration": "PT5M",
"travelTimeFromPreviousStandstill": "PT16M20S",
"travelDistanceMetersFromPreviousStandstill": 13611,
"load": []
},
{
"id": "jobB-delivery",
"kind": "STOP",
"arrivalTime": "2027-02-01T15:32:20Z",
"startServiceTime": "2027-02-01T15:32:20Z",
"departureTime": "2027-02-01T15:37:20Z",
"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-01T16:01:30Z"
}
},
"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 two recommendations:
-
Job E is assigned to driver Ann at the end of the current schedule.
-
Job E is assigned to driver Ann, where Job E is pooled with other jobs.
After the customer has accepted a recommendation, update the dataset to include the job in the optimized plan for the day. 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 Job time window recommendations for recommendations based on time windows for the whole job.