Lunch breaks and personal appointments
It’s important in any field service routing solution to include times when technicians can take breaks.
Technicians who work an eight-hour shift need a lunch break. They may also need to attend appointments that can’t be arranged outside their regular work hours.
There are also occasions when all technicians must attend team meetings at the same time and location.
Breaks, such as lunch breaks, can be floating breaks that fit in around the assigned visits and are taken at any location.
A technician who has an appointment, needs the appointment to be included in his schedule, and the schedule must include travel time from their last visit to the appointment and from the appointment to the next visit.
Team meetings that all technicians must attend need to provide adequate travel time for all technicians to arrive at the meeting, while still scheduling visits before and after the meeting.
Regardless of the scenario, an optimized field service routing plan will schedule customer visits, lunch breaks, appointments, team meetings, and travel between them to be a feasible solution.
This guide explains how to manage breaks with the following examples:
Prerequisites
To run the examples in this guide, you need to authenticate with a valid API key for this model:
-
Log in to Timefold Platform: app.timefold.ai
-
From the Dashboard, click your tenant, and from the drop-down menu select Tenant Settings, then choose API Keys.
-
Create a new API key or use an existing one. Ensure the list of models for the API key contains the current model.
In the examples, replace <API_KEY>
with the API Key you just copied.
1. Floating lunch breaks
Technician’s shifts run for a specific number of hours per day, ie, from 09:00 to 17:00, and must include a break for lunch.
Breaks have a set duration and are scheduled to occur after an earliest start time, for example, a lunch break might be scheduled to occur any time after 12:00.
In the example below, Carl completes Visit C before 12:00 (which is the earliest time he could take his lunch break), so he travels to his next visit. He arrives at the location for Visit A at 12:20. He then takes his lunch break which is scheduled for one hour. After lunch, he is on site and ready to start work at Visit A at 13:20.
Breaks are added to shifts by including the requiredBreaks
array:
{
"shifts": [
{
"id": "Carl-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"requiredBreaks": [
{
"id": "carl-lunch-2027-02-01",
"minStartTime": "2027-02-01T12:00:00Z",
"duration": "PT1H"
}
]
}
]
}
At a minimum, requiredBreaks
include, id
, minStartTime
, and duration
:
-
id
is a unique string that identifies the break, for instance:carl-lunch-2027-02-01
or353
. -
minStartTime
is a date and time (in ISO 8601 date time with offset to UTC format) for the earliest time the break can start. -
duration
represents the length of the break in ISO 8601 duration format.
In the following example, Carl works an eight-hour shift with a one-hour break for lunch:
-
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/field-service-routing/v1/route-plans [email protected]
{
"config": {
"run": {
"name": "Lunch break example"
}
},
"modelInput": {
"vehicles": [
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"requiredBreaks": [
{
"id": "Carl-lunch-2027-02-01",
"minStartTime": "2027-02-01T12:00:00Z",
"duration": "PT1H"
}
]
}
]
}
],
"visits": [
{
"id": "Visit A",
"location": [33.77301, -84.43838],
"serviceDuration": "PT1H"
},
{
"id": "Visit B",
"location": [33.74699, -84.02504],
"serviceDuration": "PT1H"
},
{
"id": "Visit C",
"location": [33.88664, -84.28118],
"serviceDuration": "PT1H"
},
{
"id": "Visit D",
"location": [33.71030, -84.05439],
"serviceDuration": "PT1H"
}
]
}
}
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/field-service-routing/v1/route-plans/<ID>
{
"run": {
"id": "ID",
"name": "Lunch break example",
"submitDateTime": "2024-09-18T01:43:43.227601124Z",
"startDateTime": "2024-09-18T01:43:48.576942816Z",
"activeDateTime": "2024-09-18T01:43:48.676942816Z",
"completeDateTime": "2024-09-18T01:48:49.174389094Z",
"shutdownDateTime": "2024-09-18T01:48:49.274389094Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/-7148soft",
"tags": null,
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"vehicles": [
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "Visit C",
"kind": "VISIT",
"arrivalTime": "2027-02-01T09:27:39Z",
"startServiceTime": "2027-02-01T09:27:39Z",
"departureTime": "2027-02-01T10:27:39Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT27M39S",
"travelDistanceMetersFromPreviousStandstill": 30741,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit A",
"kind": "VISIT",
"arrivalTime": "2027-02-01T10:51:08Z",
"startServiceTime": "2027-02-01T10:51:08Z",
"departureTime": "2027-02-01T11:51:08Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT23M29S",
"travelDistanceMetersFromPreviousStandstill": 24210,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Carl-lunch-2027-02-01",
"kind": "BREAK",
"startTime": "2027-02-01T12:34:44Z",
"endTime": "2027-02-01T13:34:44Z"
},
{
"id": "Visit B",
"kind": "VISIT",
"arrivalTime": "2027-02-01T12:34:44Z",
"startServiceTime": "2027-02-01T13:34:44Z",
"departureTime": "2027-02-01T14:34:44Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT43M36S",
"travelDistanceMetersFromPreviousStandstill": 49957,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit D",
"kind": "VISIT",
"arrivalTime": "2027-02-01T14:42:50Z",
"startServiceTime": "2027-02-01T14:42:50Z",
"departureTime": "2027-02-01T15:42:50Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT8M6S",
"travelDistanceMetersFromPreviousStandstill": 7287,
"minStartTravelTime": "2027-02-01T00:00:00Z"
}
],
"metrics": {
"totalTravelTime": "PT1H59M8S",
"travelTimeFromStartLocationToFirstVisit": "PT27M39S",
"travelTimeBetweenVisits": "PT1H15M11S",
"travelTimeFromLastVisitToEndLocation": "PT16M18S",
"totalTravelDistanceMeters": 127554,
"travelDistanceFromStartLocationToFirstVisitMeters": 30741,
"travelDistanceBetweenVisitsMeters": 81454,
"travelDistanceFromLastVisitToEndLocationMeters": 15359,
"endLocationArrivalTime": "2027-02-01T15:59:08Z"
}
}
]
}
]
},
"kpis": {
"totalTravelTime": "PT1H59M8S",
"travelTimeFromStartLocationToFirstVisit": "PT27M39S",
"travelTimeBetweenVisits": "PT1H15M11S",
"travelTimeFromLastVisitToEndLocation": "PT16M18S",
"totalTravelDistanceMeters": 127554,
"travelDistanceFromStartLocationToFirstVisitMeters": 30741,
"travelDistanceBetweenVisitsMeters": 81454,
"travelDistanceFromLastVisitToEndLocationMeters": 15359,
"totalUnassignedVisits": 0
}
}
modelOutput
contains Carl’s itinerary for the day with his scheduled lunch break.
2. Personal appointments
Sometimes, breaks are fixed and need to occur at a specific time and location, for instance, if a technician has a personal appointment, such as a visit to the dentist.
When this is the case, Timefold will schedule the break at the specified time and include travel time to the location.
In the following example, Carl has a dentist appointment at 12:00. Visit A ends at 12:30, Carl then travels to the location of his appointment, but he arrives early and must wait until the scheduled appointment at 14:00.
After his appointment, he travels to Visit B.
Fixed breaks are achieved by adding a maxStartTime
that is the same as the minStartTime
.
Setting both minStartTime
and maxStartTime
to "2027-02-01T14:00:00Z"
will result in the break starting at 14:00.
The location
is specified in the requiredBreaks
array. The plan will include travel to the location of the break and to the next visit after the break.
{
"id": "Carl-2027-02-01",
"requiredBreaks": [
{
"id": "Carl-dentist-2027-02-01",
"minStartTime": "2027-02-01T14:00:00Z",
"maxStartTime": "2027-02-01T14:00:00Z",
"duration": "PT1H",
"location": [33.68786, -84.18487]
}
]
}
In the following example, Carl has a dentist appointment at 14:00.
-
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/field-service-routing/v1/route-plans [email protected]
{
"config": {
"run": {
"name": "Fixed break with a location example"
}
},
"modelInput": {
"vehicles": [
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startLocation": [
33.68786,
-84.18487
],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"requiredBreaks": [
{
"id": "Carl-dentist-2027-02-01",
"minStartTime": "2027-02-01T14:00:00Z",
"maxStartTime": "2027-02-01T14:00:00Z",
"duration": "PT1H",
"location": [
33.79438,
-84.13629
]
}
]
}
]
}
],
"visits": [
{
"id": "Visit A",
"location": [
33.77301,
-84.43838
],
"serviceDuration": "PT1H"
},
{
"id": "Visit B",
"location": [
33.74699,
-84.02504
],
"serviceDuration": "PT1H"
},
{
"id": "Visit C",
"location": [
33.88664,
-84.28118
],
"serviceDuration": "PT1H"
},
{
"id": "Visit D",
"location": [
33.71030,
-84.05439
],
"serviceDuration": "PT1H"
}
]
}
}
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/field-service-routing/v1/route-plans/<ID>
{
"run": {
"id": "ID",
"name": "Fixed break with a location example",
"submitDateTime": "2024-09-16T09:55:41.986875415Z",
"startDateTime": "2024-09-16T09:55:47.648560712Z",
"activeDateTime": "2024-09-16T09:55:47.748560712Z",
"completeDateTime": "2024-09-16T10:00:48.108145695Z",
"shutdownDateTime": "2024-09-16T10:00:48.208145695Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/-7070soft",
"tags": null,
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"vehicles": [
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "Visit D",
"kind": "VISIT",
"arrivalTime": "2027-02-01T09:16:24Z",
"startServiceTime": "2027-02-01T09:16:24Z",
"departureTime": "2027-02-01T10:16:24Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT16M24S",
"travelDistanceMetersFromPreviousStandstill": 15551,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit C",
"kind": "VISIT",
"arrivalTime": "2027-02-01T10:53:08Z",
"startServiceTime": "2027-02-01T10:53:08Z",
"departureTime": "2027-02-01T11:53:08Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT36M44S",
"travelDistanceMetersFromPreviousStandstill": 43191,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit A",
"kind": "VISIT",
"arrivalTime": "2027-02-01T12:16:37Z",
"startServiceTime": "2027-02-01T12:16:37Z",
"departureTime": "2027-02-01T13:16:37Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT23M29S",
"travelDistanceMetersFromPreviousStandstill": 24210,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Carl-dentist-2027-02-01",
"kind": "BREAK",
"startTime": "2027-02-01T14:00:00Z",
"endTime": "2027-02-01T15:00:00Z",
"travelTimeFromPreviousStandstill": "PT36M34S",
"travelDistanceMetersFromPreviousStandstill": 31230
},
{
"id": "Visit B",
"kind": "VISIT",
"arrivalTime": "2027-02-01T15:19:33Z",
"startServiceTime": "2027-02-01T15:19:33Z",
"departureTime": "2027-02-01T16:19:33Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT19M33S",
"travelDistanceMetersFromPreviousStandstill": 15307,
"minStartTravelTime": "2027-02-01T00:00:00Z"
}
],
"metrics": {
"totalTravelTime": "PT2H34M24S",
"travelTimeFromStartLocationToFirstVisit": "PT16M24S",
"travelTimeBetweenVisits": "PT1H56M20S",
"travelTimeFromLastVisitToEndLocation": "PT21M40S",
"totalTravelDistanceMeters": 150711,
"travelDistanceFromStartLocationToFirstVisitMeters": 15551,
"travelDistanceBetweenVisitsMeters": 113938,
"travelDistanceFromLastVisitToEndLocationMeters": 21222,
"endLocationArrivalTime": "2027-02-01T16:41:13Z"
}
}
]
}
]
},
"kpis": {
"totalTravelTime": "PT2H34M24S",
"travelTimeFromStartLocationToFirstVisit": "PT16M24S",
"travelTimeBetweenVisits": "PT1H56M20S",
"travelTimeFromLastVisitToEndLocation": "PT21M40S",
"totalTravelDistanceMeters": 150711,
"travelDistanceFromStartLocationToFirstVisitMeters": 15551,
"travelDistanceBetweenVisitsMeters": 113938,
"travelDistanceFromLastVisitToEndLocationMeters": 21222,
"totalUnassignedVisits": 0
}
}
modelOutput
contains Carl’s itinerary for the day with his scheduled appointment break.
2.1. Appointments without a location
There are occasions when employees need to attend appointments, but the location of the appointment is sensitive information, for instance if they are receiving medical treatment or attending a job interview, and they do not share the location with their employer.
When the location for a fixed appointment is not provided, Timefold cannot schedule travel time.
In the following example, Carl has an appointment at 13:00, but he hasn’t provided the location.
In this case, Carl is assigned to Visit A which ends at 12:20. Without the location information, Timefold delays travel from Visit A to Visit B until after the appointment.
However, this approach may not provide enough travel time to reach the appointment, and the travel time from the appointment to Visit B is unlikely to be accurate. In such situations, it may be necessary to pad the appointment to provide additional travel time.
Sharing the location of appointments with their employer is a change for many employees who might be familiar with systems where this isn’t necessary, but if employees are comfortable sharing the location of their appointments, travel time can be included, and it becomes unnecessary to add additional time, and the schedule will include less driving time and more time available for customer visits.
3. Team meetings
When technicians are all required to attend a meeting at the same location, the meeting is added as a required break for each technician.
Timefold will schedule visits and travel throughout the day, with travel from the last visit before the meeting to the meeting, and travel from the meeting to the next visit after the meeting for each technician.
The meeting is a fixed break that must happen at a specific time at a specific location.
minStartTime
and maxStartTime
are set to the same value. A duration
and a location
are both included.
{
"id": "Ann-2027-02-01",
"requiredBreaks": [
{
"id": "Ann-meeting-2027-02-01",
"minStartTime": "2027-02-01T13:00:00Z",
"maxStartTime": "2027-02-01T13:00:00Z",
"duration": "PT2H",
"location": [33.75812, -84.36219]
}
]
}
The technicians are all attending the same team meeting, however, the
|
In the following example, Ann and Carl are both working 09:00 to 17:00 shifts, Beth is taking PTO in the morning. The team has been working hard and the team meeting has been combined with a team lunch. The meeting is taking place at 13:00 to 15:00.
-
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/field-service-routing/v1/route-plans [email protected]
{
"config": {
"run": {
"name": "Team meeting example"
}
},
"modelInput": {
"vehicles": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"requiredBreaks": [
{
"id": "Ann-meeting-2027-02-01",
"minStartTime": "2027-02-01T13:00:00Z",
"maxStartTime": "2027-02-01T13:00:00Z",
"duration": "PT2H",
"location": [33.75812, -84.36219]
}
]
}
]
},
{
"id": "Beth",
"shifts": [
{
"id": "Beth-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T12:30:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"requiredBreaks": [
{
"id": "Beth-meeting-2027-02-01",
"minStartTime": "2027-02-01T13:00:00Z",
"maxStartTime": "2027-02-01T13:00:00Z",
"duration": "PT2H",
"location": [33.75812, -84.36219]
}
]
}
]
},
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"requiredBreaks": [
{
"id": "Carl-meeting-2027-02-01",
"minStartTime": "2027-02-01T13:00:00Z",
"maxStartTime": "2027-02-01T13:00:00Z",
"duration": "PT2H",
"location": [33.75812, -84.36219]
}
]
}
]
}
],
"visits": [
{
"id": "Visit A",
"location": [33.77301, -84.43838],
"serviceDuration": "PT1H"
},
{
"id": "Visit B",
"location": [33.74699, -84.02504],
"serviceDuration": "PT1H"
},
{
"id": "Visit C",
"location": [33.88664, -84.28118],
"serviceDuration": "PT1H"
},
{
"id": "Visit D",
"location": [33.71030, -84.05439],
"serviceDuration": "PT1H"
},
{
"id": "Visit E",
"location": [33.75790, -84.12067],
"serviceDuration": "PT1H"
},
{
"id": "Visit F",
"location": [33.72416, -84.01022],
"serviceDuration": "PT1H"
},
{
"id": "Visit G",
"location": [33.75987, -84.17453],
"serviceDuration": "PT1H"
}
]
}
}
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/field-service-routing/v1/route-plans/<ID>
{
"run": {
"id": "ID",
"name": "Team meeting example",
"submitDateTime": "2024-09-17T05:08:30.310476661Z",
"startDateTime": "2024-09-17T05:08:38.367377371Z",
"activeDateTime": "2024-09-17T05:08:38.467377371Z",
"completeDateTime": "2024-09-17T05:13:38.83207233Z",
"shutdownDateTime": "2024-09-17T05:13:38.93207233Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/-11096soft",
"tags": null,
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"vehicles": [
{
"id": "Ann",
"shifts": [
{
"id": "Ann-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "Visit D",
"kind": "VISIT",
"arrivalTime": "2027-02-01T09:16:24Z",
"startServiceTime": "2027-02-01T09:16:24Z",
"departureTime": "2027-02-01T10:16:24Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT16M24S",
"travelDistanceMetersFromPreviousStandstill": 15551,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit F",
"kind": "VISIT",
"arrivalTime": "2027-02-01T10:26:23Z",
"startServiceTime": "2027-02-01T10:26:23Z",
"departureTime": "2027-02-01T11:26:23Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT9M59S",
"travelDistanceMetersFromPreviousStandstill": 7749,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Ann-meeting-2027-02-01",
"kind": "BREAK",
"startTime": "2027-02-01T13:00:00Z",
"endTime": "2027-02-01T15:00:00Z",
"travelTimeFromPreviousStandstill": "PT36M20S",
"travelDistanceMetersFromPreviousStandstill": 41231
},
{
"id": "Visit G",
"kind": "VISIT",
"arrivalTime": "2027-02-01T15:23:18Z",
"startServiceTime": "2027-02-01T15:23:18Z",
"departureTime": "2027-02-01T16:23:18Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT23M18S",
"travelDistanceMetersFromPreviousStandstill": 19886,
"minStartTravelTime": "2027-02-01T00:00:00Z"
}
],
"metrics": {
"totalTravelTime": "PT1H37M42S",
"travelTimeFromStartLocationToFirstVisit": "PT16M24S",
"travelTimeBetweenVisits": "PT1H9M37S",
"travelTimeFromLastVisitToEndLocation": "PT11M41S",
"totalTravelDistanceMeters": 94301,
"travelDistanceFromStartLocationToFirstVisitMeters": 15551,
"travelDistanceBetweenVisitsMeters": 68866,
"travelDistanceFromLastVisitToEndLocationMeters": 9884,
"endLocationArrivalTime": "2027-02-01T16:34:59Z"
}
}
]
},
{
"id": "Beth",
"shifts": [
{
"id": "Beth-2027-02-01",
"startTime": "2027-02-01T12:30:00Z",
"itinerary": [
{
"id": "Beth-meeting-2027-02-01",
"kind": "BREAK",
"startTime": "2027-02-01T13:00:00Z",
"endTime": "2027-02-01T15:00:00Z",
"travelTimeFromPreviousStandstill": "PT22M19S",
"travelDistanceMetersFromPreviousStandstill": 22006
},
{
"id": "Visit A",
"kind": "VISIT",
"arrivalTime": "2027-02-01T15:11:44Z",
"startServiceTime": "2027-02-01T15:11:44Z",
"departureTime": "2027-02-01T16:11:44Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT11M44S",
"travelDistanceMetersFromPreviousStandstill": 9137,
"minStartTravelTime": "2027-02-01T00:00:00Z"
}
],
"metrics": {
"totalTravelTime": "PT1H3M35S",
"travelTimeFromStartLocationToFirstVisit": "PT22M19S",
"travelTimeBetweenVisits": "PT11M44S",
"travelTimeFromLastVisitToEndLocation": "PT29M32S",
"totalTravelDistanceMeters": 65127,
"travelDistanceFromStartLocationToFirstVisitMeters": 22006,
"travelDistanceBetweenVisitsMeters": 9137,
"travelDistanceFromLastVisitToEndLocationMeters": 33984,
"endLocationArrivalTime": "2027-02-01T16:41:16Z"
}
}
]
},
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "Visit E",
"kind": "VISIT",
"arrivalTime": "2027-02-01T09:16:26Z",
"startServiceTime": "2027-02-01T09:16:26Z",
"departureTime": "2027-02-01T10:16:26Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT16M26S",
"travelDistanceMetersFromPreviousStandstill": 12102,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit B",
"kind": "VISIT",
"arrivalTime": "2027-02-01T10:32:02Z",
"startServiceTime": "2027-02-01T10:32:02Z",
"departureTime": "2027-02-01T11:32:02Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT15M36S",
"travelDistanceMetersFromPreviousStandstill": 13054,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Carl-meeting-2027-02-01",
"kind": "BREAK",
"startTime": "2027-02-01T13:00:00Z",
"endTime": "2027-02-01T15:00:00Z",
"travelTimeFromPreviousStandstill": "PT36M45S",
"travelDistanceMetersFromPreviousStandstill": 40321
},
{
"id": "Visit C",
"kind": "VISIT",
"arrivalTime": "2027-02-01T15:21:29Z",
"startServiceTime": "2027-02-01T15:21:29Z",
"departureTime": "2027-02-01T16:21:29Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT21M29S",
"travelDistanceMetersFromPreviousStandstill": 22771,
"minStartTravelTime": "2027-02-01T00:00:00Z"
}
],
"metrics": {
"totalTravelTime": "PT1H59M3S",
"travelTimeFromStartLocationToFirstVisit": "PT16M26S",
"travelTimeBetweenVisits": "PT1H13M50S",
"travelTimeFromLastVisitToEndLocation": "PT28M47S",
"totalTravelDistanceMeters": 117922,
"travelDistanceFromStartLocationToFirstVisitMeters": 12102,
"travelDistanceBetweenVisitsMeters": 76146,
"travelDistanceFromLastVisitToEndLocationMeters": 29674,
"endLocationArrivalTime": "2027-02-01T16:50:16Z"
}
}
]
}
]
},
"kpis": {
"totalTravelTime": "PT4H40M20S",
"travelTimeFromStartLocationToFirstVisit": "PT55M9S",
"travelTimeBetweenVisits": "PT2H35M11S",
"travelTimeFromLastVisitToEndLocation": "PT1H10M",
"totalTravelDistanceMeters": 277350,
"travelDistanceFromStartLocationToFirstVisitMeters": 49659,
"travelDistanceBetweenVisitsMeters": 154149,
"travelDistanceFromLastVisitToEndLocationMeters": 73542,
"totalUnassignedVisits": 0
}
}
modelOutput
contains the technicians' itineraries which include the team meeting.
Team meetings typically occur at the beginning or the end of the shift.
If the team meeting occurs at the beginning of the shift,
you can use minFirstVisitArrivalTime
set to the start time of the meeting so that travel time to the meeting isn’t included in the schedule.
See First travel time for more information.
If the team meeting occurs at the end of the shift,
you can use maxLastVisitDepartureTime
set to the end time of the meeting so that travel time home isn’t included in the schedule.
See Last travel time for more information.
Next
-
Understand the constraints of the Field Service Routing model.
-
See the full API spec or try the online API.
-
Manage shift times with Time zones and daylight-saving time (DST) changes.
-
Learn about Shift hours and overtime.