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:
In the examples, replace |
1. Define capacity
The capacity of the vehicles drivers will be driving during their shift is defined in the shift as a capacities:
{
"drivers": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann Mon",
"startLocation": [33.77284, -84.42989],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"capacities": [
{
"type": "Passenger",
"quantity": 5
}
]
}
]
}
]
}
capacities must include type and quantity.
type identifies the type of capacity.
This can be any string and will be matched against the demand specified by stops, for instance, passenger or storage.
A given type must be unique in the capacities array.
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’s stops.
quantity specifies how many units can be transported together.
If a job demands more capacity than a driver can provide, the job will not be assigned to the driver.
capacities is an array and can include the capacity for multiple capacity types:
{
"capacities": [
{
"type": "Dry-goods",
"quantity": 5
},
{
"type": "Frozen-goods",
"quantity": 5
}
]
}
Stops have capacity demands:
{
"stops": [
{
"id": "A1-pickup",
"name": "A1-pickup",
"location": [33.77911, -84.49644],
"duration": "PT10M",
"demands": [
{
"type": "Passenger",
"pickup": 3,
"deliver": 0
}
]
}
]
}
demands must include a type, pickup, and deliver.
type identifies the type of capacity.
This can be any string and will be matched against the capacities specified by drivers, for instance, passenger or storage.
A given type must be unique in the demands array.
pickup is the number of units of capacity the stop will pick up.
If it is necessary to drive one passenger from location A to location B, the pick-up stop will have a pickup of 1 for type passenger (and a deliver of 0).
deliver is the number of units of capacity the stop delivers.
If it is necessary to drive 1 passenger from location A to location B, the delivery stop will have a deliver of 1 for type passenger (and a pickup of 0).
demands is an array and can include the demand for multiple capacity types:
{
"demands": [
{
"type": "Dry-goods",
"pickup": 3,
"deliver": 0
},
{
"type": "Frozen-goods",
"pickup": 2,
"deliver": 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 | Demand +/- | 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.
For both jobs, 3 passengers need to be transported.
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",
"capacities": [
{
"type": "Passenger",
"quantity": 5
}
]
}
]
}
],
"jobs": [
{
"id": "A",
"stops": [
{
"id": "A1",
"name": "A1",
"location": [33.77911, -84.49644],
"duration": "PT20M",
"demands": [
{
"type": "Passenger",
"pickup": 3,
"deliver": 0
}
]
},
{
"id": "A2",
"name": "A2",
"location": [33.65979, -84.46366],
"duration": "PT20M",
"stopDependencies": [
{
"id": "A1_dep1",
"precedingStop": "A1"
}
],
"demands": [
{
"type": "Passenger",
"pickup": 0,
"deliver": 3
}
]
}
]
},
{
"id": "B",
"stops": [
{
"id": "B1",
"name": "B1",
"location": [33.74648, -84.46461],
"duration": "PT20M",
"demands": [
{
"type": "Passenger",
"pickup": 3,
"deliver": 0
}
]
},
{
"id": "B2",
"name": "B2",
"location": [33.65207, -84.46496],
"duration": "PT20M",
"stopDependencies": [
{
"id": "B1_dep1",
"precedingStop": "B1"
}
],
"demands": [
{
"type": "Passenger",
"pickup": 0,
"deliver": 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-12-10T10:59:24.550265+01:00",
"startDateTime": "2025-12-10T10:59:24.57292+01:00",
"activeDateTime": "2025-12-10T10:59:24.573942+01:00",
"completeDateTime": "2025-12-10T10:59:54.58151+01:00",
"shutdownDateTime": "2025-12-10T10:59:54.581512+01:00",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/-3871soft",
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"drivers": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann Mon",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "A1",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:07:26Z",
"startServiceTime": "2027-02-01T09:07:26Z",
"departureTime": "2027-02-01T09:27:26Z",
"effectiveServiceDuration": "PT20M",
"travelTimeFromPreviousStandstill": "PT7M26S",
"travelDistanceMetersFromPreviousStandstill": 6190,
"load": [
{
"type": "Passenger",
"previous": 0,
"current": 3
}
]
},
{
"id": "A2",
"kind": "STOP",
"arrivalTime": "2027-02-01T09:43:46Z",
"startServiceTime": "2027-02-01T09:43:46Z",
"departureTime": "2027-02-01T10:03:46Z",
"effectiveServiceDuration": "PT20M",
"travelTimeFromPreviousStandstill": "PT16M20S",
"travelDistanceMetersFromPreviousStandstill": 13610,
"load": [
{
"type": "Passenger",
"previous": 3,
"current": 0
}
]
},
{
"id": "B1",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:15:20Z",
"startServiceTime": "2027-02-01T10:15:20Z",
"departureTime": "2027-02-01T10:35:20Z",
"effectiveServiceDuration": "PT20M",
"travelTimeFromPreviousStandstill": "PT11M34S",
"travelDistanceMetersFromPreviousStandstill": 9640,
"load": [
{
"type": "Passenger",
"previous": 0,
"current": 3
}
]
},
{
"id": "B2",
"kind": "STOP",
"arrivalTime": "2027-02-01T10:47:56Z",
"startServiceTime": "2027-02-01T10:47:56Z",
"departureTime": "2027-02-01T11:07:56Z",
"effectiveServiceDuration": "PT20M",
"travelTimeFromPreviousStandstill": "PT12M36S",
"travelDistanceMetersFromPreviousStandstill": 10498,
"load": [
{
"type": "Passenger",
"previous": 3,
"current": 0
}
]
}
],
"metrics": {
"totalTravelTime": "PT1H4M31S",
"travelTimeFromStartLocationToFirstStop": "PT7M26S",
"travelTimeBetweenStops": "PT40M30S",
"travelTimeFromLastStopToEndLocation": "PT16M35S",
"totalTravelDistanceMeters": 53753,
"travelDistanceFromStartLocationToFirstStopMeters": 6190,
"travelDistanceBetweenStopsMeters": 33748,
"travelDistanceFromLastStopToEndLocationMeters": 13815,
"endLocationArrivalTime": "2027-02-01T11:24:31Z"
}
}
]
}
],
"unassignedJobs": []
},
"inputMetrics": {
"jobs": 2,
"stops": 4,
"drivers": 1,
"driverShifts": 1
},
"kpis": {
"totalTravelTime": "PT1H4M31S",
"totalTravelDistanceMeters": 53753,
"totalActivatedDrivers": 1,
"totalUnassignedJobs": 0,
"totalAssignedJobs": 2,
"assignedMandatoryJobs": 2,
"totalUnassignedStops": 0,
"totalAssignedStops": 4,
"assignedMandatoryStops": 4,
"travelTimeFromStartLocationToFirstStop": "PT7M26S",
"travelTimeBetweenStops": "PT40M30S",
"travelTimeFromLastStopToEndLocation": "PT16M35S",
"travelDistanceFromStartLocationToFirstStopMeters": 6190,
"travelDistanceBetweenStopsMeters": 33748,
"travelDistanceFromLastStopToEndLocationMeters": 13815
}
}
Next
-
See the full API spec or try the online API.