Introduction

API Documentation

This document provides a detailed description of the different features and capabilities of the API for solving routing and scheduling optimization problems.

Table of Contents:

Welcome to our Routing and Scheduling API user manual!

Our API is engineered to enhance route planning and scheduling for vehicle fleets, addressing key constraints such as service time windows, capacity limits, and traffic conditions. By leveraging our API, businesses can significantly improve delivery efficiency, reduce operational costs, and save valuable time through optimized routing and scheduling solutions.

At its core, the API solves the Vehicle Routing Problem (VRP) with pickup and delivery. This problem involves calculating the most efficient routes for a fleet to visit multiple locations to perform pickup and delivery tasks while meeting constraints like time windows, vehicle capacity, and availability.

Additionally, our API supports dynamic schedule adjustments or re-optimization. If you need to modify an existing schedule—whether due to new orders, cancellations, or other changes—you can provide an updated picture of your schedule by specifying the job statuses and vehicle locations. The API will then re-optimize the schedule to reflect these changes, ensuring continuous efficiency in your operations.

For information on how to quickly get ready and start using the API, see Get Started. Several quick tutorials are also provided in the “Tutorials” section.

 

Get Started

The API offers two key methods for managing routing and scheduling optimization:

  1. Optimization POST – Use this method to submit a routing and scheduling optimization problem. After submitting a POST method, you will receive a unique reference ID.
  2. Optimization GET – Use this method to retrieve the status of a submitted problem using the unique reference ID obtained from the POST method. If the optimization solution is ready, you can get the solution of the optimization problem.

Optimization POST Method

POST: https://iq.aiqwhite.ddsdeploytest.com/raas/optimization

Use this method to submit your routing and scheduling optimization problem to the API. Once an optimization POST request is successfully submitted, the API will return a unique reference ID in the acknowledgement response. Use this unique ID to retrieve the actual solution using the Optimization GET Method (see next section).

An example for submitting an optimization problem using the POST method:

curl --location https://iq.aiqwhite.ddsdeploytest.com/raas/optimization
        --request POST --header 'Content-Type: application/json' 
        --header 'Authorization: Bearer {your_access_token}' 
        --data-raw '{problem}'

In the above example, you need to replace {problem} with your input problem (i.e. input JSON payload) to be solved by the API. The schema for the input problem is defined in the “Problem” section.

After submitting the POST method, you will get a response message with the following format:

Response Schema for the POST method:

{ "id": "string",
 "message": "string", 
"status": "string", 
"error" : "string"
 }

If the submission is successful, the status will be “202,” with the message reading “accepted” and the id representing the unique reference number for the asynchronous operation. This ID is used to track the status of the operation and retrieve results later. If there is an error, the status will indicate an error code, the id will be zero or empty, the message will be “failure” and the error will describe the error. For more details, please refer to the POST status codes below.

POST Status Codes

Response Code Description Additional Notes
202 The request was accepted for processing. A reference ID is returned by which you can use the GET request to get the solution once it is ready.
400 Input validation failed (Bad Request). There is a missing or an invalid parameter or a parameter with an invalid value type is added to the request. Please correct your input data, and resubmit your request.
403 Unauthorized request. This error occurs when the authentication process fails.
404 Requested path not found. This error occurs when an incorrect path address is used.
429 Too many requests. QPM (Query per Minute) reached or API request count quota reached. In other words, the user has sent too many requests in a minute.
500 Internal Service error. There was an internal issue with our API. You can reach out to [support@ddswireless.com] for an explanation.

Optimization GET Method

GET: https://iq.aiqwhite.ddsdeploytest.com/raas/optimization/{id}

Use this method to retrieve the optimized solution for the optimization tasks created using the Optimization POST Method. For this purpose, you need to specify the reference ID received from the POST method.

An example for getting the output response of the API using the GET method (assuming that the id returned by the POST method is 123305):

curl --location --request GET https://iq.aiqwhite.ddsdeploytest.com/raas/optimization/123305
        --header 'Authorization: Bearer {your_access_token}'

Response Schema for the GET method:

{ "status": "string", 
 "message": "string", 
 "error": "string", 
 "solution": { 
        "statistics": {}, 
        "routes": [], 
         "unassigned": []
   }
 }

If the solution is ready, statistics, routes, and unassigned will be populated based on the obtained solution. Otherwise, similar to the POST method, status, message, and error will show the status or error. The schema for the output solution is defined in the “Solution” section.

GET Status Codes

Response Code Description Additional Notes
200 The request has succeeded. Normal success case. The solution of the problem is ready and it is returned via statistics, routes, unassigned.
202 The request was accepted but it is not completed yet (pending status) Solution is not ready yet. You need to check later.
400 Could not process the request (Bad Request). A feasible solution could not be generated for the given set of locations or parameter configuration.
401 Unauthorized request. The request requires user authentication. The server did not receive the proper credentials.
500 Internal Service error. There was an internal issue with our API. You can reach out to [support@ddswireless.com] for an explanation. statistics, routes, and unassigned will be empty.

To solve a routing and scheduling optimization problem for a fleet of vehicles, follow these steps:

  1. Define the Problem: Begin by outlining your problem using the format specified in the “Problem” section.
  2. Submit the Problem: Use the POST method, as described in the “Get Started” section, to send your problem to the API.
  3. Retrieve the Solution: Access the solution to your optimization problem by using the GET method detailed in the “Get Started” section. The format of the solution is outlined in the “Solution” section.

To learn more about different terminologies used in the API, see the “Glossary” section. To see a list of frequently asked questions, see the “FAQ” section.

 

Problem

The Problem entity represents a routing and scheduling problem which can represent a Pickup and Delivery Problem (PDP). As shown in the following figure, it consists of four main components: fleet, jobs, objective, and configuration. Among these four components, fleet and jobs, are mandatory whereas objective and configuration are optional.

Note: To specify a location or address in the API, use the WGS84 Geo-coordinates with at least 5 decimal places for accuracy.
For example, if you have an address like “1600 Amphitheatre Parkway, Mountain View, CA,” its corresponding Geo-coordinate would be latitude 37.423021 and longitude -122.083739. Therefore, you specify it as either:

"location":{"lat":37.423021, "lng":-122.083739}  or [37.423021, -122.083739].

Note: The API uses the ISO 8601 format for timestamps, including time zone information, to define local time for the area for which you require optimized routing and scheduling.

Example:

2024-07-31T14:45:30-08:00 represents July 31, 2024, at 2:45:30 PM PST, which is 8 hours behind Coordinated Universal Time (UTC).

Also, in the input API payload, you must use the same local time zone consistently. If multiple time zones are detected, the API will return an error. The times for scheduled stops in the output response will be provided in the same format as specified in the input API payload.

Note: Ensure that no confidential or personal information is included in the data sent to the API. For example, avoid using real-life identifiers, such as vehicle license plate numbers, as the vehicle ID or job/task IDs.

We will now provide a detailed description of each of these components:

Fleet: it specifies a list of vehicles along with their associated information, such as shift schedules, start and end locations, breaks, capacities, and skills.

  • For each vehicle, you can define one or multiple shift schedules by specifying the start and end times, as well as the corresponding locations. To identify these locations, you’ll need to provide their Geo-coordinates, which consist of latitude and longitude.
  • Each vehicle may have one or more breaks. For each break, you can define a time window during which it can be taken, as well as the location and duration of the break.
  • For each vehicle, you can define one or more capacity types along with the available units for each type. Vehicle capacity can be represented using multidimensional units of measure, such as volume, mass, or size.
  • For each vehicle, you can specify one or more skills that enable it to perform certain jobs. For example, you might assign “welding machine” and “oxygen tank” as skills for one vehicle, and “lift” as a skill for another vehicle. If a job requires a lift, only the vehicle equipped with this skill will be able to serve it.
  • You can also set limits for each vehicle, such as the maximum number of stops and the maximum travel distance (in miles).

Jobs: it specifies a list of jobs to be served by the vehicles specified in the fleet Each job can include a series of tasks, which may be pickups, deliveries, or a combination of both. For each task, you can define various attributes such as their location, time windows, duration, capacity requirements, and necessary skills.

  • To specify the location of a task, you need to provide its Geo-coordinate, which includes latitude and longitude.
  • If you set a service time window for a pickup or delivery task, the optimizer will schedule the task to occur within that time frame. In other words, the estimated time of arrival (ETA) for the task in the API response will fall within the specified time window. If the optimizer cannot find a suitable ETA for a task within its specified time window, the job or task will remain unassigned. For tasks that are flexible or not time-sensitive, you can specify a broader time window, with a maximum span of 24 hours. The API uses the ISO timestamps as described earlier.
  • You can specify a duration (in seconds) for each task. This is the time spent at a given location.
  • You can specify the capacity requirements for each task using multidimensional units of measure, such as volume, mass, or size. Additionally, you can create custom names for your capacity types, such as “seat,” “container,” “pallet,” or “bin.” For each capacity type, you can also define the exact amount needed to perform the task.
  • You can also define a list of required skills for each task. Only vehicles with a matching skill set will be eligible to perform that task. For example, if you specify “welding machine” and “oxygen tank” as the required skills for a job, only vehicles equipped with these skills will be selected to complete the job.

Objective: it determines the optimization objective or strategy. Currently, the following three objectives are supported by the API:

  • Minimize Total Travel Time: This is the default optimization strategy, and it tries to minimize the total travel time of the fleet while completing the specified jobs.
  • Minimize Number of Routes: This optimization strategy focuses on reducing the number of vehicles needed to complete the specified jobs. However, this may lead to increased total travel time for the fleet or greater workload on individual vehicles as a trade-off.
  • Balance Workload among Routes: This optimization strategy aims to evenly distribute the workload among all vehicles in the fleet. However, this balance may result in increased total travel time for the fleet.

Configuration: through configuration, you can adjust API settings or modify default options. For example, you can specify whether to include a summary of optimization statistics (such as total travel time and distance) or a list of unassigned jobs in the API response.

Input Request Schema:

The schema of the input request to solve a route optimization problem is as follows:

 "problem": {
      "fleet": required 
      "jobs": required
        [
          "pickups": [...] 
          "deliveries": [...]
        ]
      "objective": optional
      "configuration": optional
    }

To submit a problem using the API, this request must be included in the POST method as described in the “Get Started” section.

In a route optimization problem, a fleet of vehicles aims to serve a set of jobs efficiently. The above template allows users to define their fleet and their jobs. Each job can consist of a number of tasks as follows:

  1. Pickup tasks only: These tasks involve picking up items along the route and delivering them to the route’s end location.
  2. Delivery tasks only: These tasks require delivering items that are loaded onto the vehicle at the beginning of the route.
  3. Pickup and delivery (P/D) tasks together: These tasks combine both pickup and delivery actions. They involve picking up something at one location and bringing it to another location.

Additionally:

  1. If only the “pickups” object is provided for a job, it’s considered a pickup-only job.

  2. If only the “deliveries” object is provided for a job, it’s considered a delivery-only job.

  3. When both “pickups” and “deliveries” are provided for a job, it’s categorized as a pickup and delivery job.

Note:

  1. At least one job and one vehicle must be provided for the problem.
  2. The API does not support jobs with multiple pickups AND multiple deliveries. In other words, if you want to define a “pickup and delivery” job, the “pickups” object of the job must contain only one pickup task, and the “deliveries” object of the job must contain only one delivery task.
  3. The API does not support jobs with no pickups AND no deliveries.
  4. If you only specify “pickups” for a job, that job is classified as a pickup-anchored job.
  5. If you only specify “deliveries” for a job, that job is classified as a delivery-anchored job.
  6. If a job has both a pickup and delivery, the anchor is the one that defines a service window (see below).
  7. If a job has both a pickup and delivery AND both tasks have service windows, the job is considered as a pickup-anchored job.

For each task, various attributes and constraints can be defined, such as capacity demands, service time windows, and required skills. Visit tasks, where we need to visit specific locations to perform tasks (e.g. repairs), can indeed be seen as a specialized form of delivery tasks (with or without capacity requirements). Tasks are assigned to vehicles whose capacities or skill sets match the task’s requirements. For example, if a task requires a lift or ladder, only vehicles equipped with a lift or ladder will be used to perform that task.

Now, let’s delve into the details of each element in the input API payload.

Input Payload

The input payload of the API is a JSON document whose main element (key) is “problem”. It is defined as follows:

“problem” [required]
This element defines the specific routing and scheduling optimization problem that the API will solve. It includes all required and optional parameters and constraints to generate an optimized solution. It consists of the following attributes:

1. “fleet” [required]
This element provides comprehensive information about the vehicle fleet available for task assignment. It is an array of fleet objects. Each fleet object consists of the following attributes:

  • “id” [required]: A unique identifier (integer) for each vehicle in the fleet. This ID is crucial for tracking and managing the vehicles during the routing process.
  • “shifts” [optional]: An array of shift objects, each containing detailed information about the vehicle’s operational periods, including start and end times and locations. Shifts also encompass break periods, which are essential for ensuring compliance with labor regulations and operational efficiency. Multiple shift objects can be defined but they must be disjoint. Elements in each shift object:
    • “start” [optional]: Defines the start time and location for the vehicle’s shift. It has the following keys:
      • “time” [optional]: The start time of the shift. If not provided, the default is set to 00:00:00 (midnight) of the current date.
      • “location” [optional]: The starting location for the shift. You can specify it as an array such as [A,B] in which A represents the latitude and B represents the longitude. Alternatively, you can specify it as {“lat”: A, “lng”: B}.
    • “end”: Defines the end time and location for the vehicle’s shift. It has the following keys:
      • “time” [optional]: The end time of the shift. If not provided, the default is set to 23:59:00 of the current date.
      • “location” [optional]: The ending location for the shift. You can specify it similar to the starting location.
  • “breaks” [optional]: An array of break objects, each specifying a break period during the shift. Breaks are necessary for legal compliance and driver well-being. Each break object consists of the following keys:
    • “serviceWindow” [required if breaks are used]: Specifies the time period during which the break can occur.
    • “duration” [required if breaks are used]: An integer value representing the duration of the break in seconds.
    • “location” [optional]: The location where the break will take place. The location of the break is optional. If the location is omitted the break is ‘floating’ which means that it can be taken anywhere at the convenience of the driver.

Example:

"shifts": [{
  "start": {
    "time": "2020-07-04T09:00:00-08:00",
    "location": {"lat": 52.46642, "lng": 13.28124}
  },
  "end": {
    "time": "2020-07-04T18:00:00-08:00",
    "location": [54.21981, 14.01237]
  },
  "breaks": [
    {
      "serviceWindow": ["2020-07-04T12:00:05-08:00","2020-07-04T14:05:05-08:00"],
      "duration": 1200,
      "location": {"lat": 53.70645, "lng": 12.34156}
    },
    {
      "serviceWindow": ["2020-07-04T16:00:00-08:00","2020-07-04T16:45:00-08:00"],
      "duration": 600,
      "location": {"lat": 51.46642, "lng": 12.28124}
    }
    ]
  }]
  • “capacities”: [required] an array of capacity objects. Each capacity object is defined with the following keys:
    • “name”: [required] a string specifying the name of the capacity type (e.g. “wheelchair”, “box”, ”seat”, “bin”)
    • “units”: [required] an integer number specifying the available units of the capacity type
    • “lifo”: [optional] a binary flag that indicates whether the LIFO (Last In, First Out) constraint is applied to this capacity type. The default value is False. If LIFO is set to True for a capacity type, items of this type will be unloaded first during a delivery or drop-off task.

Example:

    "capacities": [
        {
        "name": "seat",
        "units": 2,
        "lifo" : true
        },
        {
        "name": "package",
        "units": 20,
        "lifo" : false
        }        
      ]
  • “skills”: [optional] a list of vehicle skills or equipment, each represented by an arbitrary string specific to your application. This allows you to customize the capabilities of your vehicles to match the requirements of the jobs they need to serve.

Example:

"skills": ["lift","fridge","oxygen tank"]
  • “limits”: [optional] specifies constraints applied to the vehicle
    • “maxDistance”: [optional] a float number specifying the maximum distance limitation for the vehicle in miles
    • “maxStops”: [optional] an integer defining maximum number of stops (pickup or delivery tasks) the vehicle can serve in one shift
    • “lifoDepth”: [optional] an integer defining the LIFO depth of the vehicle

Example:

  "limits": {
    "lifoDepth" : 1,
    "maxDistance": 3000,
    "maxStops" : 20
  }
  • “lastKnownLocation”: [optional, used for re-optimization only] Specifies the last known location of the vehicle at the specified time. This information is crucial for re-optimizing an ongoing route to account for new changes, such as broken vehicles, late jobs, new jobs, or canceled jobs. The API uses this data to re-optimize the plan efficiently. Therefore, when re-optimizing an existing schedule, you need to provide the location of all involved vehicles.

Example:

"lastKnownLocation": {
      "location": {"lat":53.45612, "lng":12.65421},
      "time" : "2020-07-04T12:00:05-08:00"
      }

2. “jobs”: an array of job objects [at least one job is required]. Each job object consists of the following keys:

    • “id” : [required] a unique identifier (integer) for the job
    • “pickups”: [optional] an array of task objects, each defining a pickup task
    • “deliveries”: [optional] an array of task objects, each defining a delivery or drop-off task

Note:

      1. The API does not support jobs with multiple pickups AND multiple deliveries.
      2. The API does not support jobs with no pickups AND no deliveries.
      3. If you only specify “pickups” for a job, that job is classified as a pickup-anchored job.
      4. If you only specify “deliveries” for a job, that job is classified as a delivery-anchored job.
      5. If a job has both a pickup and delivery, the anchor is the one that defines a service window (see below).
      6. If a job has both a pickup and delivery AND both tasks have service windows, the job is considered as a pickup-anchored job.

Each Task Object consists of the following attributes (keys):

      • “id”: [required] a unique identifier (integer) for the task
      • “location”: [required] it is a key-value object that specifies the Geo-coordinates (latitude and longitude) of the location where the task must be performed. You can specify it as an array such as [A,B] in which A represents the latitude and B represents the longitude. Alternatively, you can specify it as {“lat”: A,”lng”: B}.

Example:

"location": {"lat": 52.46642, "lng": 13.28124}

OR

 "location": [52.46642, 13.28124]
      • “serviceWindows”: [required] [optional or required depending on the use case, see the definition of pickups and deliveries above] It specifies the service time window for performing the task. The service window is an array with this format: [A,B] where A and B are the start and end times of the service time window. The API will attempt to produce an ETA within the specified service window for that task. If this is not possible, the task will be listed as unassigned. In other words, times “A” and “B” define the earliest and latest times by which a task must be completed by a vehicle. For tasks that are flexible or not time-sensitive, use an arbitrarily large window (max 24 hours) to give the API more flexibility in scheduling other tasks. The current version of the API supports only one service window for each task.

Example:

"serviceWindows": ["2024-08-30T09:00:00-08:00",
"2024-08-30T21:00:00-08:00"]
      • “duration”: [required] It specifies the duration of the task in seconds. It can be either an integer or a key-value object with the following keys:
        • “fixed”: the fixed duration (seconds) for the task (e.g. for finding parking, lowering the lift, etc.)
        • “service”: the service duration (seconds) for doing the task

Example:

"duration": 1950
   OR
"duration": {"fixed":150, "service": 1800}
      • “demand”: [required] An array of the required capacity demands for the task. The structure of each demand object is identical to that of the capacity object in the fleet entity defined above. Each capacity item consists of a name (string) and its available units (integer). The specified names must match those defined in the capacity object of the fleet entity. For example, if a job requires capacity for two seats and 20 packages, you would define the demand as follows:

Example:

"demand": [
    {
    "name": "seat",
    "units": 2,
    },
    {
    "name": "package",
    "units": 20,
    }        
  ]
      • skills: [optional] an array of skills or equipment required to perform the task, each represented by an arbitrary string specific to your application. Only vehicles whose skills set match the skill set of the task will be considered for performing the task. These skills are matched to the skills defined in the fleet entity defined above.

Example:

"skills": ["lift", "ladder", "welding machine"]
      • “status”: [optional, used for re-optimization only] it is a string that specifies the status of the task which can be one of these options: “pending”, “in_progress”, “performed”. This information is crucial for re-optimizing an ongoing route to account for new changes, such as broken vehicles, late jobs, new jobs, or canceled jobs. The API uses this data to re-optimize the plan efficiently. Therefore, when re-optimizing an existing schedule, you need to specify the value of this attribute. For new tasks or tasks that are not performed yet, set it to “pending”. If the task is already performed set it to “performed”. If the vehicle has already arrived at the location to do the task, and the task is in progress, set it to “in_progress”. The default value is “pending”.

Example:

"status": "pending"
      • “vehicleId”: [optional, used for re-optimization only], it specifies the assigned vehicle ID (integer) for the already-scheduled tasks. This information is crucial for re-optimizing an ongoing route to account for new changes, such as broken vehicles, late jobs, new jobs, or canceled jobs. The API uses this data to re-optimize the plan efficiently. Therefore, when re-optimizing an existing schedule, you need to specify the value of this attribute. The default value is zero. For new tasks, set it to zero. For existing tasks that are already assigned to a vehicle, set this attribute to the assigned vehicle ID.

Example:

"vehicleID": 12
      • “eta”: [optional, used for re-optimization only], it specifies the current ETA (estimated time of arrival) for the already-scheduled jobs. This information is crucial for re-optimizing an ongoing route to account for new changes, such as broken vehicles, late jobs, new jobs, or canceled jobs. The API uses this data to re-optimize the plan efficiently. Therefore, when re-optimizing an existing schedule, you need to specify the value of this attribute. The default value is 0. For the new or performed tasks, set it to 0 but for the existing pending tasks, set it to the existing ETA.

Example:

"eta": "2021-07-04T12:13:00-08:00"

3. “objective”: [optional] An integer specifying the optimization objective (strategy): (default = 1)

    • 1: Minimize Total Travel Distance [default]
    • 2: Minimize Number of Routes
    • 3: Balance Workload Among Routes

Example:

"objective": 1

4. “configuration”: [optional] it can be used to specify some additional settings or configurations:

      • “polyLineType”: [optional] it specifies the type of the output polyline that can be returned for each scheduled route. It is a string from these options: “none”, “plain”, “encoded”. If “none”is selected, no polylines will be included in the output API response. If “plain” is specified, an ordered list of intersections that we need to travel between each pair of consecutive stops will be returned as the polyline. If “encoded” is used, the polyline is compressed into a string format that users can provide to third-party navigation APIs, such as Google Maps, to obtain turn-by-turn instructions. The default value is “none”.
      • “unassignedTasks”: [optional] it is a flag that determines whether the unassigned tasks must be included in the output response or not. Default is False. If, for any reason, the API cannot assign a task to a route, it will list it as unassigned.
      • “statistics”: [optional] it is a flag that determines whether the optimization statistics must be included in the output solution or not. Default is True.
      • “units”: [optional] it specifies the units for the output statistics as well as the units for the fleet limits. It can be either “metric” or “imperial”. The default value is “metric”.

Example:

"configuration": 
{
      "polylineType": "plain",
      "unassignedTasks": false,
      "statistics": true
}

To see various examples of a Problem and learn how to use the API in different use cases (e.g. re-optimization), see Tutorials.

 

Solution

As explained in the “Get Started” section, once you submit a problem via the POST method, you will receive a unique reference ID. You can use this reference ID with the GET method to retrieve the status of the submitted problem. If the optimization solution is ready, you can access it in the “solution” entity. As shown in the following figure, the “solution” entity is composed of three main parts:

  • “statistics”:
    • It provides key metrics that summarize the overall solution across all routes. Metrics like total travel distance help assess the efficiency and quality of the optimization. These insights enable you to evaluate the performance and effectiveness of the routing process.
  • “routes”:
    • It contains the optimized route for each vehicle, including specific stops and their estimated time of arrival (ETA). It may also include a polyline representing the vehicle’s path, aiding in visualizing and verifying the route.
  • “unassigned”:
    • It lists tasks that couldn’t be assigned to a route. It may also include reasons for their exclusion, offering insights into constraints or issues that affected the assignment process.

 

Output Solution Schema:

The template of the solution of the optimization problem provided in the output response of the API is as follows:

"solution": {
      "status" : integer
      "statistics": {},
      "routes": []
      "unassigned": [],
      }  

1.statistics”: it represents the solution of the route optimization problem which consists of the following attributes:

  • distance”:
    • totalDistance” : the total distance traveled by the entire fleet. This measurement includes the distance from each vehicle’s start location to its end location.
    • revenueDistance“: the total revenue distance traveled by the entire fleet. This measurement includes the distance from the first stop to the last stop for each vehicle. It does not include the distance from the vehicle’s start location to the first stop or the distance from the last stop to the vehicle’s end location.
  • vehicles”:
    • used”: The number of used vehicles in the solution to perform the scheduled jobs/tasks.
    • unused”: The number of unused vehicles
  • jobs”:
    • scheduledTasks”: The number of scheduled tasks
    • unassignedTasks”: The number of unassigned tasks
  • times”:
    • totalHours”: the total travel hours for the entire fleet. This measurement includes the time spent traveling from each vehicle’s start location to its end location.
    • revenueHours“: the total revenue hours traveled by the entire fleet. This measurement includes the time taken from the first stop to the last stop for each vehicle. It does not include the time spent traveling from the vehicle’s start location to the first stop or from the last stop to the vehicle’s end location.

Example:

"statistics": {
    "distance": {
        "totalDistance": 42,
        "revenueDistance": 25
    },
    "vehicles": {
        "used": 2,
        "unused": 0
    },
    "jobs": {
        "scheduledTasks": 3,
        "unassignedTasks": 0
    },
    "times": {
        "totalHours": 11.6,
        "revenueHours": 10.8
    }
}

2. “routes”: it provides an array of the scheduled route for each vehicle. Each scheduled route contains the following data:

  • vehicleId”: an integer that specifies the ID of the assigned vehicle
  • shifts: an array of shift objects. Note that the API supports multiple shifts for each vehicle. Each shift object consists of the following elements:
    • index”: the index of the shift (integer)
    • stops”: it provides an array of all stops to be performed by the vehicle on this shift. Each stop has the following properties:
      • ordinal”: The stop’s position within the vehicle schedule, represented by its index (integer).
      • jobId”: The job ID related to this stop (integer)
      • taskId”: The task ID related to this stop (integer)
      • type”: The type (string) of the task that must be performed at this stop (“pickup” or “delivery”)
      • location”: The Geo-coordinates of the location of the stop
      • eta”: The estimated time of arrival (ETA) for the stop (in the same time zone of the input payload)
      • timeToNext”: This is the driving time to the next stop. For example, if you drop-off a passenger at 9:00am and your next job is at 10:00, this stat tells you that the driving time from the current stop to the next stop is 20mins.
      • distanceToNext”: This is the driving distance to the next stop. Depending on the chosen units in the “configuration”, this can represent miles or meters.
      • waitTime”: the wait time tells you how long the driver should wait at the next stop if he starts driving now. In the above example, the wait time will be 40 minutes. So, the driver can decide when to leave the current stop.
      • polyline”: The polyline connecting the stop to its preceding stop. If “plain” polyline is specified in the “configuration”, the polyline is an ordered list of intersections that we need to travel between the preceding stop and the current stop. If “encoded” polyline is specified in the “configuration”, the plain polyline is encoded and returned as an encoded string.
      • break”: if the scheduled stop is for a break, it represents the ID of the break. Other stops don’t have this element. The API does not enforce that the breaks (or jobs) be listed in chronological order.

Example:

       "routes": [
            {
                "vehicleId": 1,
                "shifts": [
                    {
                        "index": 1,
                        "stops": [
                            {
                                "break": 1,
                                "start": "2023-10-01T10:00:00-08:00",
                                "end": "2023-10-01T10:15:00-08:00",
                                "timeToNext": 15,
                                "distanceToNext": 7.3,
                                "waitTime": 0,
                                "polyline": null,
                                "ordinal": 1
                            },
                            {
                                "jobId": 4,
                                "taskId": 5,
                                "type": "pickup",
                                "location": [
                                    50.70816,
                                    -120.37796
                                ],
                                "eta": "2023-10-01T10:30:00-08:00",
                                "timeToNext": 13,
                                "distanceToNext": 5.6,
                                "waitTime": 112,
                                "polyline": null,
                                "ordinal": 2
                            },
                            {
                                "jobId": 4,
                                "taskId": 6,
                                "type": "delivery",
                                "location": [
                                    50.66559,
                                    -120.36924
                                ],
                                "eta": "2023-10-01T12:45:00-08:00",
                                "timeToNext": 4,
                                "distanceToNext": 1.7,
                                "waitTime": 71,
                                "polyline": null,
                                "ordinal": 3
                            },
                            {
                                "break": 2,
                                "start": "2023-10-01T14:00:00-08:00",
                                "end": "2023-10-01T14:15:00-08:00",
                                "timeToNext": 7,
                                "distanceToNext": 3.2,
                                "waitTime": 217,
                                "polyline": null,
                                "ordinal": 4
                            }
                        ]
                    }
                ]
            },
            {
                "vehicleId": 2,
                "shifts": [
                    {
                        "index": 1,
                        "stops": [
                            {
                                "break": 1,
                                "start": "2023-10-01T11:00:00-08:00",
                                "end": "2023-10-01T11:15:00-08:00",
                                "timeToNext": 3,
                                "distanceToNext": 1.2,
                                "waitTime": 267,
                                "polyline": null,
                                "ordinal": 1
                            },
                            {
                                "jobId": 10,
                                "taskId": 11,
                                "type": "pickup",
                                "location": [
                                    50.65187,
                                    -120.40052
                                ],
                                "eta": "2023-10-01T15:45:00-08:00",
                                "timeToNext": 12,
                                "distanceToNext": 6.4,
                                "waitTime": 0,
                                "polyline": null,
                                "ordinal": 2
                            },
                            {
                                "jobId": 10,
                                "taskId": 12,
                                "type": "delivery",
                                "location": [
                                    50.69262,
                                    -120.35412
                                ],
                                "eta": "2023-10-01T16:22:00-08:00",
                                "timeToNext": 6,
                                "distanceToNext": 2.7,
                                "waitTime": 91,
                                "polyline": null,
                                "ordinal": 3
                            }
                        ]
                    }
                ]
            }
        ]

3. “unassigned”: It lists tasks which cannot be assigned due to specific constraints. Each item consists of a job id, a task id, and possible unassignment reasons (a code plus a description):

  • id”:
    • job”: the job ID (integer) of the unassigned task
    • task”: the ID (integer) of the unassigned task
  • reason”: an array of possible reasons for the unassigned tasks
    • code”: the code (integer) of the possible reason
    • description”: the description (string) of the possible reason

Example:

{
  "unassigned": [
    {
      "id": {
        "job": 2,
        "task": 1
      },
      "reason": [
        {
          "code": 2,
          "description": "Not enough capacity for this job"
        }
      ]
    },
    {
      "id": {
        "job": "31",
        "task": "2"
      },
      "reason": [
        {
          "code": 5,
          "description": "The service time of the job is out of the shift hours"
        }
      ]
    }
  ]
}

 

Glossary

Terms Definition
problem A routing and scheduling optimization problem to be solved by the API
solution The solution of the routing and scheduling optimization problem provided by the API
fleet A fleet specifies a list of vehicle types and their information
job A list of pickup, delivery, or pickup and delivery tasks that must be performed by a specific vehicle
task A task is part of a job and is to be performed at a specific location and time. The task could be a pickup, a delivery activity, or both.
break An attribute to define one or multiple break times for drivers at specific locations
demand As a task capacity requirement, demand is represented in multidimensional units of measure, such as volume, mass, and size. For example: “demand”: [1]
duration The amount of time used for performing a task or a break
shifts An object defining the vehicle schedule, their shift start and end times and locations and their potential breaks
pickup A job task for picking up something along the route and delivering it later in the tour
delivery A job task for delivering something loaded earlier in the tour
pickup and delivery A job for picking and delivering along the route. It is used when both pickup and delivery places are specified and a job can have multiple pickups and deliveries
skills A list of vehicle skills which is needed to serve jobs. For example, when a truck of a certain size or with a certain equipment is required. This attribute applies to both vehicles and tasks. Only vehicles with skills that match the requirements of certain tasks will be assigned to those tasks
service window It is a time window consisting of two times, an start time and an end time that define the earliest and latest times a task must be completed by a vehicle
start/end location The first/last location where the vehicle departs/arrives, such as a depot or garage
start/end time Start/end times can be used for for shifts, breaks, departure time, and the plan part for specifying the tasks times.
location The latitude and longitude of an address in WGS84 format.
re-optimization If you’ve already created a schedule using the API and begun executing it, but then new changes arise—such as new orders coming in or some orders being cancelled—you can update the status of your jobs and the current location of your vehicles. The API will then re-optimize the schedule to account for these changes.
ID A unique identifier for a job, task or vehicle
VRP Vehicle Routing Problem
CVRP Capacitated Vehicle Routing Problem
PDP Pickup and Delivery Problem
limits Constraints applied to a vehicle type
objective An optimization objective (strategy) to solve the routing and scheduling problem
statistics Represents the statistics of the optimized routes in the output solution
stop A stop specifies the list of activities performed at a specific time, at a specific place on a given route
unassigned jobs/tasks Jobs/tasks which cannot be assigned to any routes due to different reasons
ETA It is acronym for Estimated Time of Arrival. The API provides an ETA for all stops on a scheduled route in the output solution.
polyline A polyline is a series of connected line segments that represents a path or route on a map. Each line segment in a polyline is defined by its endpoints, and together they create a continuous path. In the API, each endpoint is defined by its Geo-coordinates (latitude, longitude).
encoded polyline An encoded polyline is a compact representation of a polyline used in mapping and routing applications. Instead of storing a series of coordinate pairs explicitly, an encoded polyline uses a string of characters to represent the polyline data efficiently. This encoding is commonly used in applications like Google Maps and other mapping services to reduce the amount of data that needs to be transmitted or stored. An example of an encoded polyline: _kv~uF|y~wGdkZ~gAx|]t@

In this section, you’ll find various examples demonstrating how to use the API for various scenarios. The API primarily supports two main use cases:

  1. Planning and Scheduling: Generates an optimized schedule for a fleet’s tours, considering constraints related to jobs and vehicles.
  2. Re-optimization: Modifies an existing or ongoing schedule to reflect changes such as new jobs or cancellations as well as broken vehicles.

Explore the examples provided to see how these use cases are implemented:

  • Example 1: Planning a simple pickup and delivery (drop-off) scenario
  • Example 2: A simple re-optimization scenario for adding new jobs to an existing schedule
  • Example 3: Re-optimization with cancelled jobs
  • Example 4: Re-optimization with broken vehicles

Note: The locations mentioned in the following examples are fictional and randomly generated, and do not correspond to real places.

Example 1: Planning a simple pickup and delivery scenario

In this example, our fleet consists of 2 vehicles and we have 3 pickup and delivery jobs that must be served by the two vehicles. Here are the details for each vehicle:

  • Vehicle 1:
    • Shift Details: The shift starts on 2024-10-01 at 8:00 AM PST from location (50.67293, -120.34195) and ends at 6:00 PM at the same location. Note that the time zone is PST, so the start time will be recorded as 2024-10-01T08:00:00-08:00, and the end time will be 2024-10-01T18:00:00-08:00.
    • Breaks: The vehicle has two breaks, each lasting 15 minutes:
      • First break: Between 10:00 AM and 10:30 AM at location (50.6531, -120.38393).
      • Second break: Between 2:00 PM and 2:30 PM at location (50.6531, -120.38393).
    • Capacity: 15 seats and 5 pieces of cargo.
    • Skills: Equipped with a lift and air conditioning.

    Vehicle 2:

    • Shift Details: The shift starts on 2024-10-01 at 8:00 AM PST from location (50.7117, -120.39286) and ends at 6:00 PM at location (50.67698, -120.32012).
    • Breaks: The vehicle has one 15-minute break:
      • Break: Between 11:00 AM and 11:30 AM at location (50.6531, -120.38393).
    • Capacity: 10 seats and 8 pieces of cargo.
    • Skills: Equipped with a lift only.

We also have three “pickup and delivery” jobs in Kamloops, BC, Canada. Here are the details of each job:

  • Job 1:
    • Pickup: Location (50.65391, -120.37365)
      • Service Window: 9:00 AM to 9:30 AM (the job is pickup-anchored, and the pickup must be performed within this time window)
      • Duration: 10 minutes
      • Requirements: 1 seat, 2 pieces of cargo, vehicle equipped with a lift
    • Delivery: Location (50.69409, -120.35425)
      • Duration: 5 minutes
  • Job 2:
    • Pickup: Location (50.70816, -120.37796)
      • Duration: 5 minutes
      • Requirements: 1 seat, vehicle equipped with both a lift and air conditioning
    • Delivery: Location (50.66559, -120.36924)
      • Service Window: 12:45 PM to 1:30 PM (the job is delivery-anchored, and the delivery must be performed within this time window)
      • Duration: 5 minutes
  • Job 3:
    • Pickup: Location (50.70393, -120.37263)
      • Service Window: 2:00 PM to 2:30 PM (the job is pickup-anchored, and the pickup must be performed within this time window)
      • Duration: 10 minutes
      • Requirements: 1 seat, 3 pieces of cargo, no specific equipment is required
    • Delivery: Location (50.69028, -120.39028)
      • Duration: 5 minutes

Our goal is to assign these jobs to the defined vehicles so that the total travel time is minimized. In other words, our optimization objective will be equal to 1. Now, let’s create our input problem as follows:

Input Problem (payload):

{
    "problem": {
        "fleet": [
            {
                "id": 1,
                "shifts": [
                    {
                        "start": {
                            "time": "2023-10-01T08:00:00-08:00",
                            "location": {
                                "lat": 50.67293,
                                "lng": -120.34195
                            }
                        },
                        "end": {
                            "time": "2023-10-01T18:00:00-08:00",
                            "location": {
                                "lat": 50.67293,
                                "lng": -120.34195
                            }
                        },
                        "breaks": [
                            {
                                "serviceWindow": [
                                    "2023-10-01T10:00:00-08:00",
                                    "2023-10-01T10:30:00-08:00"
                                ],
                                "duration": 900,
                                "location": {
                                    "lat": 50.6531,
                                    "lng": -120.38393
                                }
                            },
                            {
                                "serviceWindow": [
                                    "2023-10-01T14:00:00-08:00",
                                    "2023-10-01T14:30:00-08:00"
                                ],
                                "duration": 900,
                                "location": {
                                    "lat": 50.6531,
                                    "lng": -120.38393
                                }
                            }
                        ]
                    }
                ],
                "capacities": [
                    {
                        "name": "seat",
                        "units": 15
                    },
                    {
                        "name": "cargo",
                        "units": 5
                    }
                ],
                "skills": [
                    "lift",
                    "air_conditioner"
                ]
            },
            {
                "id": 2,
                "shifts": [
                    {
                        "start": {
                            "time": "2023-10-01T08:00:00-08:00",
                            "location": {
                                "lat": 50.7117,
                                "lng": -120.39286
                            }
                        },
                        "end": {
                            "time": "2023-10-01T18:00:00-08:00",
                            "location": {
                                "lat": 50.67698,
                                "lng": -120.32012
                            }
                        },
                        "breaks": [
                            {
                                "serviceWindow": [
                                    "2023-10-01T11:00:00-08:00",
                                    "2023-10-01T11:30:00-08:00"
                                ],
                                "duration": 900,
                                "location": {
                                    "lat": 50.6531,
                                    "lng": -120.38393
                                }
                            }
                        ]
                    }
                ],
                "capacities": [
                    {
                        "name": "seat",
                        "units": 10
                    },
                    {
                        "name": "cargo",
                        "units": 8
                    }
                ],
                "skills": [
                    "lift"
                ]
            }
        ],
        "jobs": [
            {
                "id": 1,
                "pickups": [
                    {
                        "id": 2,
                        "location": [
                            50.65391,
                            -120.37365
                        ],
                        "serviceWindows": [
                            [
                                "2023-10-01T09:00:00-08:00",
                                "2023-10-01T09:30:00-08:00"
                            ]
                        ],
                        "duration": 600,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 2
                            }
                        ],
                        "skills": [
                            "lift"
                        ]
                    }
                ],
                "deliveries": [
                    {
                        "id": 3,
                        "location": [
                            50.69409,
                            -120.35425
                        ],
                        "duration": 300,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 2
                            }
                        ],
                        "skills": [
                            "lift"
                        ]
                    }
                ]
            },
            {
                "id": 4,
                "pickups": [
                    {
                        "id": 5,
                        "location": [
                            50.70816,
                            -120.37796
                        ],
                        "duration": 300,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            }
                        ],
                        "skills": [
                            "lift",
                            "air_conditioner"
                        ]
                    }
                ],
                "deliveries": [
                    {
                        "id": 6,
                        "location": [
                            50.66559,
                            -120.36924
                        ],
                        "serviceWindows": [
                            [
                                "2023-10-01T12:45:00-08:00",
                                "2023-10-01T13:30:00-08:00"
                            ]
                        ],
                        "duration": 300,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            }
                        ],
                        "skills": [
                            "lift",
                            "air_conditioner"
                        ]
                    }
                ]
            },
            {
                "id": 7,
                "pickups": [
                    {
                        "id": 8,
                        "location": [
                            50.70393,
                            -120.37263
                        ],
                        "serviceWindows": [
                            [
                                "2023-10-01T14:00:00-08:00",
                                "2023-10-01T14:30:00-08:00"
                            ]
                        ],
                        "duration": 600,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 3
                            }
                        ]
                    }
                ],
                "deliveries": [
                    {
                        "id": 9,
                        "location": [
                            50.69028,
                            -120.39028
                        ],
                        "duration": 300,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 3
                            }
                        ]
                    }
                ]
            }
        ],
        "objective": 1,
        "configuration": {
            "polylineType": "none",
            "unassignedTasks": true,
            "units": "imperial",
            "statistics": true
        }
    }
}

After submitting this problem using the POST method (as described in the “Get Started”), we get the following solution using the GET method:

Output Solution:

{
    "id": 8193,
    "status": 200,
    "solution": {
        "statistics": {
            "distance": {
                "totalDistance": 54,
                "revenueDistance": 36
            },
            "vehicles": {
                "used": 2,
                "unused": 0
            },
            "jobs": {
                "scheduledTasks": 3,
                "unassignedTasks": 0
            },
            "times": {
                "totalHours": 9.4,
                "revenueHours": 8.7
            }
        },
        "routes": [
            {
                "vehicleId": 1,
                "shifts": [
                    {
                        "index": 1,
                        "stops": [
                            {
                                "jobId": 1,
                                "taskId": 2,
                                "type": "pickup",
                                "location": [
                                    50.65391,
                                    -120.37365
                                ],
                                "eta": "2023-10-01T09:00:00-08:00",
                                "timeToNext": 10,
                                "distanceToNext": 4.9,
                                "waitTime": 0,
                                "polyline": null,
                                "ordinal": 1
                            },
                            {
                                "jobId": 1,
                                "taskId": 3,
                                "type": "delivery",
                                "location": [
                                    50.69409,
                                    -120.35425
                                ],
                                "eta": "2023-10-01T09:25:00-08:00",
                                "timeToNext": 10,
                                "distanceToNext": 5.4,
                                "waitTime": 25,
                                "polyline": null,
                                "ordinal": 2
                            },
                            {
                                "break": 1,
                                "start": "2023-10-01T10:00:00-08:00",
                                "end": "2023-10-01T10:15:00-08:00",
                                "timeToNext": 15,
                                "distanceToNext": 7.3,
                                "waitTime": 0,
                                "polyline": null,
                                "ordinal": 3
                            },
                            {
                                "jobId": 4,
                                "taskId": 5,
                                "type": "pickup",
                                "location": [
                                    50.70816,
                                    -120.37796
                                ],
                                "eta": "2023-10-01T10:30:00-08:00",
                                "timeToNext": 13,
                                "distanceToNext": 5.6,
                                "waitTime": 112,
                                "polyline": null,
                                "ordinal": 4
                            },
                            {
                                "jobId": 4,
                                "taskId": 6,
                                "type": "delivery",
                                "location": [
                                    50.66559,
                                    -120.36924
                                ],
                                "eta": "2023-10-01T12:45:00-08:00",
                                "timeToNext": 4,
                                "distanceToNext": 1.7,
                                "waitTime": 71,
                                "polyline": null,
                                "ordinal": 5
                            },
                            {
                                "break": 2,
                                "start": "2023-10-01T14:00:00-08:00",
                                "end": "2023-10-01T14:15:00-08:00",
                                "timeToNext": 7,
                                "distanceToNext": 3.2,
                                "waitTime": 217,
                                "polyline": null,
                                "ordinal": 6
                            }
                        ]
                    }
                ]
            },
            {
                "vehicleId": 2,
                "shifts": [
                    {
                        "index": 1,
                        "stops": [
                            {
                                "break": 1,
                                "start": "2023-10-01T11:00:00-08:00",
                                "end": "2023-10-01T11:15:00-08:00",
                                "timeToNext": 13,
                                "distanceToNext": 6.6,
                                "waitTime": 152,
                                "polyline": null,
                                "ordinal": 1
                            },
                            {
                                "jobId": 7,
                                "taskId": 8,
                                "type": "pickup",
                                "location": [
                                    50.70393,
                                    -120.37263
                                ],
                                "eta": "2023-10-01T14:00:00-08:00",
                                "timeToNext": 14,
                                "distanceToNext": 4.6,
                                "waitTime": 0,
                                "polyline": null,
                                "ordinal": 2
                            },
                            {
                                "jobId": 7,
                                "taskId": 9,
                                "type": "delivery",
                                "location": [
                                    50.69028,
                                    -120.39028
                                ],
                                "eta": "2023-10-01T14:29:00-08:00",
                                "timeToNext": 13,
                                "distanceToNext": 3.9,
                                "waitTime": 197,
                                "polyline": null,
                                "ordinal": 3
                            }
                        ]
                    }
                ]
            }
        ],
        "unassigned": []
    },
    "message": "success"
}

Example 2: A simple re-optimization scenario for adding new jobs to an existing schedule

Now consider the previous example. Assume that you have started performing the produced schedule since the morning, and now it is 11:36:34, and you get a new job order as follows:

  • Job 4: (a new job)
    • Pickup: Location (50.65187, -120.40052)
      • Service Window: 15:45 to 16:15 (it is a pickup-anchored job)
      • Duration: 15 minutes
      • Requirements: 1 seat, 1 piece of cargo
    • Delivery: Location (50.69262, -120.35412)
      • Duration: 10 minutes

BTW, you have already performed Job 1 but Job 2 and Job 3 are still in progress with the following details:

  • Job 1: (performed)
  • Job 2: (in progress)
    • Pickup:
      • Current Vehicle ID: 1
      • ETA: 10:30
    • Delivery:
      • Current Vehicle ID: 1
      • ETA: 12:45
  • Job 3: (in progress)
    • Pickup:
      • Current Vehicle ID: 2
      • ETA: 14:00
    • Delivery:
      • Current Vehicle ID: 2
      • ETA: 14:29

Note that since Job 2 and Job 3 are in progress, they have an associate vehicle ID and ETA. To re-optimize your schedule to include the new job (i.e. Job 4), you’ll need to provide an updated view of your current schedule through the API. This should include details about your jobs follows:

  • Job 1: for this job, since it is already performed, you can set the status of the pickup and delivery tasks for this job to “status”:”performed” . Note that you don’t need to provide the current vehicle ID and ETA for these tasks as they are already performed, and you cannot change them anymore.
  • Job 2: this job is still in progress and it is assigned to vehicle 1 with pickup ETA=10:30 and delivery ETA=12:45. So, you need to include the following object for its pickup task:
          "status": "in_progress",
          "vehicleID": 1,
          "eta": "2024-10-01T10:30:00-08:00"

Also, you need to include the following object for its delivery task:

          "status": "in_progress",
          "vehicleID": 1,
          "eta": "2024-10-01T12:45:00-08:00"

Job 3: this job is still in progress and it is assigned to vehicle 1 with pickup ETA=14:00 and delivery ETA=14:29. So, you need to include the following object for its pickup task:

          "status": "in_progress",
          "vehicleID": 1,
          "eta": "2024-10-01T14:00:00-08:00"

Also, you need to include the following object for its delivery task:

          "status": "in_progress",
          "vehicleID": 1,
          "eta": "2024-10-01T14:29:00-08:00"

Job 4: since this is a new job and not scheduled yet, you simply set its status to “status”:”pending”. You don’t need to specify a vehicle ID or ETA for this job because it is not scheduled yet, and you don’t have this information. After performing the re-optimization, you will get a vehicle ID and an ETA for each task of this job.

Moreover, you need to provide the last known location of your vehicles so that the API can have an updated picture of your current schedule to do the optimization task efficiently. Suppose that the last known location of your vehicles at time 11:36:34 (i.e. the time that we want to do re-optimization) is as follows:

  • Vehicle 1: (50.66692,-120.35293)
  • Vehicle 2: (50.65324,-120.37398)

For this purpose, you need to include the following object for vehicle 1:

"lastKnownLocation":{
        "location":[50.66692,-120.35293],
        "time":"2024-10-01T11:36:34-08:00"
      } 

Similarly, you need to include the following object for vehicle 2:

"lastKnownLocation":{
        "location":[50.65324,-120.37398],
        "time":"2024-10-01T11:36:34-08:00"
      } 

To do re-optimization, you can now submit your new optimization problem as follows:

{
    "problem": {
        "fleet": [
            {
                "id": 1,
                "shifts": [
                    {
                        "start": {
                            "time": "2023-10-01T08:00:00-08:00",
                            "location": {
                                "lat": 50.67293,
                                "lng": -120.34195
                            }
                        },
                        "end": {
                            "time": "2023-10-01T18:00:00-08:00",
                            "location": {
                                "lat": 50.67293,
                                "lng": -120.34195
                            }
                        },
                        "breaks": [
                            {
                                "serviceWindow": [
                                    "2023-10-01T10:00:00-08:00",
                                    "2023-10-01T10:30:00-08:00"
                                ],
                                "duration": 900,
                                "location": {
                                    "lat": 50.6531,
                                    "lng": -120.38393
                                }
                            },
                            {
                                "serviceWindow": [
                                    "2023-10-01T14:00:00-08:00",
                                    "2023-10-01T14:30:00-08:00"
                                ],
                                "duration": 900,
                                "location": {
                                    "lat": 50.6531,
                                    "lng": -120.38393
                                }
                            }
                        ]
                    }
                ],
                "capacities": [
                    {
                        "name": "seat",
                        "units": 15
                    },
                    {
                        "name": "cargo",
                        "units": 5
                    }
                ],
                "skills": [
                    "lift",
                    "air_conditioner"
                ],
                "lastKnownLocation":{
                         "location":[50.66692,-120.35293],
                         "time":"2024-10-01T11:36:34-08:00"
               }                 
            },
            {
                "id": 2,
                "shifts": [
                    {
                        "start": {
                            "time": "2023-10-01T08:00:00-08:00",
                            "location": {
                                "lat": 50.7117,
                                "lng": -120.39286
                            }
                        },
                        "end": {
                            "time": "2023-10-01T18:00:00-08:00",
                            "location": {
                                "lat": 50.67698,
                                "lng": -120.32012
                            }
                        },
                        "breaks": [
                            {
                                "serviceWindow": [
                                    "2023-10-01T11:00:00-08:00",
                                    "2023-10-01T11:30:00-08:00"
                                ],
                                "duration": 900,
                                "location": {
                                    "lat": 50.6531,
                                    "lng": -120.38393
                                }
                            }
                        ]
                    }
                ],
                "capacities": [
                    {
                        "name": "seat",
                        "units": 10
                    },
                    {
                        "name": "cargo",
                        "units": 8
                    }
                ],
                "skills": [
                    "lift"
                ],
                "lastKnownLocation":{
                         "location":[50.65324,-120.37398],
                         "time":"2024-10-01T11:36:34-08:00"
               }                 
            }
        ],
        "jobs": [
            {
                "id": 1,
                "pickups": [
                    {
                        "id": 2,
                        "location": [
                            50.65391,
                            -120.37365
                        ],
                        "serviceWindows": [
                            [
                                "2023-10-01T09:00:00-08:00",
                                "2023-10-01T09:30:00-08:00"
                            ]
                        ],
                        "duration": 600,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 2
                            }
                        ],
                        "skills": [
                            "lift"
                        ],
                        "status": "performed"
                    }
                ],
                "deliveries": [
                    {
                        "id": 3,
                        "location": [
                            50.69409,
                            -120.35425
                        ],
                        "duration": 300,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 2
                            }
                        ],
                        "skills": [
                            "lift"
                        ],
                        "status": "performed"
                    }
                ]
            },
            {
                "id": 4,
                "pickups": [
                    {
                        "id": 5,
                        "location": [
                            50.70816,
                            -120.37796
                        ],
                        "duration": 300,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            }
                        ],
                        "skills": [
                            "lift",
                            "air_conditioner"
                        ],
                        "status": "in_progress",
                        "vehicleId": 1,
                        "eta": "2023-10-01T10:30:00-08:00"
                    }
                ],
                "deliveries": [
                    {
                        "id": 6,
                        "location": [
                            50.66559,
                            -120.36924
                        ],
                        "serviceWindows": [
                            [
                                "2023-10-01T12:45:00-08:00",
                                "2023-10-01T13:30:00-08:00"
                            ]
                        ],
                        "duration": 300,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            }
                        ],
                        "skills": [
                            "lift",
                            "air_conditioner"
                        ],
                        "status": "in_progress",
                        "vehicleId": 1,
                        "eta": "2023-10-01T12:45:00-08:00"
                    }
                ]
            },
            {
                "id": 7,
                "pickups": [
                    {
                        "id": 8,
                        "location": [
                            50.70393,
                            -120.37263
                        ],
                        "serviceWindows": [
                            [
                                "2023-10-01T14:00:00-08:00",
                                "2023-10-01T14:30:00-08:00"
                            ]
                        ],
                        "duration": 600,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 3
                            }
                        ],
                        "status": "in_progress",
                        "vehicleId": 2,
                        "eta": "2023-10-01T14:00:00-08:00"                        
                    }
                ],
                "deliveries": [
                    {
                        "id": 9,
                        "location": [
                            50.69028,
                            -120.39028
                        ],
                        "duration": 300,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 3
                            }
                        ],
                        "status": "in_progress",
                        "vehicleId": 2,
                        "eta": "2023-10-01T14:29:00-08:00"                       
                    }
                ]
            },
            {
                "id": 10,
                "pickups": [
                    {
                        "id": 11,
                        "location": [
                            50.65187,
                            -120.40052
                        ],
                        "serviceWindows": [
                            [
                                "2023-10-01T15:45:00-08:00",
                                "2023-10-01T16:15:00-08:00"
                            ]
                        ],
                        "duration": 900,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 1
                            }
                        ],
                        "status": "pending"
                    }
                ],
                "deliveries": [
                    {
                        "id": 12,
                        "location": [
                            50.69262,
                            -120.35412
                        ],
                        "duration": 600,
                        "demand": [
                            {
                                "name": "seat",
                                "units": 1
                            },
                            {
                                "name": "cargo",
                                "units": 1
                            }
                        ],
                        "status": "pending"
                    }
                ]
            }

        ],
        "objective": 1,
        "configuration": {
            "polylineType": "none",
            "unassignedTasks": true,
            "units": "imperial",
            "statistics": true
        }
    }
}

Example 3: Re-optimization with Cancelled Jobs

If you’ve submitted an optimization problem for a set of jobs and already have a schedule in place, but some jobs have been cancelled, you can re-optimize your schedule by removing the cancelled jobs from the problem. To do this, you’ll need to:

  • Provide an updated picture of your remaining jobs and the last known locations of your vehicles similar to Example 2.
  • Create and submit a revised problem reflecting these changes.

Once submitted, you will receive a new schedule that accounts for the updated jobs and fleet status.

Example 4: Re-optimization with broken vehicles

Suppose it’s 8:00 AM and you use the API to generate an optimized schedule for your jobs with 10 vehicles. You begin executing the schedule, but at 9:14 AM, you learn that one of your vehicles has broken down and can no longer perform its assigned jobs.

To re-optimize the schedule, follow these steps:

  1. Update Fleet Information: Remove the broken vehicle from your fleet object.
  2. Provide Vehicle Locations: Submit the last known locations of the remaining vehicles, similar to Example 2.
  3. Update Task Status:
    • Provide the status of all tasks. You need to specify which tasks are already performed, which ones are in progress, and which one are new or pending (not scheduled yet).
    • For tasks in progress, include the associated vehicle ID and the estimated time of arrival (ETA).
  4. Handle Tasks for the Broken Vehicle:
    • Change the status of all tasks previously assigned to the broken vehicle to “pending”. This allows the API to reassign them to other available vehicles and recalculate their ETAs.
  5. Submit for Re-optimization: Submit the updated problem to the API for a new schedule optimization.

As described in Get Started, the API supports both POST and GET methods. Depending on the method, it returns a status code in the output response. Here, you can find the description of various status codes for these two methods.

POST Status Codes

Response Code Description Additional Notes
202 The request was accepted for processing. A reference ID is returned by which you can use the GET request to get the solution once it is ready.
400 Input validation failed (Bad Request). There is a missing or an invalid parameter or a parameter with an invalid value type is added to the request. Please correct your input data, and resubmit your request.
403 Unauthorized request. This error occurs when the authentication process fails.
404 Requested path not found. This error occurs when an incorrect path address is used.
429 Too many requests. QPM (Query per Minute) reached or API request count quota reached. In other words, the user has sent too many requests in a minute.
500 Internal Service error. There was an internal issue with our API. You can reach out to [support@ddswireless.com] for an explanation.

GET Status Codes

Response Code Description Additional Notes
200 The request has succeeded. Normal success case. The solution of the problem is ready and it is returned via statistics, routes, unassigned.
202 The request was accepted but it is not completed yet (pending status) Solution is not ready yet. You need to check later.
400 Could not process the request (Bad Request). A feasible solution could not be generated for the given set of locations or parameter configuration.
401 Unauthorized request. The request requires user authentication. The server did not receive the proper credentials.
500 Internal Service error. There was an internal issue with our API. You can reach out to [support@ddswireless.com] for an explanation. statistics, routes, and unassigned will be empty.
Question Answer
Does the API support solving Pickup and Delivery Problem (PDP)? Yes, see the Tutorials section for the detailed explanation of how to use the API for solving various PDP scenarios.
Does the API support open PDP? Yes, you can define arbitrary start and end locations for each vehicle in your fleet, which allows you to solve open PDP scenarios.
Does the API utilize real-time traffic data for route optimization and scheduling? Yes, the API utilizes both historical and real-time traffic data for route optimization and scheduling.
Is it possible to define a fleet of multiple vehicles with various attributes such as vehicle shift timings, their start and end locations, their break’s time periods and location? Yes, see the fleet object of Problem for more information.
Can we define multiple arbitrary capacity types and their available units for our vehicles? Yes, see the fleet object of Problem for more information. The ‘capacity’ attribute in the fleet object allows to specify distinct capacities for different units, creating a comprehensive profile of the vehicle’s capabilities. A single vehicle can be attributed to multiple dimensions such as weight, volume, and quantity of items carried. For instance, a truck might have a capacity of 100 kg weight, 10 cubic meters of volume and the ability to transport 5 construction workers.
Can we specify the maximum number of tasks for each vehicle separately? Yes, see the fleet object of Problem for more information. You can define the maximum number of tasks each vehicle can handle during its shift.
Does the API support multiple breaks per vehicle? Yes, see the fleet object of Problem for more information.
Does the API support pickups, deliveries, or pickup and delivery tasks? Yes, see the jobs object of Problem for more information.
Does the API allow specifying the task duration? Yes, see the jobs object of Problem for more information.
Does the API support defining arbitrary task capacity demands (or amounts)? Yes, see the jobs object of Problem for more information.
Can we define a service time window for each task? Yes, see the jobs object of Problem for more information. Using service time windows, you can specify the earliest and latest times for a task to be performed by an available vehicle.
Can we define one or multiple required skills (traits) for each pickup or delivery task? Yes, see the jobs object of Problem for more information. The ability to define one or multiple required skills (traits) for each job/task. This is useful for job allocation that accounts for field agent skills and/or equipment/inventory with them. It allows to define the expertise and capabilities required for efficient task execution. It ensures that only vehicles, workers, and drivers equipped with the complete set of skills required for a specific job or shipment are assigned to that task. For example, only vehicles equipped with temperature-controlled compartments and drivers skilled in carrying heavy boxes will be transporting temperature-sensitive pharmaceuticals, or a customer may need a ladder or a welding machine or a lift to do its job and only those vehicles or drivers that have such skills should service that customer.
Does the API support re-optimization for ongoing routes? Yes, see the Tutorials section for the detailed explanation of how to perform re-optimization for ongoing routes.
Does the API provide some statistics about the optimized and scheduled routes (e.g. the number of scheduled routes, the total travel time, the total travel distance, the number of unassigned jobs, the number of unused vehicles, etc.)? Yes, see Solution for more details.
Does the API provide a reason for unassigned tasks/jobs? Yes, see Solution for more details.
Does the API provide an estimated time of arrival (ETA) for the scheduled tasks? Yes, see Solution for more details.
Can the API cluster or group jobs based on their locations to improve efficiency? Yes, the API can cluster or group jobs based on their locations to improve efficiency. Example: when picking up multiple students of a class at a recreation centre, it is desired to assign them to the same or similar routes.
Can we use different optimization objectives for routing and scheduling? Yes, the API supports the following optimization objectives (strategies):

  • Minimize Total Travel Time
  • Minimize Number of Routes
  • Balance Workload among Routes

For more details, please see Problem.

See Next: Get Started