Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
  • Platform
Try models
  • Field Service Routing
  • Visit service constraints
  • Visit service level agreement (SLA)

Field Service Routing

    • Introduction
    • Planning AI concepts
    • Metrics and optimization goals
    • Getting started with field service routing
    • Understanding the API
    • Constraints
    • Vehicle resource constraints
      • Shift hours and overtime
      • Lunch breaks and personal appointments
      • Fairness
      • Technician costs
      • Technician ratings
    • Visit service constraints
      • Time windows and opening hours
      • Skills
      • Visit dependencies
      • Visit requirements
      • Multi-vehicle visits
      • Priority visits and optional visits
      • Visit service level agreement (SLA)
    • Recommendations
      • Recommendations
      • Visit time window recommendations
      • Visit group time window recommendations
    • Real-time planning
      • Real-time planning
      • Real-time planning: extended visit
      • Real-time planning: reassignment
      • Real-time planning: emergency visit
      • Real-time planning: no show
      • Real-time planning: technician ill
      • Real-time planning: pinning visits
    • Time zones and daylight-saving time (DST)
    • New and noteworthy
    • Upgrading to the latest versions
    • Feature requests
    • Reference guide

Visit service level agreement (SLA)

As described in the guide about time windows, visits can have hard requirements for when they can be serviced. This can refer to business hours of the service location or describe the general availability of the customer on site. In addition to these hard constraints about site availability, there is often requirements about when the visit should be completed. This requirement is called a service level agreement (SLA) and describes the maximum time allowed to complete the visit. This is often determined by the urgency of the incident that has been reported, and how quickly the service must be performed.

This guide describes the SLA with the following example:

  • Visit SLAs

Prerequisites

To run the examples in this guide, you need to authenticate with a valid API key for this model:

  1. Log in to Timefold Platform: app.timefold.ai.

  2. From the Dashboard, click your tenant, and from the drop-down menu select Tenant Settings, then choose API Keys.

  3. Create a new API key or use an existing one. Ensure the list of models for the API key contains the current model.

In the examples, replace <API_KEY> with the API Key you just copied.

1. Visit SLAs

In order to define an SLA, the property latestSlaEndTime needs to be added to the visit.

{
  "visits": [
    {
      "id": "Visit A",
      "location": [34.31785, -83.82816],
      "serviceDuration": "PT1H30M",
      "latestSlaEndTime": "2027-02-01T13:00:00Z"
    }
  ]
}

latestSlaEndTime uses the ISO 8601 date and time format with offset to UTC format.

Below is an example dataset with 1 vehicle and 2 visits, where 1 visit has a latestSlaEndTime defined:

  • Input

  • Output

Try this example in Timefold Platform by saving the JSON into a file called sla-example-1.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": "SLA 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 A",
        "location": [33.31785, -83.82816],
        "serviceDuration": "PT2H30M"
      },
      {
        "id": "Visit B",
        "location": [33.32468, -84.127456],
        "serviceDuration": "PT3H",
        "latestSlaEndTime": "2027-02-01T13:00:00Z"
      }
    ]
  }
}
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": "SLA example",
    "submitDateTime": "2025-05-16T12:01:05.974541+02:00",
    "startDateTime": "2025-05-16T12:01:05.987945+02:00",
    "activeDateTime": "2025-05-16T12:01:05.993695+02:00",
    "completeDateTime": "2025-05-16T12:01:36.002054+02:00",
    "shutdownDateTime": "2025-05-16T12:01:36.004414+02:00",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-130078soft",
    "tags": null,
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "vehicles": [
      {
        "id": "Carl",
        "shifts": [
          {
            "id": "Carl-2027-02-01",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "Visit B",
                "kind": "VISIT",
                "arrivalTime": "2027-02-01T09:48:53Z",
                "startServiceTime": "2027-02-01T09:48:53Z",
                "departureTime": "2027-02-01T12:48:53Z",
                "effectiveServiceDuration": "PT3H",
                "travelTimeFromPreviousStandstill": "PT48M53S",
                "travelDistanceMetersFromPreviousStandstill": 40733,
                "minStartTravelTime": "2027-02-01T00:00:00Z"
              },
              {
                "id": "Visit A",
                "kind": "VISIT",
                "arrivalTime": "2027-02-01T13:22:16Z",
                "startServiceTime": "2027-02-01T13:22:16Z",
                "departureTime": "2027-02-01T15:52:16Z",
                "effectiveServiceDuration": "PT2H30M",
                "travelTimeFromPreviousStandstill": "PT33M23S",
                "travelDistanceMetersFromPreviousStandstill": 27819,
                "minStartTravelTime": "2027-02-01T00:00:00Z"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT2H25M37S",
              "travelTimeFromStartLocationToFirstVisit": "PT48M53S",
              "travelTimeBetweenVisits": "PT33M23S",
              "travelTimeFromLastVisitToEndLocation": "PT1H3M21S",
              "totalTravelDistanceMeters": 121341,
              "travelDistanceFromStartLocationToFirstVisitMeters": 40733,
              "travelDistanceBetweenVisitsMeters": 27819,
              "travelDistanceFromLastVisitToEndLocationMeters": 52789,
              "endLocationArrivalTime": "2027-02-01T16:55:37Z",
              "technicianCosts": null,
              "overtime": null
            }
          }
        ]
      }
    ]
  },
  "inputMetrics": {
    "visits": 2,
    "visitGroups": 0,
    "vehicles": 1,
    "mandatoryVisits": 2,
    "optionalVisits": 0,
    "vehicleShifts": 1,
    "visitsWithSla": 1
  },
  "kpis": {
    "totalTravelTime": "PT2H25M37S",
    "travelTimeFromStartLocationToFirstVisit": "PT48M53S",
    "travelTimeBetweenVisits": "PT33M23S",
    "travelTimeFromLastVisitToEndLocation": "PT1H3M21S",
    "totalTravelDistanceMeters": 121341,
    "travelDistanceFromStartLocationToFirstVisitMeters": 40733,
    "travelDistanceBetweenVisitsMeters": 27819,
    "travelDistanceFromLastVisitToEndLocationMeters": 52789,
    "totalUnassignedVisits": 0,
    "totalAssignedVisits": 2,
    "assignedMandatoryVisits": 2,
    "assignedOptionalVisits": 0,
    "totalActivatedVehicles": 1,
    "workingTimeFairnessPercentage": 100.0,
    "totalTechnicianCosts": null,
    "totalOvertime": null,
    "percentageVisitsInSla": "100.0",
    "absoluteVisitsInSla": "1"
  }
}

modelOutput contains the itinerary for Carl’s shift with Visit A and Visit B.

In this example, Carl’s shift begins at 09:00. There are 2 visits, Visit A and Visit B, that need to be scheduled. Visit B has a latestSlaEndTime of 2027-02-01T13:00:00Z, which means that it must be completed by 13:00.

In order to accomplish that, Visit B needs to be handled first, otherwise it won’t be possible for Carl to be in the SLA for Visit B. Luckily, Visit A has more freedom and no SLA defined, so it can be scheduled after Visit B.

Next

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

  • Learn more about field service routing from our YouTube playlist.

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