Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
    • Pick-up and Delivery Routing
  • Platform
Try models
  • Pick-up and Delivery Routing
  • Job service constraints
  • Job requirements and tags
  • Job required drivers

Pick-up and Delivery Routing

    • Introduction
    • Getting started: Hello world
    • User guide
      • Terms
      • Planning AI concepts
      • Demo datasets
      • Validation
      • Routing with Timefold’s maps service
      • Metrics and optimization goals
    • Driver resource constraints
      • Lunch breaks and personal appointments
      • Route optimization
      • Shift hours and overtime
    • Job service constraints
      • Time windows and opening hours
      • Skills
      • Movable stops and multi-day schedules
      • Dependencies between stops
      • Priority stops and optional stops
      • Job requirements and tags
        • Job required drivers
        • Job pooling
        • Prohibit job combinations
        • Maximum time burden
        • Driver capacity
        • Tags
    • Changelog
    • Upgrading to the latest versions
    • Feature requests

Job required drivers

Jobs can have requirements for which drivers are assigned.

Required drivers.

Jobs can require specific drivers. If one of the required drivers is available, they will be assigned to the job. If none of the specified drivers can be assigned, the job will remain unassigned.

Preferred drivers.

Jobs can prefer specific drivers. If possible preferred drivers will be assigned to the job. However, if none of the preferred drivers are available, the job can still be assigned to another driver.

Prohibited drivers.

Jobs can prohibit specific drivers. Prohibited drivers will not be assigned to the job. If there are no other available drivers the job will remain unassigned.

This guide explains job requirements with the following examples:

  • Required drivers

  • Preferred drivers

  • Prohibited drivers

Prerequisites

Learn how to configure an API Key to run the examples in this guide:
  1. Log in to Timefold Platform: app.timefold.ai

  2. From the Dashboard, click your tenant, and from the drop-down menu select Tenant Settings, then choose API Keys.

  3. Create a new API key or use an existing one. Ensure the list of models for the API key contains the Pick-up and Delivery Routing model.

In the examples, replace <API_KEY> with the API Key you just copied.

1. Required drivers

When a job must be assigned to specific drivers, for instance, Ann or Carl, add a requiredDrivers array to the job with the drivers listed:

{
  "jobs": [
    {
      "id": "Job A",
      "requiredDrivers": ["Ann", "Carl"],
      "stops": [
        {
          "id": "A1",
          "location": [33.78592, -84.46136],
          "duration": "PT20M"
        },
        {
          "id": "A2",
          "location": [33.72757, -83.96354],
          "duration": "PT20M",
          "stopDependencies": [
            {
              "id": "jobA_dep1",
              "precedingStop": "A1"
            }
          ]
        }
      ]
    }
  ]
}

If the requiredDrivers array is empty or not specified, the visit can be assigned to any driver.

The Match required drivers hard constraint penalizes solutions with a hard score if they assign drivers who are not a required driver.

Stops will be left unassigned if a required driver cannot be assigned.

In the following example, Job A requires either Ann or Carl as the driver.

Ann is assigned to the job.

Ann and Carl both have the same start location and no other assigned jobs, so there is no advantage to assigning Ann instead of Carl or Carl instead of Ann, however, in other circumstances, other constraints might result in an optimization gain by assigning Ann or Carl.

required driver
  • Input

  • Output

Try this example in Timefold Platform by saving the JSON into a file called required-vehicles-example-1.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": "Required driver example"
    }
  },
  "modelInput": {
    "drivers": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      },
      {
        "id": "Beth",
        "shifts": [
          {
            "id": "Beth Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      },
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      }
    ],
    "jobs": [
      {
        "id": "Job A",
        "requiredDrivers": ["Ann", "Carl"],
        "stops": [
          {
            "id": "A1",
            "location": [33.78592, -84.46136],
            "duration": "PT20M"
          },
          {
            "id": "A2",
            "location": [33.72757, -83.96354],
            "duration": "PT20M",
            "stopDependencies": [
              {
                "id": "jobA_dep1",
                "precedingStop": "A1"
              }
            ]
          }
        ]
      }
    ]
  }
}
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",
    "parentId": null,
    "originId": "ID",
    "name": "Required driver example",
    "submitDateTime": "2025-08-08T05:07:58.914167538Z",
    "startDateTime": "2025-08-08T05:08:04.239962706Z",
    "activeDateTime": "2025-08-08T05:08:04.804530119Z",
    "completeDateTime": "2025-08-08T05:13:05.066122557Z",
    "shutdownDateTime": "2025-08-08T05:13:05.513135356Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-6852soft",
    "tags": [
      "system.type:from-request",
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "drivers": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "A1",
                "arrivalTime": "2027-02-01T09:31:38Z",
                "startServiceTime": "2027-02-01T09:31:38Z",
                "departureTime": "2027-02-01T09:51:38Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT31M38S",
                "travelDistanceMetersFromPreviousStandstill": 33381
              },
              {
                "id": "A2",
                "arrivalTime": "2027-02-01T10:45:22Z",
                "startServiceTime": "2027-02-01T10:45:22Z",
                "departureTime": "2027-02-01T11:05:22Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT53M44S",
                "travelDistanceMetersFromPreviousStandstill": 62124
              }
            ],
            "metrics": {
              "totalTravelTime": "PT1H54M12S",
              "travelTimeFromStartLocationToFirstStop": "PT31M38S",
              "travelTimeBetweenStops": "PT53M44S",
              "travelTimeFromLastStopToEndLocation": "PT28M50S",
              "totalTravelDistanceMeters": 127024,
              "travelDistanceFromStartLocationToFirstStopMeters": 33381,
              "travelDistanceBetweenStopsMeters": 62124,
              "travelDistanceFromLastStopToEndLocationMeters": 31519,
              "endLocationArrivalTime": "2027-02-01T11:34:12Z",
              "overtime": "PT0S"
            }
          }
        ]
      },
      {
        "id": "Beth",
        "shifts": [
          {
            "id": "Beth Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [],
            "metrics": {
              "totalTravelTime": "PT0S",
              "travelTimeFromStartLocationToFirstStop": "PT0S",
              "travelTimeBetweenStops": "PT0S",
              "travelTimeFromLastStopToEndLocation": "PT0S",
              "totalTravelDistanceMeters": 0,
              "travelDistanceFromStartLocationToFirstStopMeters": 0,
              "travelDistanceBetweenStopsMeters": 0,
              "travelDistanceFromLastStopToEndLocationMeters": 0,
              "overtime": "PT0S"
            }
          }
        ]
      },
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [],
            "metrics": {
              "totalTravelTime": "PT0S",
              "travelTimeFromStartLocationToFirstStop": "PT0S",
              "travelTimeBetweenStops": "PT0S",
              "travelTimeFromLastStopToEndLocation": "PT0S",
              "totalTravelDistanceMeters": 0,
              "travelDistanceFromStartLocationToFirstStopMeters": 0,
              "travelDistanceBetweenStopsMeters": 0,
              "travelDistanceFromLastStopToEndLocationMeters": 0,
              "overtime": "PT0S"
            }
          }
        ]
      }
    ]
  },
  "inputMetrics": {
    "stops": 2,
    "drivers": 3,
    "driverShifts": 3
  },
  "kpis": {
    "totalTravelTime": "PT1H54M12S",
    "travelTimeFromStartLocationToFirstStop": "PT31M38S",
    "travelTimeBetweenStops": "PT53M44S",
    "travelTimeFromLastStopToEndLocation": "PT28M50S",
    "totalTravelDistanceMeters": 127024,
    "travelDistanceFromStartLocationToFirstStopMeters": 33381,
    "travelDistanceBetweenStopsMeters": 62124,
    "travelDistanceFromLastStopToEndLocationMeters": 31519,
    "totalUnassignedStops": 0,
    "totalAssignedStops": 2,
    "totalActivatedDrivers": 1,
    "totalOvertime": "PT0S"
  }
}

2. Preferred drivers

When a job prefers specific drivers, for instance, Beth or Carl, add a preferredDrivers array to the job with the drivers listed:

{
  "jobs": [
    {
      "id": "Job B",
      "preferredDrivers": ["Beth", "Carl"],
      "stops": [
        {
          "id": "B1",
          "location": [33.78592, -84.46136],
          "duration": "PT20M"
        },
        {
          "id": "B2",
          "location": [33.72757, -83.96354],
          "duration": "PT20M",
          "stopDependencies": [
            {
              "id": "jobB_dep1",
              "precedingStop": "B1"
            }
          ]
        }
      ]
    }
  ]
}

If the preferredDrivers array is empty or not specified, the visit can be assigned to any driver.

The Match job preferred drivers soft constraint penalizes solutions with a soft score if they assign drivers who match the preferred drivers, incentivizing Timefold to assign preferred drivers when possible.

Stops will still be assigned if the preferred drivers cannot be assigned but other drivers are available.

In the following example, Job B prefers either Beth or Carl as the driver.

Beth is assigned to the job.

If neither Beth or Carl were available to be assigned, the stops in Job B would be assigned to Ann.

preferred driver
  • Input

  • Output

Try this example in Timefold Platform by saving the JSON into a file called required-vehicles-example-1.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": "Preferred driver example"
    }
  },
  "modelInput": {
    "drivers": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      },
      {
        "id": "Beth",
        "shifts": [
          {
            "id": "Beth Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      },
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      }
    ],
    "jobs": [
      {
        "id": "Job B",
        "preferredDrivers": ["Beth", "Carl"],
        "stops": [
          {
            "id": "B1",
            "location": [33.78592, -84.46136],
            "duration": "PT20M"
          },
          {
            "id": "B2",
            "location": [33.72757, -83.96354],
            "duration": "PT20M",
            "stopDependencies": [
              {
                "id": "jobB_dep1",
                "precedingStop": "B1"
              }
            ]
          }
        ]
      }
    ]
  }
}
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",
    "parentId": null,
    "originId": "ID",
    "name": "Preferred driver example",
    "submitDateTime": "2025-08-08T06:25:45.024332819Z",
    "startDateTime": "2025-08-08T06:25:50.468850311Z",
    "activeDateTime": "2025-08-08T06:25:51.000946136Z",
    "completeDateTime": "2025-08-08T06:30:51.329363977Z",
    "shutdownDateTime": "2025-08-08T06:30:51.746368307Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-6852soft",
    "tags": [
      "system.type:from-request",
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "drivers": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [],
            "metrics": {
              "totalTravelTime": "PT0S",
              "travelTimeFromStartLocationToFirstStop": "PT0S",
              "travelTimeBetweenStops": "PT0S",
              "travelTimeFromLastStopToEndLocation": "PT0S",
              "totalTravelDistanceMeters": 0,
              "travelDistanceFromStartLocationToFirstStopMeters": 0,
              "travelDistanceBetweenStopsMeters": 0,
              "travelDistanceFromLastStopToEndLocationMeters": 0,
              "overtime": "PT0S"
            }
          }
        ]
      },
      {
        "id": "Beth",
        "shifts": [
          {
            "id": "Beth Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "B1",
                "arrivalTime": "2027-02-01T09:31:38Z",
                "startServiceTime": "2027-02-01T09:31:38Z",
                "departureTime": "2027-02-01T09:51:38Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT31M38S",
                "travelDistanceMetersFromPreviousStandstill": 33381
              },
              {
                "id": "B2",
                "arrivalTime": "2027-02-01T10:45:22Z",
                "startServiceTime": "2027-02-01T10:45:22Z",
                "departureTime": "2027-02-01T11:05:22Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT53M44S",
                "travelDistanceMetersFromPreviousStandstill": 62124
              }
            ],
            "metrics": {
              "totalTravelTime": "PT1H54M12S",
              "travelTimeFromStartLocationToFirstStop": "PT31M38S",
              "travelTimeBetweenStops": "PT53M44S",
              "travelTimeFromLastStopToEndLocation": "PT28M50S",
              "totalTravelDistanceMeters": 127024,
              "travelDistanceFromStartLocationToFirstStopMeters": 33381,
              "travelDistanceBetweenStopsMeters": 62124,
              "travelDistanceFromLastStopToEndLocationMeters": 31519,
              "endLocationArrivalTime": "2027-02-01T11:34:12Z",
              "overtime": "PT0S"
            }
          }
        ]
      },
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [],
            "metrics": {
              "totalTravelTime": "PT0S",
              "travelTimeFromStartLocationToFirstStop": "PT0S",
              "travelTimeBetweenStops": "PT0S",
              "travelTimeFromLastStopToEndLocation": "PT0S",
              "totalTravelDistanceMeters": 0,
              "travelDistanceFromStartLocationToFirstStopMeters": 0,
              "travelDistanceBetweenStopsMeters": 0,
              "travelDistanceFromLastStopToEndLocationMeters": 0,
              "overtime": "PT0S"
            }
          }
        ]
      }
    ]
  },
  "inputMetrics": {
    "stops": 2,
    "drivers": 3,
    "driverShifts": 3
  },
  "kpis": {
    "totalTravelTime": "PT1H54M12S",
    "travelTimeFromStartLocationToFirstStop": "PT31M38S",
    "travelTimeBetweenStops": "PT53M44S",
    "travelTimeFromLastStopToEndLocation": "PT28M50S",
    "totalTravelDistanceMeters": 127024,
    "travelDistanceFromStartLocationToFirstStopMeters": 33381,
    "travelDistanceBetweenStopsMeters": 62124,
    "travelDistanceFromLastStopToEndLocationMeters": 31519,
    "totalUnassignedStops": 0,
    "totalAssignedStops": 2,
    "totalActivatedDrivers": 1,
    "totalOvertime": "PT0S"
  }
}

3. Prohibited drivers

When a job must not be assigned to a specific driver (or drivers), for instance, Carl, add a prohibitedDrivers array to the job with the drivers listed:

{
  "jobs": [
    {
      "id": "Job C",
      "prohibitedDrivers": ["Carl"],
      "stops": [
        {
          "id": "C1",
          "location": [33.78592, -84.46136],
          "duration": "PT20M"
        },
        {
          "id": "C2",
          "location": [33.72757, -83.96354],
          "duration": "PT20M",
          "stopDependencies": [
            {
              "id": "jobC_dep1",
              "precedingStop": "C1"
            }
          ]
        }
      ]
    }
  ]
}

If the prohibitedDrivers array is empty or not specified, the stop can be assigned to any driver.

The Require stop driver not match prohibited drivers hard constraint penalizes solutions with a hard score if they assign drivers who match prohibited drivers.

Stops will be left unassigned if prohibited drivers are the only available drivers.

In the following example, Job C lists Carl as a prohibited driver.

Beth is assigned to the job.

If neither Beth or Ann were available to be assigned, the stops in Job C would be left unassigned.

prohibited driver
  • Input

  • Output

Try this example in Timefold Platform by saving the JSON into a file called prohibited-driver-input.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": "Prohibited driver example"
    }
  },
  "modelInput": {
    "drivers": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      },
      {
        "id": "Beth",
        "shifts": [
          {
            "id": "Beth Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      },
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startLocation": [33.68786, -84.18487],
            "endLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z"
          }
        ]
      }
    ],
    "jobs": [
      {
        "id": "Job C",
        "prohibitedDrivers": ["Carl"],
        "stops": [
          {
            "id": "C1",
            "location": [33.78592, -84.46136],
            "duration": "PT20M"
          },
          {
            "id": "C2",
            "location": [33.72757, -83.96354],
            "duration": "PT20M",
            "stopDependencies": [
              {
                "id": "jobC_dep1",
                "precedingStop": "C1"
              }
            ]
          }
        ]
      }
    ]
  }
}
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",
    "parentId": null,
    "originId": "ID",
    "name": "Prohibited driver example",
    "submitDateTime": "2025-08-08T06:57:33.932125935Z",
    "startDateTime": "2025-08-08T06:59:06.252214512Z",
    "activeDateTime": "2025-08-08T06:59:10.777229648Z",
    "completeDateTime": "2025-08-08T07:04:11.028976379Z",
    "shutdownDateTime": "2025-08-08T07:04:11.43255357Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-6852soft",
    "tags": [
      "system.type:from-request",
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "drivers": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [],
            "metrics": {
              "totalTravelTime": "PT0S",
              "travelTimeFromStartLocationToFirstStop": "PT0S",
              "travelTimeBetweenStops": "PT0S",
              "travelTimeFromLastStopToEndLocation": "PT0S",
              "totalTravelDistanceMeters": 0,
              "travelDistanceFromStartLocationToFirstStopMeters": 0,
              "travelDistanceBetweenStopsMeters": 0,
              "travelDistanceFromLastStopToEndLocationMeters": 0,
              "overtime": "PT0S"
            }
          }
        ]
      },
      {
        "id": "Beth",
        "shifts": [
          {
            "id": "Beth Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "C1",
                "arrivalTime": "2027-02-01T09:31:38Z",
                "startServiceTime": "2027-02-01T09:31:38Z",
                "departureTime": "2027-02-01T09:51:38Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT31M38S",
                "travelDistanceMetersFromPreviousStandstill": 33381
              },
              {
                "id": "C2",
                "arrivalTime": "2027-02-01T10:45:22Z",
                "startServiceTime": "2027-02-01T10:45:22Z",
                "departureTime": "2027-02-01T11:05:22Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT53M44S",
                "travelDistanceMetersFromPreviousStandstill": 62124
              }
            ],
            "metrics": {
              "totalTravelTime": "PT1H54M12S",
              "travelTimeFromStartLocationToFirstStop": "PT31M38S",
              "travelTimeBetweenStops": "PT53M44S",
              "travelTimeFromLastStopToEndLocation": "PT28M50S",
              "totalTravelDistanceMeters": 127024,
              "travelDistanceFromStartLocationToFirstStopMeters": 33381,
              "travelDistanceBetweenStopsMeters": 62124,
              "travelDistanceFromLastStopToEndLocationMeters": 31519,
              "endLocationArrivalTime": "2027-02-01T11:34:12Z",
              "overtime": "PT0S"
            }
          }
        ]
      },
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [],
            "metrics": {
              "totalTravelTime": "PT0S",
              "travelTimeFromStartLocationToFirstStop": "PT0S",
              "travelTimeBetweenStops": "PT0S",
              "travelTimeFromLastStopToEndLocation": "PT0S",
              "totalTravelDistanceMeters": 0,
              "travelDistanceFromStartLocationToFirstStopMeters": 0,
              "travelDistanceBetweenStopsMeters": 0,
              "travelDistanceFromLastStopToEndLocationMeters": 0,
              "overtime": "PT0S"
            }
          }
        ]
      }
    ]
  },
  "inputMetrics": {
    "stops": 2,
    "drivers": 3,
    "driverShifts": 3
  },
  "kpis": {
    "totalTravelTime": "PT1H54M12S",
    "travelTimeFromStartLocationToFirstStop": "PT31M38S",
    "travelTimeBetweenStops": "PT53M44S",
    "travelTimeFromLastStopToEndLocation": "PT28M50S",
    "totalTravelDistanceMeters": 127024,
    "travelDistanceFromStartLocationToFirstStopMeters": 33381,
    "travelDistanceBetweenStopsMeters": 62124,
    "travelDistanceFromLastStopToEndLocationMeters": 31519,
    "totalUnassignedStops": 0,
    "totalAssignedStops": 2,
    "totalActivatedDrivers": 1,
    "totalOvertime": "PT0S"
  }
}

Next

  • See the full API spec or try the online API.

  • © 2025 Timefold BV
  • Timefold.ai
  • Documentation
  • Changelog
  • Send feedback
  • Privacy
  • Legal
    • Light mode
    • Dark mode
    • System default