POST /v1/matrix
Overview
Compute travel times and distances between many origins (sources) and destinations (targets) in a single request. Typical uses: nearest-depot assignment, delivery round preparation (as input to a route optimizer), travel-time rankings ("which agency is closest for each customer?").
Cost: 1 credit per started block of 25 elements, where elements = sources × targets (a 2×3 matrix costs 1 credit, a 10×10 matrix costs 4). Availability: from the Startup plan. The maximum matrix size depends on your plan: 25×25 (625 elements) on Startup, 50×50 (2,500) on Growth, 100×100 (10,000) on Pro.
Request
POST https://api.geocodeme.net/v1/matrix
Content-Type: application/json
Required headers:
X-Api-Key: gm_YOUR_API_KEYContent-Type: application/json
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
sources | array | Yes | n/a | Origin points as [longitude, latitude] pairs (1 to 100) |
targets | array | Yes | n/a | Destination points as [longitude, latitude] pairs (1 to 100) |
profile | string | No | car | Vehicle profile: car, bike, foot, truck, or moto (plan-gated: bike/foot Startup+, truck/moto Growth+) |
use_tolls | boolean | No | n/a | Prefer (true) or avoid (false) toll roads. Motorized profiles only |
truck_height | float | No | n/a | Vehicle height in meters (0 to 10). Requires profile=truck |
truck_width | float | No | n/a | Vehicle width in meters (0 to 5). Requires profile=truck |
truck_weight | float | No | n/a | Vehicle weight in metric tons (0 to 100). Requires profile=truck |
Coordinates are in [longitude, latitude] order (GeoJSON standard), not [lat, lon].
Code Examples
- cURL
- Python
- JavaScript
curl -X POST \
-H "X-Api-Key: gm_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sources": [
[2.3522, 48.8566],
[2.2945, 48.8584]
],
"targets": [
[2.3730, 48.8443],
[4.8357, 45.7640]
],
"profile": "car"
}' \
"https://api.geocodeme.net/v1/matrix"
import os
import requests
api_key = os.environ["GEOCODEME_API_KEY"]
response = requests.post(
"https://api.geocodeme.net/v1/matrix",
json={
"sources": [[2.3522, 48.8566], [2.2945, 48.8584]],
"targets": [[2.3730, 48.8443], [4.8357, 45.7640]],
"profile": "car",
},
headers={"X-Api-Key": api_key},
)
response.raise_for_status()
data = response.json()
for i, row in enumerate(data["durations"]):
for j, seconds in enumerate(row):
if seconds is None:
print(f"source {i} -> target {j}: unroutable")
else:
print(f"source {i} -> target {j}: {seconds / 60:.0f} min")
const apiKey = process.env.GEOCODEME_API_KEY;
const response = await fetch("https://api.geocodeme.net/v1/matrix", {
method: "POST",
headers: {
"X-Api-Key": apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
sources: [[2.3522, 48.8566], [2.2945, 48.8584]],
targets: [[2.3730, 48.8443], [4.8357, 45.7640]],
profile: "car",
}),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
data.durations.forEach((row, i) => {
row.forEach((seconds, j) => {
console.log(
`source ${i} -> target ${j}: ` +
(seconds === null ? "unroutable" : `${Math.round(seconds / 60)} min`)
);
});
});
Response
All responses include rate limiting headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Monthly-Remaining, etc.).
{
"durations": [
[540.2, 16480.5],
[780.9, 16890.1]
],
"distances": [
[3620.0, 465800.0],
[5210.0, 468400.0]
],
"attribution": "Route data (c) OpenStreetMap contributors",
"meta": {
"took_ms": 84,
"cache_hit": false
}
}
Schema
| Field | Type | Description |
|---|---|---|
durations | array | durations[i][j] = travel time in seconds from sources[i] to targets[j], or null if the pair is unroutable |
distances | array | distances[i][j] = travel distance in meters from sources[i] to targets[j], or null if the pair is unroutable |
attribution | string | Always "Route data (c) OpenStreetMap contributors" |
meta.took_ms | integer | Server processing time in milliseconds |
meta.cache_hit | boolean | Whether the response was served from cache |
null cells: unroutable pairs
A null in durations[i][j] / distances[i][j] means the engine could not connect that source/target pair. The matrix engine is stricter than /v1/route when snapping points to the network: a point inside a pedestrian zone (or far from any road usable by the requested profile) may produce null cells in a matrix even though /v1/route finds a route from the same point. If you hit unexpected null cells, move the offending point to the nearest road open to your profile, or verify it first with /v1/nearest.
Error Responses
Matrix larger than your plan's cap
{
"error": {
"code": "PLAN_UPGRADE_REQUIRED",
"message": "Your plan allows up to 625 matrix elements (sources x targets). Upgrade to raise the limit.",
"field": "sources",
"upgrade_url": "https://geocodeme.net/dashboard/billing"
}
}
On the Free plan the endpoint itself is not available ("This feature is not included in your plan. Upgrade to unlock it.").
Invalid coordinate
{
"error": {
"code": "INVALID_PARAMETER",
"message": "Invalid coordinate at index 1 in 'targets' (expected [lon, lat])",
"field": "targets"
}
}
All endpoints are also subject to INVALID_API_KEY (401) and RATE_LIMIT_EXCEEDED / QUOTA_EXCEEDED (429) errors. See Error Codes for the full reference.