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
  • Maximum time burden

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

Maximum time burden

In a pick-up and delivery routing, jobs are often combined to optimize the routes and use the available resources as efficiently as possible. However, this also means the time between the pick-up and the delivery for a job will increase as there are other stops in between (pick-ups and deliveries for other jobs).

This is often acceptable, but there are cases where the time between pick-up and delivery should be limited to a certain maximum, for instance, when people are being picked up and transported to their destination. The inconvenience of having a prolonged time on the vehicle should be limited to a certain maximum.

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 the maximum time burden

In order to limit the possible increase in time between pick-up and delivery, the parameter maximumTimeBurden can be added to the model configuration.

{
  "config": {
    "model": {
      "overrides": {
        "maximumTimeBurden": "PT10M"
      }
    }
  }
}

The maximumTimeBurden parameter requires a duration in ISO 8601 duration format representing the maximum allowed time burden for the jobs.

Whenever the time to service a job (measured by the time between the start of the service of the first stop and the start of the service of the last stop of the job minus direct travel time) is increased by more than the maximumTimeBurden, the solution is penalized by the Maximum time burden hard constraint.

If assigning a job would break this constraint, the job will be left unassigned.

In the following example, the maximum time burden is set to PT5M.

Although Job A and Job B share the same starting location, they are assigned sequentially as mixing them would exceed the maximum time burden of 5 minutes.

  • Input

  • Output

Try this example in Timefold Platform by saving the JSON into a file called maximum-time-burden-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": "Maximum time burden example"
    },
    "model": {
      "overrides": {
        "maximumTimeBurden": "PT5M"
      }
    }
  },
  "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"
          }
        ]
      }
    ],
    "jobs": [
      {
        "id": "Job A",
        "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"
              }
            ]
          }
        ]
      },
      {
        "id": "Job B",
        "prohibitedJobs": [],
        "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",
    "originId": "ID",
    "name": "Maximum time burden example",
    "submitDateTime": "2025-10-07T11:50:34.286702+02:00",
    "startDateTime": "2025-10-07T11:50:34.384342+02:00",
    "activeDateTime": "2025-10-07T11:50:34.384876+02:00",
    "completeDateTime": "2025-10-07T11:50:34.918612+02:00",
    "shutdownDateTime": "2025-10-07T11:50:34.9232+02:00",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-13547soft",
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "drivers": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "B1",
                "arrivalTime": "2027-02-01T09:33:21Z",
                "startServiceTime": "2027-02-01T09:33:21Z",
                "departureTime": "2027-02-01T09:53:21Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT33M21S",
                "travelDistanceMetersFromPreviousStandstill": 27795
              },
              {
                "id": "B2",
                "arrivalTime": "2027-02-01T10:49:07Z",
                "startServiceTime": "2027-02-01T10:49:07Z",
                "departureTime": "2027-02-01T11:09:07Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT55M46S",
                "travelDistanceMetersFromPreviousStandstill": 46477
              },
              {
                "id": "A1",
                "arrivalTime": "2027-02-01T12:04:53Z",
                "startServiceTime": "2027-02-01T12:04:53Z",
                "departureTime": "2027-02-01T12:24:53Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT55M46S",
                "travelDistanceMetersFromPreviousStandstill": 46477
              },
              {
                "id": "A2",
                "arrivalTime": "2027-02-01T13:20:39Z",
                "startServiceTime": "2027-02-01T13:20:39Z",
                "departureTime": "2027-02-01T13:40:39Z",
                "effectiveServiceDuration": "PT20M",
                "kind": "STOP",
                "travelTimeFromPreviousStandstill": "PT55M46S",
                "travelDistanceMetersFromPreviousStandstill": 46477
              }
            ],
            "metrics": {
              "totalTravelTime": "PT3H45M47S",
              "travelTimeFromStartLocationToFirstStop": "PT33M21S",
              "travelTimeBetweenStops": "PT2H47M18S",
              "travelTimeFromLastStopToEndLocation": "PT25M8S",
              "totalTravelDistanceMeters": 188170,
              "travelDistanceFromStartLocationToFirstStopMeters": 27795,
              "travelDistanceBetweenStopsMeters": 139431,
              "travelDistanceFromLastStopToEndLocationMeters": 20944,
              "endLocationArrivalTime": "2027-02-01T14:05:47Z",
              "overtime": "PT0S"
            }
          }
        ]
      }
    ]
  },
  "inputMetrics": {
    "stops": 4,
    "drivers": 1,
    "driverShifts": 1
  },
  "kpis": {
    "totalTravelTime": "PT3H45M47S",
    "travelTimeFromStartLocationToFirstStop": "PT33M21S",
    "travelTimeBetweenStops": "PT2H47M18S",
    "travelTimeFromLastStopToEndLocation": "PT25M8S",
    "totalTravelDistanceMeters": 188170,
    "travelDistanceFromStartLocationToFirstStopMeters": 27795,
    "travelDistanceBetweenStopsMeters": 139431,
    "travelDistanceFromLastStopToEndLocationMeters": 20944,
    "totalUnassignedStops": 0,
    "totalAssignedStops": 4,
    "totalActivatedDrivers": 1,
    "totalOvertime": "PT0S"
  },
  "run": {
    "id": "f1e18fe0-6d4b-4f7f-b579-084ca4c7de29",
    "originId": "f1e18fe0-6d4b-4f7f-b579-084ca4c7de29",
    "name": "Maximum time burden example",
    "submitDateTime": "2025-10-07T11:50:34.286702+02:00",
    "startDateTime": "2025-10-07T11:50:34.384342+02:00",
    "activeDateTime": "2025-10-07T11:50:34.384876+02:00",
    "completeDateTime": "2025-10-07T11:50:34.918612+02:00",
    "shutdownDateTime": "2025-10-07T11:50:34.9232+02:00",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-13547soft",
    "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