Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
    • Pick-up and Delivery Routing
  • Platform
Try models
  • Pick-up and Delivery Routing
  • Real-time planning
  • Real-time planning: reassignment

Pick-up and Delivery Routing

    • Introduction
    • Getting started: Hello world
    • User guide
      • Terminology
      • Use case guide
      • Planning AI concepts
      • Integration
      • Constraints
      • Understanding the API
      • Demo datasets
      • Input datasets
        • Model configuration
        • Model input
        • Planning window
      • Input validation
      • Output datasets
        • Metadata
        • Model output
        • Input metrics
        • Key performance indicators (KPIs)
      • Routing with Timefold’s maps service
      • Metrics and optimization goals
    • Driver resource constraints
      • Lunch breaks and personal appointments
      • Route optimization
      • Shift hours and overtime
      • Driver capacity
    • Job service constraints
      • Time windows and opening hours
      • Skills
      • Multi-day schedules and movable stops
      • Dependencies between stops
      • Priority jobs and optional jobs
      • Stop service level agreement (SLA)
      • Job requirements and tags
        • Job required drivers
        • Job pooling
        • Prohibit job combinations
        • Maximum time burden
        • Tags
    • Recommendations
      • Job time window recommendations
      • Stop time window recommendations
    • Real-time planning
      • Real-time planning: pinning stops
      • Real-time planning: extended stop
      • Real-time planning: reassignment
      • Real-time planning: no show
      • Real-time planning: driver ill
    • Real-time planning with patches
      • Real-time planning: pinning stops (using patches)
      • Real-time planning: extended stop (using patches)
      • Real-time planning: reassignment (using patches)
      • Real-time planning: no show (using patches)
      • Real-time planning: driver ill (using patches)
    • Changelog
    • Upgrading to the latest versions
    • Feature requests

Real-time planning: reassignment

This guide details the currently supported real-time planning features. If you are using the Patch (preview) feature, please see Real-time planning with patches

There are many situations where Real-time planning is necessary.

When a stop takes longer than expected other stops might need to be rescheduled or even assigned to another driver.

Consider the following shift schedule:

Ann has six stops scheduled for the day: Stop E, Stop C, Stop A, Stop B, Stop D and Stop F.

However, Stop C takes much longer than expected.

As a result, Stop A, Stop B, Stop D and Stop F need to be rescheduled.

This guide explains real-time planning: reassignment with the following:

  • 1. Batch schedule: reassignment
  • 2. Real-time planning update: reassignment

1. Batch schedule: reassignment

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 Manage tenant, 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.

The original schedule was generated from the following input dataset during the regular batch scheduling:

  • 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": "Original shift plan: reassignment example"
    }
  },
  "modelInput": {
    "drivers": [
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startLocation": [33.77284, -84.42989],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T13:30:00Z"
          }
        ]
      },
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startLocation": [33.79426, -84.330114],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T13:30:00Z"
          }
        ]
      }
    ],
    "jobs": [
      {
        "id": "Job 1",
        "stops": [
          {
            "id": "Stop A",
            "name": "Stop A",
            "location": [33.74648, -84.46461],
            "duration": "PT30M"
          },
          {
            "id": "Stop B",
            "name": "Stop B",
            "location": [33.65207, -84.46496],
            "duration": "PT30M"
          }
        ]
      },
      {
        "id": "Job 2",
        "stops": [
          {
            "id": "Stop C",
            "name": "Stop C",
            "location": [33.77911, -84.49644],
            "duration": "PT30M"
          },
          {
            "id": "Stop D",
            "name": "Stop D",
            "location": [33.65979, -84.46366],
            "duration": "PT30M"
          }
        ]
      },
      {
        "id": "Job 3",
        "stops": [
          {
            "id": "Stop E",
            "name": "Stop E",
            "location": [ 33.78468, -84.48469],
            "duration": "PT30M"
          },
          {
            "id": "Stop F",
            "name": "Stop F",
            "location": [ 33.67966, -84.30062 ],
            "duration": "PT30M"
          }
        ]
      },
      {
        "id": "Job 4",
        "stops": [
          {
            "id": "Stop G",
            "name": "Stop G",
            "location": [ 33.73698, -84.34712 ],
            "duration": "PT30M"
          },
          {
            "id": "Stop H",
            "name": "Stop H",
            "location": [ 33.74661, -84.47359 ],
            "duration": "PT30M"
          }
        ]
      }
    ]
  }
}
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": "Original shift plan: reassignment example",
    "submitDateTime": "2026-04-09T17:06:00.955838+02:00",
    "startDateTime": "2026-04-09T17:06:01.006547+02:00",
    "activeDateTime": "2026-04-09T17:06:01.008361+02:00",
    "completeDateTime": "2026-04-09T17:06:31.02371+02:00",
    "shutdownDateTime": "2026-04-09T17:06:31.023713+02:00",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-6136soft",
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "drivers": [
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "Stop G",
                "arrivalTime": "2027-02-01T09:10:21Z",
                "startServiceTime": "2027-02-01T09:10:21Z",
                "departureTime": "2027-02-01T09:40:21Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT10M21S",
                "travelDistanceMetersFromPreviousStandstill": 8629,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop H",
                "arrivalTime": "2027-02-01T09:54:26Z",
                "startServiceTime": "2027-02-01T09:54:26Z",
                "departureTime": "2027-02-01T10:24:26Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT14M5S",
                "travelDistanceMetersFromPreviousStandstill": 11743,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT30M25S",
              "travelTimeFromStartLocationToFirstStop": "PT10M21S",
              "travelTimeBetweenStops": "PT14M5S",
              "travelTimeFromLastStopToEndLocation": "PT5M59S",
              "totalTravelDistanceMeters": 25355,
              "travelDistanceFromStartLocationToFirstStopMeters": 8629,
              "travelDistanceBetweenStopsMeters": 11743,
              "travelDistanceFromLastStopToEndLocationMeters": 4983,
              "endLocationArrivalTime": "2027-02-01T10:30:25Z"
            }
          }
        ]
      },
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "Stop E",
                "arrivalTime": "2027-02-01T09:17:11Z",
                "startServiceTime": "2027-02-01T09:17:11Z",
                "departureTime": "2027-02-01T09:47:11Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT17M11S",
                "travelDistanceMetersFromPreviousStandstill": 14324,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop C",
                "arrivalTime": "2027-02-01T09:48:41Z",
                "startServiceTime": "2027-02-01T09:48:41Z",
                "departureTime": "2027-02-01T10:18:41Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT1M30S",
                "travelDistanceMetersFromPreviousStandstill": 1250,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop A",
                "arrivalTime": "2027-02-01T10:24:17Z",
                "startServiceTime": "2027-02-01T10:24:17Z",
                "departureTime": "2027-02-01T10:54:17Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT5M36S",
                "travelDistanceMetersFromPreviousStandstill": 4671,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop B",
                "arrivalTime": "2027-02-01T11:06:53Z",
                "startServiceTime": "2027-02-01T11:06:53Z",
                "departureTime": "2027-02-01T11:36:53Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT12M36S",
                "travelDistanceMetersFromPreviousStandstill": 10498,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop D",
                "arrivalTime": "2027-02-01T11:37:55Z",
                "startServiceTime": "2027-02-01T11:37:55Z",
                "departureTime": "2027-02-01T12:07:55Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT1M2S",
                "travelDistanceMetersFromPreviousStandstill": 867,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop F",
                "arrivalTime": "2027-02-01T12:26:13Z",
                "startServiceTime": "2027-02-01T12:26:13Z",
                "departureTime": "2027-02-01T12:56:13Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT18M18S",
                "travelDistanceMetersFromPreviousStandstill": 15249,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT1H11M51S",
              "travelTimeFromStartLocationToFirstStop": "PT17M11S",
              "travelTimeBetweenStops": "PT39M2S",
              "travelTimeFromLastStopToEndLocation": "PT15M38S",
              "totalTravelDistanceMeters": 59891,
              "travelDistanceFromStartLocationToFirstStopMeters": 14324,
              "travelDistanceBetweenStopsMeters": 32535,
              "travelDistanceFromLastStopToEndLocationMeters": 13032,
              "endLocationArrivalTime": "2027-02-01T13:11:51Z"
            }
          }
        ]
      }
    ],
    "unassignedJobs": []
  },
  "inputMetrics": {
    "jobs": 4,
    "stops": 8,
    "drivers": 2,
    "driverShifts": 2,
    "pinnedStops": 0
  },
  "kpis": {
    "totalTravelTime": "PT1H42M16S",
    "totalTravelDistanceMeters": 85246,
    "totalActivatedDrivers": 2,
    "totalUnassignedJobs": 0,
    "totalAssignedJobs": 4,
    "assignedMandatoryJobs": 4,
    "totalUnassignedStops": 0,
    "totalAssignedStops": 8,
    "assignedMandatoryStops": 8,
    "travelTimeFromStartLocationToFirstStop": "PT27M32S",
    "travelTimeBetweenStops": "PT53M7S",
    "travelTimeFromLastStopToEndLocation": "PT21M37S",
    "travelDistanceFromStartLocationToFirstStopMeters": 22953,
    "travelDistanceBetweenStopsMeters": 44278,
    "travelDistanceFromLastStopToEndLocationMeters": 18015
  }
}

modelOutput contains Carl’s shift itinerary.

2. Real-time planning update: reassignment

If the same scenario occurs, and Stop C takes much longer than expected, the input dataset needs to be modified and resubmitted.

Update the duration for Stop C from 30 minutes to 60 minutes.

Add the minStartTravelTime from the most recent planning output dataset (batch or real-time) to each stop.

{
  "jobs": [
    {
      "id": "Job 1",
      "stops": [
        {
          "id": "Stop A",
          "name": "Stop A",
          "location": [33.74648, -84.46461],
          "duration": "PT30M",
          "minStartTravelTime": "2027-02-01T00:00:00Z"
        },
        {
          "id": "Stop B",
          "name": "Stop B",
          "location": [33.65207, -84.46496],
          "duration": "PT30M",
          "minStartTravelTime": "2027-02-01T00:00:00Z"
        }
      ]
    },
    {
      "id": "Job 2",
      "stops": [
        {
          "id": "Stop C",
          "name": "Stop C",
          "location": [33.77911, -84.49644],
          "duration": "PT60M",
          "minStartTravelTime": "2027-02-01T00:00:00Z"
        },
        {
          "id": "Stop D",
          "name": "Stop D",
          "location": [33.65979, -84.46366],
          "duration": "PT30M",
          "minStartTravelTime": "2027-02-01T00:00:00Z"
        }
      ]
    },
    {
      "id": "Job 3",
      "stops": [
        {
          "id": "Stop E",
          "name": "Stop E",
          "location": [ 33.78468, -84.48469],
          "duration": "PT30M",
          "minStartTravelTime": "2027-02-01T00:00:00Z"
        },
        {
          "id": "Stop F",
          "name": "Stop F",
          "location": [ 33.67966, -84.30062 ],
          "duration": "PT30M",
          "minStartTravelTime": "2027-02-01T00:00:00Z"
        }
      ]
    },
    {
      "id": "Job 4",
      "stops": [
        {
          "id": "Stop G",
          "name": "Stop G",
          "location": [ 33.73698, -84.34712 ],
          "duration": "PT30M",
          "minStartTravelTime": "2027-02-01T00:00:00Z"
        },
        {
          "id": "Stop H",
          "name": "Stop H",
          "location": [ 33.74661, -84.47359 ],
          "duration": "PT30M",
          "minStartTravelTime": "2027-02-01T00:00:00Z"
        }
      ]
    }
  ]
}

Add the itineraries to Carl’s and Ann’s shifts, including the stop IDs and the stop kind:

{
  "drivers": [
    {
      "id": "Carl",
      "shifts": [
        {
          "id": "Carl Mon",
          "startLocation": [33.77284, -84.42989],
          "minStartTime": "2027-02-01T09:00:00Z",
          "maxEndTime": "2027-02-01T11:00:00Z",
          "itinerary":[
            {
              "id": "Stop G",
              "kind": "STOP"
            },
            {
              "id": "Stop H",
              "kind": "STOP"
            }
          ]
        }
      ]
    },
    {
      "id": "Ann",
      "shifts": [
        {
          "id": "Ann Mon",
          "startLocation": [33.79426, -84.330114],
          "minStartTime": "2027-02-01T09:00:00Z",
          "maxEndTime": "2027-02-01T13:30:00Z",
          "itinerary":[
            {
              "id": "Stop E",
              "kind": "STOP"
            },
            {
              "id": "Stop C",
              "kind": "STOP"
            },
            {
              "id": "Stop A",
              "kind": "STOP"
            },
            {
              "id": "Stop B",
              "kind": "STOP"
            },
            {
              "id": "Stop D",
              "kind": "STOP"
            },
            {
              "id": "Stop F",
              "kind": "STOP"
            }
          ]
        }
      ]
    }
  ]
}

Freeze the departure times for stops that have already occurred and that drivers have begun traveling to by adding freezeTime:

{
  "modelInput": {
    "freezeTime": "2027-02-01T10:20:00Z"
  }
}

Because Ann finished Stop C at 10:18 and is already traveling to Stop A at the freezeTime, this will keep Stop A scheduled after Stop C with a new arrival time.

Submit the updated input dataset to generate the new real-time plan.

  • 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": "Original shift plan: reassignment example"
    }
  },
  "modelInput": {
    "freezeTime": "2027-02-01T10:20:00Z",
    "drivers": [
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startLocation": [33.77284, -84.42989],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T13:30:00Z",
            "itinerary":[
              {
                "id": "Stop G",
                "kind": "STOP"
              },
              {
                "id": "Stop H",
                "kind": "STOP"
              }
            ]
          }
        ]
      },
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startLocation": [33.79426, -84.330114],
            "minStartTime": "2027-02-01T09:00:00Z",
            "maxEndTime": "2027-02-01T13:30:00Z",
            "itinerary":[
              {
                "id": "Stop E",
                "kind": "STOP"
              },
              {
                "id": "Stop C",
                "kind": "STOP"
              },
              {
                "id": "Stop A",
                "kind": "STOP"
              },
              {
                "id": "Stop B",
                "kind": "STOP"
              },
              {
                "id": "Stop D",
                "kind": "STOP"
              },
              {
                "id": "Stop F",
                "kind": "STOP"
              }
            ]
          }
        ]
      }
    ],
    "jobs": [
      {
        "id": "Job 1",
        "stops": [
          {
            "id": "Stop A",
            "name": "Stop A",
            "location": [33.74648, -84.46461],
            "duration": "PT30M"
          },
          {
            "id": "Stop B",
            "name": "Stop B",
            "location": [33.65207, -84.46496],
            "duration": "PT30M"
          }
        ]
      },
      {
        "id": "Job 2",
        "stops": [
          {
            "id": "Stop C",
            "name": "Stop C",
            "location": [33.77911, -84.49644],
            "duration": "PT60M"
          },
          {
            "id": "Stop D",
            "name": "Stop D",
            "location": [33.65979, -84.46366],
            "duration": "PT30M"
          }
        ]
      },
      {
        "id": "Job 3",
        "stops": [
          {
            "id": "Stop E",
            "name": "Stop E",
            "location": [ 33.78468, -84.48469],
            "duration": "PT30M"
          },
          {
            "id": "Stop F",
            "name": "Stop F",
            "location": [ 33.67966, -84.30062 ],
            "duration": "PT30M"
          }
        ]
      },
      {
        "id": "Job 4",
        "stops": [
          {
            "id": "Stop G",
            "name": "Stop G",
            "location": [ 33.73698, -84.34712 ],
            "duration": "PT30M"
          },
          {
            "id": "Stop H",
            "name": "Stop H",
            "location": [ 33.74661, -84.47359 ],
            "duration": "PT30M"
          }
        ]
      }
    ]
  }
}
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": "Original shift plan: reassignment example",
    "submitDateTime": "2026-04-10T17:00:10.026997+02:00",
    "startDateTime": "2026-04-10T17:00:10.071052+02:00",
    "activeDateTime": "2026-04-10T17:00:10.072466+02:00",
    "completeDateTime": "2026-04-10T17:00:40.086433+02:00",
    "shutdownDateTime": "2026-04-10T17:00:40.086435+02:00",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-7414soft",
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "drivers": [
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "Stop G",
                "arrivalTime": "2027-02-01T09:10:21Z",
                "startServiceTime": "2027-02-01T09:10:21Z",
                "departureTime": "2027-02-01T09:40:21Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT10M21S",
                "travelDistanceMetersFromPreviousStandstill": 8629,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "pinned": true,
                "kind": "STOP"
              },
              {
                "id": "Stop H",
                "arrivalTime": "2027-02-01T09:54:26Z",
                "startServiceTime": "2027-02-01T09:54:26Z",
                "departureTime": "2027-02-01T10:24:26Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT14M5S",
                "travelDistanceMetersFromPreviousStandstill": 11743,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "pinned": true,
                "kind": "STOP"
              },
              {
                "id": "Stop A",
                "arrivalTime": "2027-02-01T10:25:26Z",
                "startServiceTime": "2027-02-01T10:25:26Z",
                "departureTime": "2027-02-01T10:55:26Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT1M",
                "travelDistanceMetersFromPreviousStandstill": 830,
                "minStartTravelTime": "2027-02-01T10:20:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop B",
                "arrivalTime": "2027-02-01T11:08:02Z",
                "startServiceTime": "2027-02-01T11:08:02Z",
                "departureTime": "2027-02-01T11:38:02Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT12M36S",
                "travelDistanceMetersFromPreviousStandstill": 10498,
                "minStartTravelTime": "2027-02-01T10:20:00Z",
                "load": [],
                "kind": "STOP"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT54M37S",
              "travelTimeFromStartLocationToFirstStop": "PT10M21S",
              "travelTimeBetweenStops": "PT27M41S",
              "travelTimeFromLastStopToEndLocation": "PT16M35S",
              "totalTravelDistanceMeters": 45515,
              "travelDistanceFromStartLocationToFirstStopMeters": 8629,
              "travelDistanceBetweenStopsMeters": 23071,
              "travelDistanceFromLastStopToEndLocationMeters": 13815,
              "endLocationArrivalTime": "2027-02-01T11:54:37Z"
            }
          }
        ]
      },
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "Stop E",
                "arrivalTime": "2027-02-01T09:17:11Z",
                "startServiceTime": "2027-02-01T09:17:11Z",
                "departureTime": "2027-02-01T09:47:11Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT17M11S",
                "travelDistanceMetersFromPreviousStandstill": 14324,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "pinned": true,
                "kind": "STOP"
              },
              {
                "id": "Stop C",
                "arrivalTime": "2027-02-01T09:48:41Z",
                "startServiceTime": "2027-02-01T09:48:41Z",
                "departureTime": "2027-02-01T10:48:41Z",
                "effectiveServiceDuration": "PT1H",
                "travelTimeFromPreviousStandstill": "PT1M30S",
                "travelDistanceMetersFromPreviousStandstill": 1250,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "pinned": true,
                "kind": "STOP"
              },
              {
                "id": "Stop D",
                "arrivalTime": "2027-02-01T11:05:01Z",
                "startServiceTime": "2027-02-01T11:05:01Z",
                "departureTime": "2027-02-01T11:35:01Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT16M20S",
                "travelDistanceMetersFromPreviousStandstill": 13610,
                "minStartTravelTime": "2027-02-01T10:20:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop F",
                "arrivalTime": "2027-02-01T11:53:19Z",
                "startServiceTime": "2027-02-01T11:53:19Z",
                "departureTime": "2027-02-01T12:23:19Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT18M18S",
                "travelDistanceMetersFromPreviousStandstill": 15249,
                "minStartTravelTime": "2027-02-01T10:20:00Z",
                "load": [],
                "kind": "STOP"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT1H8M57S",
              "travelTimeFromStartLocationToFirstStop": "PT17M11S",
              "travelTimeBetweenStops": "PT36M8S",
              "travelTimeFromLastStopToEndLocation": "PT15M38S",
              "totalTravelDistanceMeters": 57465,
              "travelDistanceFromStartLocationToFirstStopMeters": 14324,
              "travelDistanceBetweenStopsMeters": 30109,
              "travelDistanceFromLastStopToEndLocationMeters": 13032,
              "endLocationArrivalTime": "2027-02-01T12:38:57Z"
            }
          }
        ]
      }
    ],
    "unassignedJobs": []
  },
  "inputMetrics": {
    "jobs": 4,
    "stops": 8,
    "drivers": 2,
    "driverShifts": 2,
    "pinnedStops": 4
  },
  "kpis": {
    "totalTravelTime": "PT2H3M34S",
    "totalTravelDistanceMeters": 102980,
    "totalActivatedDrivers": 2,
    "totalUnassignedJobs": 0,
    "totalAssignedJobs": 4,
    "assignedMandatoryJobs": 4,
    "totalUnassignedStops": 0,
    "totalAssignedStops": 8,
    "assignedMandatoryStops": 8,
    "travelTimeFromStartLocationToFirstStop": "PT27M32S",
    "travelTimeBetweenStops": "PT1H3M49S",
    "travelTimeFromLastStopToEndLocation": "PT32M13S",
    "travelDistanceFromStartLocationToFirstStopMeters": 22953,
    "travelDistanceBetweenStopsMeters": 53180,
    "travelDistanceFromLastStopToEndLocationMeters": 26847
  }
}

modelOutput contains Ann’s and Carl’s updated shift itineraries.

Stop C took much longer than expected, Stop A and Stop B have been reassigned to Carl’s shift. Stop D and Stop F are rescheduled on Ann’s shift.

Next

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

  • Learn about real-time planning.

  • Real-time planning with pinned stops.

  • Real-time planning with extended stops.

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