Modern technology can provide us with a wealth of data about the location of vehicles and their states, but sometimes the path between those data points and the useful and actionable information isn’t easy to find. In this article, I’m going to introduce you to some of the APIs available from TomTom and demonstrate how you can leverage them to turn location data points into actionable information about your fleet.
We’ll look at some examples to determine the location of a specific vehicle in an understandable human form and then identify the route the vehicle followed to get there. Finally, we’ll investigate how to find out additional information about the route, and even identify if the vehicle violated speed limits while completing the route.
I’ll be sharing direct API calls to keep this article as coding language-agnostic as possible; however, any modern web language can access these APIs.
The TomTom Maps APIs
The TomTom Developer Portal is where you’ll find everything you need to get up and running with the TomTom APIs. The first thing you’ll want to do is create an account on the portal. From the home page, enter your email address and click on the "Get a free API key" button.
Fig. 1 The TomTom Developer Portal
The next step in the process is to select a username and read through the Terms and Conditions. Your free account supports up to 2,500 free transactions per day. It should be noted that should 2,500 API transactions per day not be enough, more transactions can be purchased by visiting the My Credits screen in the developer dashboard.
An email contains a link to set the password for your account, and with that, you’ll be ready to go. You need to configure an application before you can request an API Key. From your dashboard, click on the "+ Add an App" button.
Applications require a name, and you’ll need to enable the APIs which the application needs to access. For this example, the products we’ll be using are the Search API and the Routing API products. If you’re following along, select the Search API and Routing API products and click on Create App.
Fig. 2 Creating a New Application
You can receive a unique API key by visiting the TomTom Developer Portal, and entering your email address for a "Free API Key." You’ll need to read and agree to the terms and conditions and select a username. An email prompts you to set a password, and from there, you can navigate to your dashboard and create a new application.
Applications are approved quickly and appear on your dashboard. The entry shows the Consumer API Key, and information about your application, including the approval status of the application, and each of the products it uses.
This article focuses on how to use the TomTom Search and Routing APIs, but developers also have access to Web and Mobile SDKs which contain similar functionality. You can learn more about each of the SDKs from the following links:
Fig. 3 Application Details
Each of the examples below includes the phrase ReplaceWithYourAPIHere. You’ll need to replace that phrase with the Consumer API Key from your unique application. Let’s see where our drivers have been taking the corporate vehicles.
Where Are They Now?
The scenario is this: We have a vehicle which is carrying a GPS locator and sending location information to our system in the form of latitude and longitude pairs. For this example, we’ll be working with the following pair of coordinates:
45.512077,-122.627832
Let’s see if we can find the address, and then we’ll see if we can also get the nearest cross street. The base URL is api.tomtom.com, and we’ll be accessing the search API. The current version of this API is 2, and we’re going to be performing a reverse geocoding option.
https:
Fig. 4 Example URL for Reverse GeoCoding
If you receive a response similar to the one below, you’ll need to ensure that your API key is entered correctly.
<h1>Developer Inactive</h1>
Fig. 5 Error Received When the API Key is Incorrect
The JSON path parameter indicates that we would like to receive a response in JSON format. If this parameter is omitted, the default format of XML is used. The response from the URL above is shown below.
{
"summary": {
"queryTime": 134,
"numResults": 1
},
"addresses": [
{
"address": {
"buildingNumber": "3527",
"streetNumber": "3527",
"routeNumbers": [],
"street": "SE Hawthorne Blvd",
"streetName": "SE Hawthorne Blvd",
"streetNameAndNumber": "3527 SE Hawthorne Blvd",
"countryCode": "US",
"countrySubdivision": "OR",
"countrySecondarySubdivision": "Multnomah",
"municipality": "Portland",
"postalCode": "97214",
"country": "United States Of America",
"countryCodeISO3": "USA",
"freeformAddress": "3527 SE Hawthorne Blvd, Portland, OR 97214",
"countrySubdivisionName": "Oregon"
},
"position": "45.512046,-122.627833"
}
]
}
Fig. 6 Reverse Geocoding Response
All right—I now know that the driver has parked the vehicle at 3527 SE Hawthorne Blvd in downtown Portland. If I’m not mistaken, Blue Star Donuts is right down the street. (I hope they bring a couple back to the office.)
While we wait for the donuts, let’s see if there is a way to get more information about exactly where they are. Hawthorne Blvd is a pretty long road. I’d like to know which cross street they’re closest to.
https:
Fig. 7 Example URL for Reverse GeoCoding with Cross Street Information
{
"summary": {
"numResults": 1,
"queryTime": 209
},
"addresses": [
{
"address": {
"streetName": "SE 35th Pl & SE Hawthorne Blvd",
"crossStreet": "SE 35th Pl",
"municipalitySubdivision": "Richmond, Portland",
"municipality": "Portland",
"countrySecondarySubdivision": "Multnomah",
"countryTertiarySubdivision": "Portland East",
"countrySubdivision": "OR",
"postalCode": "97214",
"countryCode": "US",
"country": "United States Of America",
"countryCodeISO3": "USA",
"freeformAddress": "SE 35th Pl & SE Hawthorne Blvd, Portland, OR 97214",
"countrySubdivisionName": "Oregon",
"street": "SE Hawthorne Blvd"
},
"position": "45.51204,-122.62763"
}
]
}
Fig. 8 Reverse Geocoding Response
The cross street option is especially useful in cases where the address doesn’t yield exact information, or if a precise location is necessary for emergency situations. Let’s see if we can find out more about how they traveled to this exact location.
How Did They Get There?
Our next challenge is to reconstruct the route the vehicle traveled to get from one location to another. We’ll use the Routing API to work this out. If we submit a POST request, we’re able to include a list of supporting points that allow us to reconstruct the route based on where the vehicle traveled. We can also include the start and end time to determine if there were any delays along the way.
We’ll use the following URL and then pass in a JSON body which includes the supporting point and other critical parameters. Here’s the information we know about the driver and the route they took:
- The driver started at the PDX airport (45.5868227,-122.5937596) and ended up at the Blue Star Donut Shop (45.512077,-122.627832).
- We have a series of points as pairs of latitude and longitude values, along which the vehicle drove.
https:
Fig. 9 Base URL to Reconstruct Route with Supporting Points
The request body is in JSON format, so we’ll pass along a Content-Type header set to application/json. The body we’ll pass in with the request is shown below. I thinned out the list of supporting points to keep the snippet small.
{
"supportingPoints": [
{
"latitude": 45.58355,
"longitude": -122.58545
},
{
"latitude": 45.52641,
"longitude": -122.61544
},
{
"latitude": 45.51287,
"longitude": -122.62296
},
{
"latitude": 45.51204,
"longitude": -122.62782
}
]
}
Fig. 10 Passing a Collection of Supporting Points to Accurately Map the Route
The following response is typical of what you can expect to receive from the Routes API with this request.
{
"formatVersion": "0.0.12",
"copyright": "Copyright 2018 TomTom International BV. ...",
"privacy": "TomTom keeps information that tells us how ...",
"routes": [
{
"summary": {
"lengthInMeters": 12201,
"travelTimeInSeconds": 1479,
"trafficDelayInSeconds": 0,
"departureTime": "2018-09-24T23:01:26-07:00",
"arrivalTime": "2018-09-24T23:26:04-07:00"
},
"legs": [
{
"summary": {
"lengthInMeters": 12201,
"travelTimeInSeconds": 1479,
"trafficDelayInSeconds": 0,
"departureTime": "2018-09-24T23:01:26-07:00",
"arrivalTime": "2018-09-24T23:26:04-07:00"
},
"points": [
{
"latitude": 45.58671,
"longitude": -122.59387
},
{
"latitude": 45.58638,
"longitude": -122.59324
},
{
"latitude": 45.51287,
"longitude": -122.62588
},
{
"latitude": 45.51204,
"longitude": -122.62783
}
]
}
],
"sections": [
{
"startPointIndex": 0,
"endPointIndex": 10,
"sectionType": "TRAVEL_MODE",
"travelMode": "other"
},
{
"startPointIndex": 10,
"endPointIndex": 213,
"sectionType": "TRAVEL_MODE",
"travelMode": "car"
}
]
}
]
}
Fig. 11 Reconstructed Route Based on Supporting Points
The full route information includes a complete set of points which you can plot on a map. The route also includes a summary section which provides details about the distance of the route, the time to travel the route, and an adjustment based on traffic.
Departure time and arrival time are optional parameters and mutually exclusive. These are useful if you want to plot a route based on specific departure time, or if you need to arrive by a particular time and need to know the best time to leave.
Exploring Additional Details of the Route
If you have a tracking system which includes speed readings from the vehicle, then you can compare these readings against speed information using the returnSpeedLimit
parameter with the reverse geocoding request. We’ll pick a point on the route, and pass this to the Search API.
https:
Fig. 12 Example URL for Reverse GeoCoding with Speed Limit Information
If you look at the response below, you’ll see that in addition to the address information, we also have a speed limit parameter which indicates the speed limit on this stretch of road. We can perform this query for each point of the route, and compare it programmatically with the speed data from the vehicle, allowing us to determine if any speed violations occurred en route to the destination.
{
"summary": {
"queryTime": 109,
"numResults": 1
},
"addresses": [
{
"address": {
"routeNumbers": [
"I-84",
"US-30"
],
"street": "I-84",
"streetName": "I-84",
"speedLimit": "55.00MPH",
"countryCode": "US",
"countrySubdivision": "OR",
"countrySecondarySubdivision": "Multnomah",
"municipality": "Portland",
"postalCode": "97213",
"country": "United States Of America",
"countryCodeISO3": "USA",
"freeformAddress": "I-84, Portland, OR 97213",
"countrySubdivisionName": "Oregon"
},
"position": "45.531806,-122.596331"
}
]
}
Fig. 13 Response with Speed Limit Information
We can also pass in configuration parameters for the vehicle, such as:
- Vehicle Engine Type
- Consumption Information - collection of pairs of speed and the corresponding consumption rate.
- Acceleration and Deceleration Efficiency
- Vehicle Metrics - Weight, Load Type, Max Speed
With these configuration parameters, the API returns information about expected fuel consumption. You can learn about these parameters in the Routing API Documentation.
You can also add the vehicle configuration for more accurate route planning. Routes can be decided based on speed, distance or eco mode. Eco mode factors in fuel consumption, vehicle efficiency, traffic, and hilliness of the route to find the route which consumes the least fuel/energy possible.
Additional Information
If you would like to learn more about options available within the TomTom APIs, you can access the online documentation or use the API Explorer to try different parameters and see how they all work together.