How to Find the Nearest Driver, Store, or Facility by Travel Time
- API or service
- Route Matrix API
- Task
- Origin and candidates → nearest reachable candidate
- Examples
- Difficulty
- Intermediate
- Time
- 10 min
Find the nearest location by travel time
You have a user, job, or pickup location and several candidate drivers, stores, or facilities. Straight-line distance can select the wrong candidate when roads, rivers, bridges, access restrictions, or one-way streets affect the trip.
Use the Route Matrix API to calculate road travel time between the origin and every candidate in one request, then select the smallest reachable matrix cell.
Task flow: origin and candidate coordinates → Route Matrix API → travel-time matrix → nearest reachable candidate.
Calculate candidate travel times
For a user choosing among stores or facilities, send the user as one source and the candidates as targets. POST the JSON body to:
POST https://api.geoapify.com/v1/routematrix?apiKey=YOUR_API_KEY
Content-Type: application/json
{
"mode": "drive",
"sources": [
{
"location": [-121.32485316561406, 38.67387210503517]
}
],
"targets": [
{
"location": [-121.31172308967166, 38.66553576111227]
},
{
"location": [-121.31533025339189, 38.661141891975916]
},
{
"location": [-121.334451, 38.672844]
}
]
}
Matrix coordinates use [longitude, latitude] order. Preserve the candidate array in the same order because each response cell refers to its candidate through target_index.
To find the nearest driver to one pickup, reverse the shape: send drivers as sources and the pickup as the single target. Road travel can be directional, so source-to-target and target-to-source times are not necessarily equal.
Read the matrix row
With one source and three targets, sources_to_targets contains one row with three cells.
Reduced response:
{
"sources_to_targets": [
[
{
"distance": 3421,
"time": 274,
"source_index": 0,
"target_index": 0
},
{
"distance": 3279,
"time": 251,
"source_index": 0,
"target_index": 1
},
{
"distance": 1954,
"time": 209,
"source_index": 0,
"target_index": 2
}
]
],
"units": "metric",
"distance_units": "meters",
"mode": "drive"
}
Candidate 2 is nearest by travel time at 209 seconds. It is also nearest by road distance in this example, but always rank using the measurement required by the product rather than assuming distance and time produce the same order.
The complete response contains both original_location and road-snapped location values. Keep the original coordinates for your business objects and use the matrix cells for comparisons.
Select the nearest candidate
Keep candidates in request order and map the winning target_index back to the corresponding application object.
const candidates = [
{ id: "store-a", location: [-121.31172308967166, 38.66553576111227] },
{ id: "store-b", location: [-121.31533025339189, 38.661141891975916] },
{ id: "store-c", location: [-121.334451, 38.672844] }
];
function findNearestCandidate(matrix, candidates) {
const reachableCells = matrix.sources_to_targets[0]
.filter(cell => Number.isFinite(cell.time));
if (!reachableCells.length) {
return null;
}
const nearestCell = reachableCells.reduce((nearest, cell) =>
cell.time < nearest.time ? cell : nearest
);
return {
candidate: candidates[nearestCell.target_index],
travelTimeSeconds: nearestCell.time,
distance: nearestCell.distance,
distanceUnits: matrix.distance_units
};
}
const nearest = findNearestCandidate(matrixResponse, candidates);
Treat missing or non-finite times as unreachable candidates. In production, also apply business constraints—such as opening hours, driver capacity, service type, or maximum response time—before selecting the final candidate.