Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
  • Platform
Try models
  • Field Service Routing
  • Getting started: Hello world

Field Service Routing

    • Introduction
    • Getting started: Hello world
    • User guide
      • Terms
      • Planning AI concepts
      • Constraints
      • Understanding the API
      • Planning window
      • Model configuration
      • Configuration overrides
      • Time zones and daylight-saving time (DST)
      • Routing with Timefold’s maps service
      • Validation
      • Model response
      • Key performance indicators (KPIs)
      • Metrics and optimization goals
    • Vehicle resource constraints
      • Shift hours and overtime
      • Lunch breaks and personal appointments
      • Fairness
      • Route optimization
      • Technician coverage area
      • Technician costs
      • Technician ratings
    • Visit service constraints
      • Time windows and opening hours
      • Skills
      • Visit dependencies
      • Visit requirements
      • Multi-vehicle visits
      • Movable visits and multi-day schedules
      • Priority visits and optional visits
      • Visit service level agreement (SLA)
    • Recommendations
      • Visit time window recommendations
      • Visit group time window recommendations
    • 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
    • Real-time planning (preview)
      • Real-time planning: extended visit (preview)
      • Real-time planning: reassignment (preview)
      • Real-time planning: emergency visit (preview)
      • Real-time planning: no show (Preview)
      • Real-time planning: technician ill (Preview)
      • Real-time planning: pinning visits (preview)
    • Scenarios
      • Long-running visits
    • Changelog
    • Upgrade to the latest version
    • Feature requests

Getting started: Hello world

The Field Service Routing model assigns customer visits to vehicles (and the technicians in those vehicles) with the goal of increasing the number of scheduled visits technicians can make by minimizing the amount of time they spend traveling and waiting between visits.

This guide introduces Timefold’s Field Service Routing model and walks you through the steps to use Timefold Platform to create an optimized field service routing solution.

To follow the steps in this guide, you need an active Timefold Platform account.

Request a trial
  1. Navigate to https://app.timefold.ai.

  2. Click Log in.

  3. Click Sign up.

    Either enter the email address and password you want to register with and click continue or select one of the federated log-in options and follow the prompts.

  4. Verify your email address.

  5. Click Request a trial.

A member of our team will contact you to arrange a trial.

The steps in this guide can be completed in under 10 minutes:

  1. Create a problem dataset

  2. Post the dataset

  3. Request the solution

This hello world example uses an example with 1 vehicle and 1 customer visit to demonstrate the process of requesting and retrieving a solution from Timefold’s Field Service Routing model.

At the end of this guide, you will have a solution for the field service routing hello world problem.

getting started

This hello world uses the POST and GET methods and the API endpoint: https://app.timefold.ai/api/models/field-service-routing/v1/route-plans/

1. Create a problem dataset

A dataset for the Field Service Routing model must include information about your customer visits and your vehicles' availability.

The following is an example field service routing input dataset:

{
  "modelInput": {
    "vehicles": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann-2027-02-01",
            "startLocation": [33.68786, -84.18487],
            "minStartTime": "2027-02-01T09:00:00Z"
          }
        ]
      }
    ],
    "visits": [
      {
        "id": "Visit A",
        "location": [33.77301, -84.43838],
        "serviceDuration": "PT1H30M"
      }
    ]
  }
}
Copy this example dataset into a file called sample.json to use in this hello world example.

The modelInput object of the dataset contains the data to be optimized.

At a minimum, modelInput must include vehicles and visits:

1.1. Vehicles

In this example, there is 1 vehicle. vehicles includes an id and shifts.

  • id is a unique identifier that identifies the vehicle. In this case, the id has the value "Ann" to identify this as Ann’s vehicle.

  • shifts represents a period of time the vehicle and its crew is working, typically a single day shift, for example, February 1st, 2027 from 09:00 to 17:00. A vehicle can contain multiple shifts.

{
  "vehicles": [
    {
      "id": "Ann",
      "shifts": [
        {
          "id": "Ann-2027-02-01",
          "startLocation": [33.68786, -84.18487],
          "minStartTime": "2027-02-01T09:00:00Z"
        }
      ]
    }
  ]
}

shifts includes id, startLocation, and minStartTime.

  • id is a unique identifier that identifies a single shift worked for this vehicle.

  • startLocation provides Ann vehicle’s location at the start of the shift. This is the location Ann travels from when she leaves for the first visit.

  • minStartTime sets the earliest time Ann can start her shift in ISO 8601 date and time format.

Learn about additional options that can be included for vehicles in the Vehicle resource constraints guides.

1.2. Visits

In this example, there is 1 customer visit. visits includes an id, location, and serviceDuration.

{
  "visits": [
    {
      "id": "Visit A",
      "location": [33.77301, -84.43838],
      "serviceDuration": "PT1H30M"
    }
  ]
}
  • id is a unique identifier that identifies the visit.

  • location provides the location of the customer visit.

  • serviceDuration is the estimated duration of the visit in ISO 8601 duration format. The value "PT1H30M" indicates the estimated duration is 1 hour and 30 minutes.

Learn about additional options that can be included for customer visits in the Visit service constraints guides.

When the dataset is posted to Timefold, Timefold will attempt to assign vehicles to customer visits, while considering the constraints of the domain.

2. Post the dataset

You have two options to post the dataset.

  1. Post the dataset in the Timefold Platform UI

  2. Post the dataset to the Timefold API

2.1. Post the dataset in the Timefold Platform UI

Typically, you post the dataset to the API. However, for testing purposes, you can upload your sample.json file directly in the Timefold Platform UI:

  1. Log into the Timefold Platform dashboard: https://app.timefold.ai

  2. Select the Field Service Routing tile.

  3. Click New dataset.

  4. Select Custom and click Next

  5. Upload the sample.json file you saved earlier.

  6. Click Next, then click Run.

2.2. Post the dataset to the Timefold API

You need an API key to access the API.

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 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.

POST the dataset contained in the sample.json file for solving to the API endpoint: https://app.timefold.ai/api/models/field-service-routing/v1/route-plans/

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]

The dataset will be validated. If the dataset is valid you will receive a response similar to:

{
  "id": "ID",
  "parentId": null,
  "originId": "ID",
  "name": "Dataset-2025-09-16T11:25:04.444347387Z",
  "submitDateTime": "2025-09-16T11:25:04.444347387Z",
  "startDateTime": null,
  "activeDateTime": null,
  "completeDateTime": null,
  "shutdownDateTime": null,
  "solverStatus": "SOLVING_SCHEDULED",
  "score": null,
  "tags": [
    "system.type:from-request",
    "system.profile:default"
  ],
  "validationResult": null
}

The output includes an ID that has been assigned to the dataset. You’ll use this ID to retrieve the solution for your dataset.

solverStatus confirms the dataset has been scheduled for solving.

3. Request the solution

Append the <ID> from the output you received to the endpoint https://app.timefold.ai/api/models/field-service-routing/v1/route-plans/ and create a GET request to retrieve the solution:

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": "Dataset-2025-09-16T11:25:04.444347387Z",
    "submitDateTime": "2025-09-16T11:25:04.444347387Z",
    "startDateTime": "2025-09-16T11:25:18.783918315Z",
    "activeDateTime": "2025-09-16T11:25:18.825755733Z",
    "completeDateTime": "2025-09-16T11:25:19.859110713Z",
    "shutdownDateTime": "2025-09-16T11:25:20.190298543Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-3569soft",
    "tags": [
      "system.type:from-request",
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  },
  "modelOutput": {
    "vehicles": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann-2027-02-01",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "Visit A",
                "kind": "VISIT",
                "arrivalTime": "2027-02-01T09:29:57Z",
                "startServiceTime": "2027-02-01T09:29:57Z",
                "departureTime": "2027-02-01T10:59:57Z",
                "effectiveServiceDuration": "PT1H30M",
                "travelTimeFromPreviousStandstill": "PT29M57S",
                "travelDistanceMetersFromPreviousStandstill": 31493,
                "minStartTravelTime": "2027-02-01T00:00:00Z"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT59M29S",
              "travelTimeFromStartLocationToFirstVisit": "PT29M57S",
              "travelTimeBetweenVisits": "PT0S",
              "travelTimeFromLastVisitToEndLocation": "PT29M32S",
              "totalTravelDistanceMeters": 65477,
              "travelDistanceFromStartLocationToFirstVisitMeters": 31493,
              "travelDistanceBetweenVisitsMeters": 0,
              "travelDistanceFromLastVisitToEndLocationMeters": 33984,
              "endLocationArrivalTime": "2027-02-01T11:29:29Z"
            }
          }
        ]
      }
    ],
    "unassignedVisits": []
  },
  "inputMetrics": {
    "visits": 1,
    "visitGroups": 0,
    "vehicles": 1,
    "mandatoryVisits": 1,
    "optionalVisits": 0,
    "vehicleShifts": 1,
    "visitsWithSla": 0
  },
  "kpis": {
    "totalTravelTime": "PT59M29S",
    "travelTimeFromStartLocationToFirstVisit": "PT29M57S",
    "travelTimeBetweenVisits": "PT0S",
    "travelTimeFromLastVisitToEndLocation": "PT29M32S",
    "totalTravelDistanceMeters": 65477,
    "travelDistanceFromStartLocationToFirstVisitMeters": 31493,
    "travelDistanceBetweenVisitsMeters": 0,
    "travelDistanceFromLastVisitToEndLocationMeters": 33984,
    "totalUnassignedVisits": 0,
    "totalAssignedVisits": 1,
    "assignedMandatoryVisits": 1,
    "assignedOptionalVisits": 0,
    "totalActivatedVehicles": 1,
    "workingTimeFairnessPercentage": 100
  },
  "run": {
    "id": "2f2c5465-1e3f-46d6-8ec5-b6b56b595742",
    "parentId": null,
    "originId": "2f2c5465-1e3f-46d6-8ec5-b6b56b595742",
    "name": "Dataset-2025-09-16T11:25:04.444347387Z",
    "submitDateTime": "2025-09-16T11:25:04.444347387Z",
    "startDateTime": "2025-09-16T11:25:18.783918315Z",
    "activeDateTime": "2025-09-16T11:25:18.825755733Z",
    "completeDateTime": "2025-09-16T11:25:19.859110713Z",
    "shutdownDateTime": "2025-09-16T11:25:20.190298543Z",
    "solverStatus": "SOLVING_COMPLETED",
    "score": "0hard/0medium/-3569soft",
    "tags": [
      "system.type:from-request",
      "system.profile:default"
    ],
    "validationResult": {
      "summary": "OK"
    }
  }
}

The output shows the solverStatus is SOLVING_COMPLETED.

modelOutput contains the solution for the dataset.

{
  "modelOutput": {
    "vehicles": [
      {
        "id": "Ann",
        "shifts": [
          {
            "id": "Ann-2027-02-01",
            "startTime": "2027-02-01T09:00:00Z",
            "itinerary": [
              {
                "id": "Visit A",
                "kind": "VISIT",
                "arrivalTime": "2027-02-01T09:29:57Z",
                "startServiceTime": "2027-02-01T09:29:57Z",
                "departureTime": "2027-02-01T10:59:57Z",
                "effectiveServiceDuration": "PT1H30M",
                "travelTimeFromPreviousStandstill": "PT29M57S",
                "travelDistanceMetersFromPreviousStandstill": 31493,
                "minStartTravelTime": "2027-02-01T00:00:00Z"
              }
            ],
            "metrics": {
              "totalTravelTime": "PT59M29S",
              "travelTimeFromStartLocationToFirstVisit": "PT29M57S",
              "travelTimeBetweenVisits": "PT0S",
              "travelTimeFromLastVisitToEndLocation": "PT29M32S",
              "totalTravelDistanceMeters": 65477,
              "travelDistanceFromStartLocationToFirstVisitMeters": 31493,
              "travelDistanceBetweenVisitsMeters": 0,
              "travelDistanceFromLastVisitToEndLocationMeters": 33984,
              "endLocationArrivalTime": "2027-02-01T11:29:29Z"
            }
          }
        ]
      }
    ]
  }
}

In this solution Ann has been assigned to Visit A. She leaves her start location at 09:00 and her arrivesTime at the visit is 09:29. The service takes 90 minutes, and Ann departuretime is 10:59. Ann arrives at her endLocationArrivalTime at 11:29.

getting started

Next

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

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

  • Configure a webhook.

  • Refer to the User guide or learn about Vehicle resource constraints and Visit service constraints.

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