GuidesAPI Reference
Guides

Get started with HERE Tour Planning API

This section outlines how to quickly get started using the HERE Tour Planning API on the HERE platform.

📘

Note

This section provides information on the minimum setup required to quickly begin using the HERE Tour Planning API. For more detailed information on HERE account setup, app registration, and authentication, see the Identity and Access Management Guide.

Get a HERE account

Obtain access to the HERE platform through your organization administrator's invitation or get started for free.

  • If your company has already established a HERE platform organization, contact your organization admin who can invite you to join the organization.
  • If your company hasn’t established a HERE platform organization yet, you can get started for free. For more information, see the HERE platform pricing.

Register your App

To register your app, follow these steps:

  1. Sign in to the HERE platform using your HERE account.
  2. Open the Access Manager from the Launcher.
  3. On the Apps tab, click Register new app and provide the requested information.
  4. Click Register. The platform creates a new app with a unique app ID.

Get the OAuth 2.0 credentials

Create HERE token credentials that conform to the OAuth 2.0 industry standard protocol for Bearer Tokens (Client Credentials Flow). Your app can use access tokens for up to 24 hours to authenticate requests to the HERE platform.

📘

Note

  • The OAuth 2.0 tokens is the main authentication method in the HERE Tour Planning API, providing enhanced security benefits in the form of short-lived bearer tokens. For simpler use cases, where additional security features of OAuth 2.0 are not required, the HERE Tour Planning also supports API keys as an alternative authentication method.
  • If you are using the API key as the authentication method, remove the 'Authorization: Bearer <TOKEN>' header from the request and then add the apikey parameter to the request URL, for example https://tourplanning.hereapi.com/v3/problems?apikey=<YOUR_HERE_API_KEY>. This approach is applicable to all HERE Tour Planning endpoints.

Follow these steps to obtain the required credentials for the OAuth 2.0 authentication:

  1. Sign in to the HERE platform using your HERE account.

  2. Open the Access Manager from the Launcher.

  3. On the Apps tab, click the app you created in the previous section, Register your App, or an existing group app for which you want to create a set of OAuth 2.0 credentials.

  4. On the Credentials tab, select OAuth 2.0, and then click Create credentials to create a maximum of two sets of OAuth 2.0 credentials for authenticating your application with the HERE platform. See the following figure for reference: Creating OAuth 2.0 credentials

  5. In the Your access key ID and secret were created dialog, click Download to download the credentials.properties file. See the following figure for reference: Viewing and downloading the credentials The file contains the following access credentials:

    • here.user.id
    • here.client.id
    • here.access.key.id
    • here.access.key.secret
    • here.token.endpoint.url
    📘

    Note

    • Store the credentials.properties file in a secure location and don't share them between users or workstations.
    • You can't download or view the contents of the credentials.properties file again in the HERE platform after closing the window.
  6. Close the dialog.

  7. Create a bearer token by using the credentials that you obtained by completing previous steps. For example, you can use the HERE OLP CLI to generate bearer tokens that are valid up to 24 hours.

Send a request

The HERE Tour Planning API supports two types of requests, synchronous and asynchronous. All features are available for both synchronous and asynchronous requests. However, synchronous requests have stricter limitations on jobs and fleet sizes.

For more information, see:

📘

Note

Certain features make solving a vehicle routing problem more challenging, therefore the algorithm needs more time to find a "good" solution. Such features can include the number of jobs and vehicle types, multi-jobs, pickup and delivery jobs, restrictive time windows, insufficient total vehicle capacity in comparison to the total job demand, and so on. HERE recommends using asynchronous requests with a higher polling interval in these cases.

Complexity of the problem vs time required to solve it

Certain features make solving a vehicle routing problem more challenging, so that the algorithm needs more time to find a "good" solution. Such features are:

  • The amount of jobs and vehicle types: the bigger amount means more complex problem
  • Multi jobs
  • Pickup and delivery jobs
  • Restrictive time windows
  • Insufficient total vehicle capacity in comparison to total job demand

Consider using asynchronous request with higher polling interval in such cases.

Synchronous request

Using the synchronous request involves sending a request to the server and waiting for the response. The synchronous request has a limit of 250 jobs and 35 vehicle types. For larger problems, you can use an asynchronous request.

Create a problem definition and send a solution calculation request to the corresponding endpoint, using the POST method. If the request is valid, the service starts calculating and returns a solution once the calculation is completed. The following snippet provides a cURL example of such a request:

curl --location 'https://tourplanning.hereapi.com/v3/problems' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <TOKEN>' \
--data '{
  "plan": {
    "jobs": [
      {
        "id": "myJob",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {"lat": 52.46642, "lng": 13.28124},
                  "times": [["2020-07-04T10:00:00.000Z","2020-07-04T12:00:00.000Z"]],
                  "duration": 180
                }
              ],
              "demand": [1]
            }
          ]
        }
      }
    ]
  },
  "fleet": {
    "types": [
      {
        "id": "myVehicleType",
        "profile": "car",
        "costs": {
          "distance": 0.0002,
          "time": 0.005,
          "fixed": 22
        },
        "shifts": [{
          "start": {
            "time": "2020-07-04T09:00:00Z",
            "location": {"lat": 52.52568, "lng": 13.45345}
          },
          "end": {
            "time": "2020-07-04T18:00:00Z",
            "location": {"lat": 52.52568, "lng": 13.45345}
          }
        }],
        "limits": {
          "maxDistance": 300000,
          "shiftTime": 28800
        },
        "capacity": [10],
        "amount": 1
      }
    ],
    "profiles": [{
      "name": "car",
      "type": "car",
      "departureTime": "2020-07-04T09:15:00Z"
    }]
  },
  "configuration": {
    "termination": {
      "maxTime": 2,
      "stagnationTime": 1
    }
  }
}'

For more information, see Problem.

If a request isn't valid, then the corresponding error is returned, as shown in the following example:

{
  "title": "BAD_REQUEST",
  "status": 400,
  "code": "E613420",
  "cause": "Vehicle's arrival time is earlier than its departure time",
  "action": "Correct arrival time of 'vehicle' to be earlier than its departure",
  "correlationId": "<globally unique id>"
}

Asynchronous request

The asynchronous request to receive a solution for a problem consists of several steps:

📘

Note

Asynchronous request flows have a limit of 6000 jobs and 150 vehicle types.

Request a solution for the problem

Create a problem definition and send a solution calculation request to the corresponding problems/async endpoint by using the POST method. The following snippet shows a sample request using the cURL tool:

curl --location 'https://tourplanning.hereapi.com/v3/problems/async' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <TOKEN>' \
--data '{
  "plan": {
    "jobs": [
      {
        "id": "myJob",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {"lat": 52.46642, "lng": 13.28124},
                  "times": [["2020-07-04T10:00:00.000Z","2020-07-04T12:00:00.000Z"]],
                  "duration": 180
                }
              ],
              "demand": [1]
            }
          ]
        }
      }
    ]
  },
  "fleet": {
    "types": [
      {
        "id": "myVehicleType",
        "profile": "car",
        "costs": {
          "distance": 0.0002,
          "time": 0.005,
          "fixed": 22
        },
        "shifts": [{
          "start": {
            "time": "2020-07-04T09:00:00Z",
            "location": {"lat": 52.52568, "lng": 13.45345}
          },
          "end": {
            "time": "2020-07-04T18:00:00Z",
            "location": {"lat": 52.52568, "lng": 13.45345}
          }
        }],
        "limits": {
          "maxDistance": 300000,
          "shiftTime": 28800
        },
        "capacity": [10],
        "amount": 1
      }
    ],
    "profiles": [{
      "name": "car",
      "type": "car",
      "departureTime": "2020-07-04T09:15:00Z"
    }]
  },
  "configuration": {
    "termination": {
      "maxTime": 2,
      "stagnationTime": 1
    }
  }
}'

The API returns the following response body:

{
  "statusId": "<globally unique id>",
  "href": "https://tourplanning.hereapi.com/v3/status/<statusId>"
}

The elements in the response are:

  • statusId - A unique identifier of the status which is used for tracking the solution calculation status and for downloading the solution result.
  • href - The URL for polling the status.

Check the status of the solution

To get the status of a solution calculation for a given problem ID, use the href parameter that you obtained when submitting the request to send a GET request as shown in the following cURL snippet:

curl --location 'https://tourplanning.hereapi.com/v3/status/<statusId>' \
--header 'Authorization: Bearer <TOKEN>'

The API responds with the request status, for example:

{
  "status": "pending"
}

If you get status pending or inProgress, then you should keep polling until the calculation is finished and a status of success, timeout, or failure is returned.

A response with success returns a resource link to download the calculated solution, as shown in the following snippet:

{
    "status": "success",
    "resource": {
      "resourceId": "<globally unique id>",
      "href": "https://tourplanning.hereapi.com/v3/problems/<resourceId>/solution"
    }
}

A response failure response returns an error object:

{
    "status": "failure",
    "error": {
      "message": "There was an error solving the problem"
    }
}

You can use the statusId to get error details through the solution endpoint as described in the following section.

Download the solution

If the status of a solution calculation is success, the calculated solution is available using the ID provided in the resourceId element which is effectively a problemId. Obtain the solution by sending a GET request that follows this pattern:

curl --location 'https://tourplanning.hereapi.com/v3/problems/<resourceId>/solution' \
--header 'Authorization: Bearer <TOKEN>'

The API responds with the solution JSON, as shown in the following example:

{
  "statistic": {
    "cost": 45.7042,
    "distance": 31921,
    "duration": 3464,
    "times": {
      "driving": 3284,
      "serving": 180,
      "waiting": 0,
      "stopping": 0,
      "break": 0,
      "intraStop": 0
    },
    "intraStopDistance": 0
  },
  "tours": [
    {
      "vehicleId": "myVehicleType_1",
      "typeId": "myVehicleType",
      "stops": [
        {
          "time": {
            "arrival": "2020-07-04T09:00:00Z",
            "departure": "2020-07-04T09:32:12Z"
          },
          "load": [1],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure",
              "location": {
                "lat": 52.52568,
                "lng": 13.45345
              },
              "time": {
                "start": "2020-07-04T09:00:00Z",
                "end": "2020-07-04T09:32:12Z",
                "arrival": "2020-07-04T09:00:00Z"
              }
            }
          ],
          "location": {
            "lat": 52.52568,
            "lng": 13.45345
          },
          "distance": 0,
          "intraStopDistance": 0
        },
        {
          "time": {
            "arrival": "2020-07-04T10:00:00Z",
            "departure": "2020-07-04T10:03:00Z"
          },
          "load": [0],
          "activities": [
            {
              "jobId": "myJob",
              "type": "delivery",
              "location": {
                "lat": 52.46642,
                "lng": 13.28124
              },
              "time": {
                "start": "2020-07-04T10:00:00Z",
                "end": "2020-07-04T10:03:00Z",
                "arrival": "2020-07-04T10:00:00Z"
              }
            }
          ],
          "location": {
            "lat": 52.46642,
            "lng": 13.28124
          },
          "distance": 16020,
          "intraStopDistance": 0
        },
        {
          "time": {
            "arrival": "2020-07-04T10:29:56Z",
            "departure": "2020-07-04T10:29:56Z"
          },
          "load": [0],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival",
              "location": {
                "lat": 52.52568,
                "lng": 13.45345
              },
              "time": {
                "start": "2020-07-04T10:29:56Z",
                "end": "2020-07-04T10:29:56Z",
                "arrival": "2020-07-04T10:29:56Z"
              }
            }
          ],
          "location": {
            "lat": 52.52568,
            "lng": 13.45345
          },
          "distance": 31921,
          "intraStopDistance": 0
        }
      ],
      "statistic": {
        "cost": 45.7042,
        "distance": 31921,
        "duration": 3464,
        "times": {
          "driving": 3284,
          "serving": 180,
          "waiting": 0,
          "stopping": 0,
          "break": 0,
          "intraStop": 0
        },
        "intraStopDistance": 0
      },
      "shiftIndex": 0
    }
  ]
}

For a detailed explanation, see Solution.

If an error occurs during the problem solving, the error response is returned:

{
    "title": "Unprocessable entity",
    "status": 422,
    "code": "E613000",
    "cause": "E613420, 'Vehicle's arrival time is earlier than its departure time' 'Correct arrival time of 'vehicle' to be earlier than its departure'",
    "action": "",
    "correlationId": "REQ-497fdde4-048d-4db5-9d6e-8e44a952dede"
}
📘

Note

Requesting a solution of an unfinished calculation results in the HTTP status code 404 Not Found.

Next steps

For more information, see the HERE Tour Planning API Reference and the use cases throughout this guide, which walk you through various tour planning scenarios.