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
  • Driver capacity

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

Driver capacity

Pick-up and delivery drivers transport people, parcels, and other items between locations.

When assigning jobs to drivers, it’s important not to exceed the capacity of the driver’s vehicle.

Different vehicles have different capacities. Some vehicles are suitable for transporting passengers while other vehicles are suitable for transporting parcels or refrigerated goods.

If a driver can take up to 3 passengers, they must never been assigned a job, or combinations of jobs that require space for 4 or more passengers at the same time.

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. Define capacity

The capacity of the vehicles drivers will be driving during their shift is defined in the shift as a capacityDefinitions:

{
  "drivers": [
    {
      "id": "Ann",
      "shifts": [
        {
          "id": "Ann Mon",
          "startLocation": [33.77284, -84.42989],
          "minStartTime": "2027-02-01T09:00:00Z",
          "maxEndTime": "2027-02-01T17:00:00Z",
          "capacityDefinitions": [
            {
              "capacityName": "Passenger",
              "providedCapacity": 5
            }
          ]
        }
      ]
    }
  ]
}

capacityDefinitions must include capacityName and providedCapacity.

capacityName identifies the type of capacity. This can be any string and will be matched against the capacity requirements specified by jobs, for instance, passenger or storage.

A job will only be assigned to a driver if the type of capacity provided by the driver matches the required capacity type of the job.

providedCapacity specifies how many units can be transported together. If a job requires more capacity than a driver can provide, the job will not be assigned to the driver.

capacityDefinitions is an array and you can include multiple capacity types:

{
  "capacityDefinitions": [
  {
    "capacityName": "Dry-goods",
    "providedCapacity": 5
  },
  {
    "capacityName": "Frozen-goods",
    "providedCapacity": 5
  }
}

Stops include capacityRequirements:

{
  "stops": [
    {
      "id": "A1-pickup",
      "name": "A1-pickup",
      "location": [33.77911, -84.49644],
      "duration": "PT10M",
      "capacityRequirements": [
        {
          "capacityName": "Passenger",
          "requiredCapacity": 3,
          "freedCapacity": 0
        }
      ]
    }
  ]
}

capacityRequirements must include an capacityName, requiredCapacity, and freedCapacity.

capacityName identifies the type of capacity. This can be any string and will be matched against the provided capacity specified by drivers, for instance, passenger or storage.

requiredCapacity is the number of units of capacity the stop requires in order to be assigned. If the job is driving 1 passenger from location A to location B, the pick-up stop will have a requiredCapacity of 1.

freedCapacity is the number of units of capacity the stop frees up. If the job is driving 1 passenger from location A to location B, the delivery stop will have a freedCapacity of 1.

capacityRequirements is an array and you can include multiple capacity types:

{
  "capacityRequirements": [
    {
      "capacityName": "Dry-goods",
      "requiredCapacity": 3,
      "freedCapacity": 0
    },
    {
      "capacityName": "Frozen-goods",
      "requiredCapacity": 2,
      "freedCapacity": 0
    }
  ]
}

Beth’s vehicle can carry 5 passengers at once, and has a capacity of 5.

There are 3 jobs. Job A is for 2 passengers. Job B is for 2 passengers. Job C is for 3 passengers.

The following demonstrates how the available capacity changes as stops are completed.

Job Pick-up/Delivery Capacity +/- Available capacity

Job A

Pick-up

-2

3

Job B

Pick-up

-2

1

Job A

Delivery

2

3

Job C

Pick-up

-3

0

Job B

Delivery

2

2

Job c

Delivery

3

5

The Driver’s vehicle capacity exceeded hard constraint penalizes the solution with a hard score if the driver capacity is exceeded at a stop. The hard score penalty is based on the amount of exceeded capacity.

Stops will not be assigned if assigning them would break this constraint.

2. Driver capacity example

In the following example, Ann has a vehicle with a capacity of 5 of type passenger. There are 2 jobs, Job A and Job B. Both jobs have a required capacity of 3. Even though the jobs are close together, they cannot be completed together because doing so would exceed the vehicle’s capacity.

  • 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": "Driver capacity example"
    }
  },
  "modelInput": {
    "drivers": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startLocation": [33.77284, -84.42989],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T17:00:00Z",
            "capacityDefinitions": [
              {
                "capacityName": "Passenger",
                "providedCapacity": 5
              }
            ]
          }
        ]
      }
    ],
    "jobs": [
      {
        "id": "A",
        "stops": [
          {
            "id": "A1",
            "name": "A1",
            "location": [33.77911, -84.49644],
            "duration": "PT20M",
            "capacityRequirements": [
              {
                "capacityName": "Passenger",
                "requiredCapacity": 3,
                "freedCapacity": 0
              }
            ]
          },
          {
            "id": "A2",
            "name": "A2",
            "location": [33.65979, -84.46366],
            "duration": "PT20M",
            "stopDependencies": [
              {
                "id": "A1_dep1",
                "precedingStop": "A1"
              }
            ],
            "capacityRequirements": [
              {
                "capacityName": "Passenger",
                "requiredCapacity": 0,
                "freedCapacity": 3
              }
            ]
          }
        ]
      },
      {
        "id": "B",
        "stops": [
          {
            "id": "B1",
            "name": "B1",
            "location": [33.74648, -84.46461],
            "duration": "PT20M",
            "capacityRequirements": [
              {
                "capacityName": "Passenger",
                "requiredCapacity": 3,
                "freedCapacity": 0
              }
            ]
          },
          {
            "id": "B2",
            "name": "B2",
            "location": [33.65207, -84.46496],
            "duration": "PT20M",
            "stopDependencies": [
              {
                "id": "B1_dep1",
                "precedingStop": "B1"
              }
            ],
            "capacityRequirements": [
              {
                "capacityName": "Passenger",
                "requiredCapacity": 0,
                "freedCapacity": 3
              }
            ]
          }
        ]
      }
    ]
  }
}
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": "Driver capacity example",
    "submitDateTime": "2025-10-20T06:20:50.45608025Z",
    "startDateTime": "2025-10-20T06:21:25.090314076Z",
    "activeDateTime": "2025-10-20T06:21:25.130963949Z",
    "completeDateTime": "2025-10-20T06:21:55.781235968Z",
    "shutdownDateTime": "2025-10-20T06:21:55.781242418Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-5014soft",
    "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": "B1-pickup",
                "arrivalTime": "2027-02-01T09:09:00Z",
                "startServiceTime": "2027-02-01T09:09:00Z",
                "departureTime": "2027-02-01T09:19:00Z",
                "effectiveServiceDuration": "PT10M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT9M",
                "travelDistanceMetersFromPreviousStandstill": 5858
              },
              {
                "id": "B1-delivery",
                "arrivalTime": "2027-02-01T09:38:27Z",
                "startServiceTime": "2027-02-01T09:38:27Z",
                "departureTime": "2027-02-01T09:43:27Z",
                "effectiveServiceDuration": "PT5M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT19M27S",
                "travelDistanceMetersFromPreviousStandstill": 19008
              },
              {
                "id": "A1-pickup",
                "arrivalTime": "2027-02-01T10:01:15Z",
                "startServiceTime": "2027-02-01T10:01:15Z",
                "departureTime": "2027-02-01T10:11:15Z",
                "effectiveServiceDuration": "PT10M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT17M48S",
                "travelDistanceMetersFromPreviousStandstill": 20015
              },
              {
                "id": "A1-delivery",
                "arrivalTime": "2027-02-01T10:28:22Z",
                "startServiceTime": "2027-02-01T10:28:22Z",
                "departureTime": "2027-02-01T10:33:22Z",
                "effectiveServiceDuration": "PT5M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT17M7S",
                "travelDistanceMetersFromPreviousStandstill": 18056
              }
            ],
            "metrics": {
              "totalTravelTime": "PT1H23M34S",
              "travelTimeFromStartLocationToFirstStop": "PT9M",
              "travelTimeBetweenStops": "PT54M22S",
              "travelTimeFromLastStopToEndLocation": "PT20M12S",
              "totalTravelDistanceMeters": 79300,
              "travelDistanceFromStartLocationToFirstStopMeters": 5858,
              "travelDistanceBetweenStopsMeters": 57079,
              "travelDistanceFromLastStopToEndLocationMeters": 16363,
              "endLocationArrivalTime": "2027-02-01T10:53:34Z",
              "overtime": "PT0S"
            }
          }
        ]
      }
    ]
  },
  "inputMetrics": {
    "jobs": 2,
    "stops": 4,
    "drivers": 1,
    "driverShifts": 1
  },
  "kpis": {
    "totalTravelTime": "PT1H23M34S",
    "totalTravelDistanceMeters": 79300,
    "totalActivatedDrivers": 1,
    "totalUnassignedJobs": "0",
    "totalAssignedJobs": "2",
    "totalUnassignedStops": 0,
    "totalAssignedStops": 4,
    "totalOvertime": "PT0S",
    "travelTimeFromStartLocationToFirstStop": "PT9M",
    "travelTimeBetweenStops": "PT54M22S",
    "travelTimeFromLastStopToEndLocation": "PT20M12S",
    "travelDistanceFromStartLocationToFirstStopMeters": 5858,
    "travelDistanceBetweenStopsMeters": 57079,
    "travelDistanceFromLastStopToEndLocationMeters": 16363
  },
  "run": {
    "id": "f51e9615-3a32-4a2b-9010-87f2c5cc562d",
    "parentId": null,
    "originId": "f51e9615-3a32-4a2b-9010-87f2c5cc562d",
    "name": "Driver capacity example",
    "submitDateTime": "2025-10-20T06:20:50.45608025Z",
    "startDateTime": "2025-10-20T06:21:25.090314076Z",
    "activeDateTime": "2025-10-20T06:21:25.130963949Z",
    "completeDateTime": "2025-10-20T06:21:55.781235968Z",
    "shutdownDateTime": "2025-10-20T06:21:55.781242418Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-5014soft",
    "tags": [
      "system.type:from-request",
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  }
}

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