Real-time planning: no show (Preview)
This guide describes features currently available as a preview feature. If you’d like early access to this feature, please Contact us. For information about the current supported feature, see Real-time planning. |
There are many situations where Real-time planning (preview) is necessary.
Sometimes customers are not available at the scheduled time.
When Carl arrives at his first visit of the day, the customer isn’t there to let him in. Carl lets head office know, and they start re-planning the visits for his shift.
Carl waits for 10 minutes at the customer location, but the customer doesn’t show up. The real-time plan is published and Carl goes to his next visit.
Prerequisites
Learn how to configure an API Key to run the examples in this guide:
-
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. Batch schedule: no show
Carl’s 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/field-service-routing/v1/route-plans [email protected]
{
"config": {
"run": {
"name": "Original shift plan: no show 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"
}
]
}
],
"visits": [
{
"id": "Visit E",
"location": [33.84475, -84.63649],
"serviceDuration": "PT1H"
},
{
"id": "Visit B",
"location": [33.90719, -84.28149],
"serviceDuration": "PT1H"
},
{
"id": "Visit D",
"location": [33.89351, -84.00649],
"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>
{
"metadata": {
"id": "ID",
"parentId": null,
"originId": "ID",
"name": "Original shift plan: no show example",
"submitDateTime": "2025-09-11T08:35:01.525739233Z",
"startDateTime": "2025-09-11T08:35:34.739560609Z",
"activeDateTime": "2025-09-11T08:35:34.826009582Z",
"completeDateTime": "2025-09-11T08:36:05.272880617Z",
"shutdownDateTime": "2025-09-11T08:36:05.638312282Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/-9547soft",
"tags": [
"system.type:from-request",
"system.profile:default"
],
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"vehicles": [
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "Visit E",
"kind": "VISIT",
"arrivalTime": "2027-02-01T09:49:00Z",
"startServiceTime": "2027-02-01T09:49:00Z",
"departureTime": "2027-02-01T10:49:00Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT49M",
"travelDistanceMetersFromPreviousStandstill": 54141,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit B",
"kind": "VISIT",
"arrivalTime": "2027-02-01T11:29:33Z",
"startServiceTime": "2027-02-01T11:29:33Z",
"departureTime": "2027-02-01T12:29:33Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT40M33S",
"travelDistanceMetersFromPreviousStandstill": 42300,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit D",
"kind": "VISIT",
"arrivalTime": "2027-02-01T13:01:14Z",
"startServiceTime": "2027-02-01T13:01:14Z",
"departureTime": "2027-02-01T14:01:14Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT31M41S",
"travelDistanceMetersFromPreviousStandstill": 34290,
"minStartTravelTime": "2027-02-01T00:00:00Z"
}
],
"metrics": {
"totalTravelTime": "PT2H39M7S",
"travelTimeFromStartLocationToFirstVisit": "PT49M",
"travelTimeBetweenVisits": "PT1H12M14S",
"travelTimeFromLastVisitToEndLocation": "PT37M53S",
"totalTravelDistanceMeters": 165335,
"travelDistanceFromStartLocationToFirstVisitMeters": 54141,
"travelDistanceBetweenVisitsMeters": 76590,
"travelDistanceFromLastVisitToEndLocationMeters": 34604,
"endLocationArrivalTime": "2027-02-01T14:39:07Z"
}
}
]
}
],
"unassignedVisits": []
},
"inputMetrics": {
"visits": 3,
"visitGroups": 0,
"vehicles": 1,
"mandatoryVisits": 3,
"optionalVisits": 0,
"vehicleShifts": 1,
"visitsWithSla": 0
},
"kpis": {
"totalTravelTime": "PT2H39M7S",
"travelTimeFromStartLocationToFirstVisit": "PT49M",
"travelTimeBetweenVisits": "PT1H12M14S",
"travelTimeFromLastVisitToEndLocation": "PT37M53S",
"totalTravelDistanceMeters": 165335,
"travelDistanceFromStartLocationToFirstVisitMeters": 54141,
"travelDistanceBetweenVisitsMeters": 76590,
"travelDistanceFromLastVisitToEndLocationMeters": 34604,
"totalUnassignedVisits": 0,
"totalAssignedVisits": 3,
"assignedMandatoryVisits": 3,
"assignedOptionalVisits": 0,
"totalActivatedVehicles": 1,
"workingTimeFairnessPercentage": 100
}
}
modelOutput
contains Carl’s shift itinerary.
2. Real-time planning update: no show
Carl reported the customer was not present when he arrived and waited at the visit location.
The customer was not present and the work was not completed. Assuming the customer still wants the work completed, the visit will need to be rescheduled for a later time. |
The serviceDuration
for Visit E needs to be updated from 1 hour to 10 minutes.
The following shows the required input and the patch operation that will change the original input:
-
Input
-
Patch
{
"id": "Visit E",
"location": [33.84475, -84.63649],
"serviceDuration": "PT10M"
}
{
"op": "replace",
"path": "/visits/[id=Visit E]/serviceDuration",
"value": "PT10M"
}
The departure times for visits that have already occurred and that technicians have already begin traveling to can be frozen by adding freezeDeparturesBeforeTime
and including the time when the freeze is implemented.
The following shows the required input and the patch operation that will change the original input:
-
Input
-
Patch
{
"modelInput": {
"freezeDeparturesBeforeTime": "2027-02-01T10:00:00Z"
}
}
{
"op": "add",
"path": "/freezeDeparturesBeforeTime",
"value": "2027-02-01T10:00:00Z"
}
Carl arrived at Visit E at 09:48 and waited 10 minutes.
FreezeDeparturesBeforeTime
is set to 10:00 so that his next visits can be rescheduled, and he can travel to the next location.
Submit the following patch to generate a new revision of the 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/field-service-routing/v1/route-plans/<ID>/from-patch [email protected]
{
"config": {
"run": {
"name": "Real-time planning: no show example"
}
},
"patch": [
{
"op": "add",
"path": "/freezeDeparturesBeforeTime",
"value": "2027-02-01T10:00:00Z"
},
{
"op": "replace",
"path": "/visits/[id=Visit E]/serviceDuration",
"value": "PT10M"
}
]
}
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>
{
"metadata": {
"id": "ID",
"name": "Real-time planning: no show example",
"submitDateTime": "2025-09-11T08:42:55.555910806Z",
"startDateTime": "2025-09-11T08:43:07.974508346Z",
"activeDateTime": "2025-09-11T08:43:08.018140566Z",
"completeDateTime": "2025-09-11T08:43:38.36945202Z",
"shutdownDateTime": "2025-09-11T08:43:38.897786937Z",
"solverStatus": "SOLVING_COMPLETED",
"score": "0hard/0medium/-9547soft",
"tags": [
"system.type:from-patch",
"system.profile:default"
],
"validationResult": {
"summary": "OK"
}
},
"modelOutput": {
"vehicles": [
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startTime": "2027-02-01T09:00:00Z",
"itinerary": [
{
"id": "Visit E",
"kind": "VISIT",
"arrivalTime": "2027-02-01T09:49:00Z",
"startServiceTime": "2027-02-01T09:49:00Z",
"departureTime": "2027-02-01T09:59:00Z",
"effectiveServiceDuration": "PT10M",
"travelTimeFromPreviousStandstill": "PT49M",
"travelDistanceMetersFromPreviousStandstill": 54141,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit B",
"kind": "VISIT",
"arrivalTime": "2027-02-01T10:39:33Z",
"startServiceTime": "2027-02-01T10:39:33Z",
"departureTime": "2027-02-01T11:39:33Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT40M33S",
"travelDistanceMetersFromPreviousStandstill": 42300,
"minStartTravelTime": "2027-02-01T00:00:00Z"
},
{
"id": "Visit D",
"kind": "VISIT",
"arrivalTime": "2027-02-01T12:11:14Z",
"startServiceTime": "2027-02-01T12:11:14Z",
"departureTime": "2027-02-01T13:11:14Z",
"effectiveServiceDuration": "PT1H",
"travelTimeFromPreviousStandstill": "PT31M41S",
"travelDistanceMetersFromPreviousStandstill": 34290,
"minStartTravelTime": "2027-02-01T10:00:00Z"
}
],
"metrics": {
"totalTravelTime": "PT2H39M7S",
"travelTimeFromStartLocationToFirstVisit": "PT49M",
"travelTimeBetweenVisits": "PT1H12M14S",
"travelTimeFromLastVisitToEndLocation": "PT37M53S",
"totalTravelDistanceMeters": 165335,
"travelDistanceFromStartLocationToFirstVisitMeters": 54141,
"travelDistanceBetweenVisitsMeters": 76590,
"travelDistanceFromLastVisitToEndLocationMeters": 34604,
"endLocationArrivalTime": "2027-02-01T13:49:07Z"
}
}
]
}
],
"unassignedVisits": []
},
"inputMetrics": {
"visits": 3,
"visitGroups": 0,
"vehicles": 1,
"mandatoryVisits": 3,
"optionalVisits": 0,
"vehicleShifts": 1,
"visitsWithSla": 0
},
"kpis": {
"totalTravelTime": "PT2H39M7S",
"travelTimeFromStartLocationToFirstVisit": "PT49M",
"travelTimeBetweenVisits": "PT1H12M14S",
"travelTimeFromLastVisitToEndLocation": "PT37M53S",
"totalTravelDistanceMeters": 165335,
"travelDistanceFromStartLocationToFirstVisitMeters": 54141,
"travelDistanceBetweenVisitsMeters": 76590,
"travelDistanceFromLastVisitToEndLocationMeters": 34604,
"totalUnassignedVisits": 0,
"totalAssignedVisits": 3,
"assignedMandatoryVisits": 3,
"assignedOptionalVisits": 0,
"totalActivatedVehicles": 1,
"workingTimeFairnessPercentage": 100
}
}
modelOutput
contains Carl’s updated shift itinerary.
Visit E was a no show, so Visits B and D are rescheduled for earlier in the day.
Next
-
See the full API spec or try the online API.
-
Learn more about field service routing from our YouTube playlist.
-
Learn about real-time planning.
-
Real-time planning with pinned visits.
-
Real-time planning with extended visits.
-
Real-time planning and emergency visits.