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 with patches
  • Real-time planning: driver ill (using patches)

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: driver ill (using patches)

This guide describes functionality that relies on the Patch feature, which is currently only available as a preview feature. If you’d like early access to this feature, please Contact us. For information about real-time planning without the Patch functionality, see Real-time planning.

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

Sometimes drivers become ill and must take the day off or, if they have already started work, go home part way through a shift.

Consider the following shift schedule:

Ann has three jobs with two stops each assigned: Stop E, Stop A, Stop F, Stop B, Stop G and Stop H. Carl has one job assigned with two stops: Stop C and Stop D.

If Ann calls in sick before the shift starts or goes home part way through the day due to illness, her stops must be reassigned to another driver or rescheduled for another day.

This guide explains real-time planning: driver ill with the following:

  • 1. Batch schedule: driver ill
  • 2. Real-time planning update: driver ill
  • 3. Real-time planning update: driver becomes ill

1. Batch schedule: driver ill

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 batch planning:

  • 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: driver ill 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: driver ill 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 and Ann’s shift itinerary.

2. Real-time planning update: driver ill

When a driver becomes ill before a shift has started, they can be removed from the input dataset.

The following shows the input to be removed and the patch operation that will change the original input:

  • Input

  • Patch

{
  "id": "Ann",
  "shifts": [
    {
      "id": "Ann Mon",
      "startLocation": [33.79426, -84.330114],
      "minStartTime": "2027-02-01T09:00:00Z",
      "maxEndTime": "2027-02-01T13:30:00Z"
    }
  ]
}
{
  "op": "remove",
  "path": "/drivers/[id=Ann]"
}

Timefold will reassign jobs that can be reassigned and leave any remaining jobs unassigned to be rescheduled for another day.

  • Patch

  • Output

Try this example in Timefold Platform by saving this JSON into a file called patch.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/<ID>/from-patch [email protected]
{
  "config": {
    "run": {
      "name": "Real-time planning: driver ill example"
    }
  },
  "patch": [
    {
      "op": "remove",
      "path": "/drivers/[id=Carl]"
    }
  ]
}
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: driver ill example",
    "submitDateTime": "2026-04-09T17:09:04.242218+02:00",
    "startDateTime": "2026-04-09T17:09:04.39681+02:00",
    "activeDateTime": "2026-04-09T17:09:04.398884+02:00",
    "completeDateTime": "2026-04-09T17:09:34.414763+02:00",
    "shutdownDateTime": "2026-04-09T17:09:34.414766+02:00",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/-20000medium/-5073soft",
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "drivers": [
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "Stop E",
                "arrivalTime": "2027-02-01T09:06:17Z",
                "startServiceTime": "2027-02-01T09:06:17Z",
                "departureTime": "2027-02-01T09:36:17Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT6M17S",
                "travelDistanceMetersFromPreviousStandstill": 5233,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop F",
                "arrivalTime": "2027-02-01T10:01:03Z",
                "startServiceTime": "2027-02-01T10:01:03Z",
                "departureTime": "2027-02-01T10:31:03Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT24M46S",
                "travelDistanceMetersFromPreviousStandstill": 20642,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop G",
                "arrivalTime": "2027-02-01T10:40:17Z",
                "startServiceTime": "2027-02-01T10:40:17Z",
                "departureTime": "2027-02-01T11:10:17Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT9M14S",
                "travelDistanceMetersFromPreviousStandstill": 7689,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop H",
                "arrivalTime": "2027-02-01T11:24:22Z",
                "startServiceTime": "2027-02-01T11:24:22Z",
                "departureTime": "2027-02-01T11:54:22Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT14M5S",
                "travelDistanceMetersFromPreviousStandstill": 11743,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop A",
                "arrivalTime": "2027-02-01T11:55:22Z",
                "startServiceTime": "2027-02-01T11:55:22Z",
                "departureTime": "2027-02-01T12:25:22Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT1M",
                "travelDistanceMetersFromPreviousStandstill": 830,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop B",
                "arrivalTime": "2027-02-01T12:37:58Z",
                "startServiceTime": "2027-02-01T12:37:58Z",
                "departureTime": "2027-02-01T13:07:58Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT12M36S",
                "travelDistanceMetersFromPreviousStandstill": 10498,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "kind": "STOP"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT1H24M33S",
              "travelTimeFromStartLocationToFirstStop": "PT6M17S",
              "travelTimeBetweenStops": "PT1H1M41S",
              "travelTimeFromLastStopToEndLocation": "PT16M35S",
              "totalTravelDistanceMeters": 70450,
              "travelDistanceFromStartLocationToFirstStopMeters": 5233,
              "travelDistanceBetweenStopsMeters": 51402,
              "travelDistanceFromLastStopToEndLocationMeters": 13815,
              "endLocationArrivalTime": "2027-02-01T13:24:33Z"
            }
          }
        ]
      }
    ],
    "unassignedJobs": [
      {
        "id": "Job 2",
        "unassignedStops": [
          "Stop C",
          "Stop D"
        ]
      }
    ]
  },
  "inputMetrics": {
    "jobs": 4,
    "stops": 8,
    "drivers": 1,
    "driverShifts": 1,
    "pinnedStops": 0
  },
  "kpis": {
    "totalTravelTime": "PT1H24M33S",
    "totalTravelDistanceMeters": 70450,
    "totalActivatedDrivers": 1,
    "totalUnassignedJobs": 1,
    "totalAssignedJobs": 3,
    "assignedMandatoryJobs": 3,
    "totalUnassignedStops": 2,
    "totalAssignedStops": 6,
    "assignedMandatoryStops": 6,
    "travelTimeFromStartLocationToFirstStop": "PT6M17S",
    "travelTimeBetweenStops": "PT1H1M41S",
    "travelTimeFromLastStopToEndLocation": "PT16M35S",
    "travelDistanceFromStartLocationToFirstStopMeters": 5233,
    "travelDistanceBetweenStopsMeters": 51402,
    "travelDistanceFromLastStopToEndLocationMeters": 13815
  }
}

modelOutput contains Carl’s updated shift itinerary.

Jobs 1 and 3 were reassigned from Ann to Carl. Job 2 remains unassigned.

3. Real-time planning update: driver becomes ill

In this example, Ann becomes ill after starting her work day. After picking up her first job (Stop E), Ann realizes that she is ill and needs to go home. Instead of continuing with her remaining jobs, she delivers the first job (Stop F) and then goes home.

The plan must be updated part way through the day.

Include the itineraries for both Ann and Carl. As Ann will only complete her first job (Stop E and Stop F), her itinerary will only include that job. Ann’s itinerary should also be pinned to ensure that it isn’t changed during the real-time planning update. Carl’s itinerary should include all of his previously assigned jobs:

The following shows the required input and the patch operation that will change the original input:

  • Input

  • Patch

{
  "id": "Ann",
  "shifts": [
    {
      "id": "Ann Mon",
      "startLocation": [33.79426, -84.330114],
      "minStartTime": "2027-02-01T09:00:00Z",
      "maxEndTime": "2027-02-01T13:30:00Z",
      "pinned": true,
      "itinerary": [
        {
          "id": "Stop E",
          "kind": "STOP"
        },
        {
          "id": "Stop F",
          "kind": "STOP"
        }
      ]
    }
  ]
}
[
  {
    "op": "add",
    "path": "/drivers/[id=Ann]/shifts/[id=Ann Mon]/pinned",
    "value": true
  },
  {
    "op": "add",
    "path": "/drivers/[id=Ann]/shifts/[id=Ann Mon]/itinerary",
    "value": [
      {
        "id": "Stop E",
        "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. Ann finished Stop E at 09:47 when she realized that she was ill and needed to go home, so the freezeTime can be set to 09:47.

The following shows the required input and the patch operation that will change the original input:

  • Input

  • Patch

{
  "modelInput": {
    "freezeTime": "2027-02-01T09:47:00Z"
  }
}
{
  "op": "add",
  "path": "/freezeTime",
  "value": "2027-02-01T09:47:00Z"
}

Submit the input dataset to generate the new real-time plan:

  • Patch

  • Output

Try this example in Timefold Platform by saving this JSON into a file called patch.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/<ID>/from-patch [email protected]
{
  "config": {
    "run": {
      "name": "Real-time planning: driver becomes ill example"
    }
  },
  "patch": [
    {
      "op": "add",
      "path": "/freezeTime",
      "value": "2027-02-01T09:47:00Z"
    },
    {
      "op": "add",
      "path": "/drivers/[id=Ann]/shifts/[id=Ann Mon]/pinned",
      "value": true
    },
    {
      "op": "add",
      "path": "/drivers/[id=Ann]/shifts/[id=Ann Mon]/itinerary",
      "value": [
        {
          "id": "Stop E",
          "kind": "STOP"
        },
        {
          "id": "Stop F",
          "kind": "STOP"
        }
      ]
    }
  ]
}
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: driver ill example",
    "submitDateTime": "2026-04-10T09:42:31.757761+02:00",
    "startDateTime": "2026-04-10T09:42:31.886929+02:00",
    "activeDateTime": "2026-04-10T09:42:31.888494+02:00",
    "completeDateTime": "2026-04-10T09:43:01.906806+02:00",
    "shutdownDateTime": "2026-04-10T09:43:01.906811+02:00",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-8647soft",
    "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 C",
                "arrivalTime": "2027-02-01T10:29:27Z",
                "startServiceTime": "2027-02-01T10:29:27Z",
                "departureTime": "2027-02-01T10:59:27Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT5M1S",
                "travelDistanceMetersFromPreviousStandstill": 4186,
                "minStartTravelTime": "2027-02-01T09:47:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop D",
                "arrivalTime": "2027-02-01T11:15:47Z",
                "startServiceTime": "2027-02-01T11:15:47Z",
                "departureTime": "2027-02-01T11:45:47Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT16M20S",
                "travelDistanceMetersFromPreviousStandstill": 13610,
                "minStartTravelTime": "2027-02-01T09:47:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop A",
                "arrivalTime": "2027-02-01T11:57:21Z",
                "startServiceTime": "2027-02-01T11:57:21Z",
                "departureTime": "2027-02-01T12:27:21Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT11M34S",
                "travelDistanceMetersFromPreviousStandstill": 9640,
                "minStartTravelTime": "2027-02-01T09:47:00Z",
                "load": [],
                "kind": "STOP"
              },
              {
                "id": "Stop B",
                "arrivalTime": "2027-02-01T12:39:57Z",
                "startServiceTime": "2027-02-01T12:39:57Z",
                "departureTime": "2027-02-01T13:09:57Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT12M36S",
                "travelDistanceMetersFromPreviousStandstill": 10498,
                "minStartTravelTime": "2027-02-01T09:47:00Z",
                "load": [],
                "kind": "STOP"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT1H26M32S",
              "travelTimeFromStartLocationToFirstStop": "PT10M21S",
              "travelTimeBetweenStops": "PT59M36S",
              "travelTimeFromLastStopToEndLocation": "PT16M35S",
              "totalTravelDistanceMeters": 72121,
              "travelDistanceFromStartLocationToFirstStopMeters": 8629,
              "travelDistanceBetweenStopsMeters": 49677,
              "travelDistanceFromLastStopToEndLocationMeters": 13815,
              "endLocationArrivalTime": "2027-02-01T13:26:32Z"
            }
          }
        ]
      },
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann Mon",
            "startTime": "2027-02-01T09:00:00Z",
            "pinned": true,
            "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 F",
                "arrivalTime": "2027-02-01T10:11:57Z",
                "startServiceTime": "2027-02-01T10:11:57Z",
                "departureTime": "2027-02-01T10:41:57Z",
                "effectiveServiceDuration": "PT30M",
                "travelTimeFromPreviousStandstill": "PT24M46S",
                "travelDistanceMetersFromPreviousStandstill": 20642,
                "minStartTravelTime": "2027-02-01T00:00:00Z",
                "load": [],
                "pinned": true,
                "kind": "STOP"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT57M35S",
              "travelTimeFromStartLocationToFirstStop": "PT17M11S",
              "travelTimeBetweenStops": "PT24M46S",
              "travelTimeFromLastStopToEndLocation": "PT15M38S",
              "totalTravelDistanceMeters": 47998,
              "travelDistanceFromStartLocationToFirstStopMeters": 14324,
              "travelDistanceBetweenStopsMeters": 20642,
              "travelDistanceFromLastStopToEndLocationMeters": 13032,
              "endLocationArrivalTime": "2027-02-01T10:57:35Z"
            }
          }
        ]
      }
    ],
    "unassignedJobs": []
  },
  "inputMetrics": {
    "jobs": 4,
    "stops": 8,
    "drivers": 2,
    "driverShifts": 2,
    "pinnedStops": 4
  },
  "kpis": {
    "totalTravelTime": "PT2H24M7S",
    "totalTravelDistanceMeters": 120119,
    "totalActivatedDrivers": 2,
    "totalUnassignedJobs": 0,
    "totalAssignedJobs": 4,
    "assignedMandatoryJobs": 4,
    "totalUnassignedStops": 0,
    "totalAssignedStops": 8,
    "assignedMandatoryStops": 8,
    "travelTimeFromStartLocationToFirstStop": "PT27M32S",
    "travelTimeBetweenStops": "PT1H24M22S",
    "travelTimeFromLastStopToEndLocation": "PT32M13S",
    "travelDistanceFromStartLocationToFirstStopMeters": 22953,
    "travelDistanceBetweenStopsMeters": 70319,
    "travelDistanceFromLastStopToEndLocationMeters": 26847
  }
}

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

Ann completed Stop E and Stop F. Her other jobs (Job 1 and Job 4) were reassigned to Carl.

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