Distance matrix (beta)
Distances and durations between many origins and destinations.
matrix.compute
Beta
element_1k
How to call it
REST
POST
/v1/matrix
202
GraphQL
mutation
openMatrix
MCP
open_matrix_compute
Road distances and durations between many origins and destinations. EXPENSIVE: one engine request per origin row, billed per thousand cells. If you are building this matrix in order to plan routes, call open_routing_optimize instead — it builds the same matrix internally, once.
Request schema
Generated from the same validation rules the endpoint runs, so a field cannot be documented without being validated.
POST /v1/matrix
{
"type": "object",
"properties": {
"callback": {
"type": [
"object",
"null"
],
"properties": {
"events": {
"type": "array",
"items": {
"type": "string",
"maxLength": 32
}
},
"format": {
"type": [
"string",
"null"
],
"enum": [
"native",
"ce_binary",
"ce_structured"
]
},
"secret": {
"type": [
"string",
"null"
],
"minLength": 16,
"maxLength": 255,
"description": "Required when callback.signature is standard_webhooks."
},
"signature": {
"type": [
"string",
"null"
],
"enum": [
"native",
"standard_webhooks"
]
},
"url": {
"type": "string",
"maxLength": 2048,
"format": "uri",
"description": "Required when callback is present."
}
}
},
"destinations": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
],
"maxLength": 128
},
"lat": {
"type": "number",
"minimum": -90,
"maximum": 90
},
"lng": {
"type": "number",
"minimum": -180,
"maximum": 180
}
},
"required": [
"lat",
"lng"
]
}
},
"metrics": {
"type": "array",
"items": {
"type": "string",
"enum": [
"distance",
"duration"
]
}
},
"mode": {
"type": [
"string",
"null"
],
"enum": [
"auto",
"sync",
"async"
]
},
"origins": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"id": {
"type": [
"string",
"null"
],
"maxLength": 128
},
"lat": {
"type": "number",
"minimum": -90,
"maximum": 90
},
"lng": {
"type": "number",
"minimum": -180,
"maximum": 180
}
},
"required": [
"lat",
"lng"
]
}
},
"profile": {
"type": [
"string",
"null"
],
"enum": [
"car",
"van",
"truck",
"bike",
"foot",
"motorcycle"
]
},
"region": {
"type": [
"string",
"null"
],
"enum": [
"NA",
"EU",
"AU",
"ASIA",
"na",
"eu",
"au",
"asia"
]
}
},
"additionalProperties": false,
"required": [
"destinations",
"origins"
]
}
Request example
{
"origins": [
{
"id": "depot",
"lat": 45.5017,
"lng": -73.5673
}
],
"destinations": [
{
"id": "order-1001",
"lat": 45.5088,
"lng": -73.554
},
{
"id": "order-1002",
"lat": 45.4972,
"lng": -73.5786
}
]
}
Response
What a successful call returns: the schema of `data` and `meta`, with a description of each field, followed by an example response from a real call.
POST /v1/matrix
Response schema
{
"description": "Road distance and driving time from every origin to every destination. Row i is origin i, column j is destination j. A cell that could not be routed is null in both matrices and listed in `unreachable`; it is never 0. Large matrices answer 202 with a job.",
"data": {
"type": "object",
"properties": {
"origins": {
"type": "array",
"items": {
"type": "string"
},
"description": "Origin ids, in row order. An origin sent without an id is numbered from 0."
},
"destinations": {
"type": "array",
"items": {
"type": "string"
},
"description": "Destination ids, in column order. Equal to `origins` when no destinations were sent."
},
"distances_meters": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": [
"integer",
"null"
]
}
},
"description": "Present when `metrics` includes distance (the default)."
},
"durations_seconds": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": [
"integer",
"null"
]
}
},
"description": "Present when `metrics` includes duration (the default)."
},
"unreachable": {
"type": "array",
"items": {
"type": "object",
"properties": {
"origin": {
"type": "string"
},
"destination": {
"type": "string"
}
}
},
"description": "Cells that could not be routed."
}
}
},
"meta": {
"type": "object",
"properties": {
"region": {
"type": "string"
},
"profile": {
"type": "string"
},
"metrics": {
"type": "array",
"items": {
"type": "string"
}
},
"origins": {
"type": "integer"
},
"destinations": {
"type": "integer"
},
"elements": {
"type": "integer",
"description": "Cells computed; what is billed."
},
"mode": {
"type": "string",
"enum": [
"sync",
"async"
]
}
}
}
}
Response example
{
"request_id": "req_01k8zq3m5n7p9r1t3v5x7z9b2d",
"capability": "matrix.compute",
"billing": {
"unit": "element_1k",
"quantity": 0.002,
"counted": true,
"breakdown": {
"origins": 1,
"destinations": 2,
"elements": 2,
"engine_requests": 1
}
},
"data": {
"origins": [
"depot"
],
"destinations": [
"order-1001",
"order-1002"
],
"distances_meters": [
[
1840,
1611
]
],
"durations_seconds": [
[
245,
227
]
],
"unreachable": []
},
"meta": {
"region": "NA",
"profile": "car",
"metrics": [
"distance",
"duration"
],
"origins": 1,
"destinations": 2,
"elements": 2,
"mode": "sync"
}
}
Example response when queued (202)
{
"request_id": "req_01k8zq3m5n7p9r1t3v5x7z9b2d",
"capability": "matrix.compute",
"billing": {
"unit": "element_1k",
"quantity": 0.002,
"counted": true,
"breakdown": {
"origins": 1,
"destinations": 2,
"elements": 2,
"engine_requests": 1
}
},
"data": {
"job": {
"id": "job_01k8zq4a6c8e0g2j4l6n8q0s2u",
"status": "queued",
"capability": "matrix.compute",
"poll_after_ms": 1000,
"result_url": "/v1/jobs/job_01k8zq4a6c8e0g2j4l6n8q0s2u/result",
"cancel_url": "/v1/jobs/job_01k8zq4a6c8e0g2j4l6n8q0s2u/cancel"
}
},
"meta": {
"mode": "async"
}
}
What it costs
Thousands of matrix cells (origins x destinations), charged fractionally.
Every billable response carries a billing block with the unit, the quantity and how the quantity was derived.
Errors it can return
| Status | Code | Description |
|---|---|---|
| 401 | TOKEN_INVALID |
Unknown or revoked API token. |
| 401 | TOKEN_MISSING |
No API token. Send Authorization: Bearer <your token>. |
| 402 | QUOTA_EXHAUSTED |
The included allowance for this capability is used up for the current period. |
| 403 | CAPABILITY_NOT_ENABLED |
This capability is not enabled for your account. See :doc to enable it. |
| 403 | CAPABILITY_NOT_GRANTED_TO_KEY |
Your account has this capability, but this API key was not granted it. |
| 403 | OPEN_API_DISABLED |
Open Platform access is not enabled for this account. |
| 413 | REQUEST_TOO_LARGE |
The request body is too large. Upload large payloads as a reusable resource instead. |
| 422 | UNSUPPORTED_REGION |
That routing region is not available. Use NA, EU, AU or ASIA. |
| 422 | VALIDATION_FAILED |
The request failed validation. See details. |
| 429 | CONCURRENCY_LIMIT |
Too many solves are already running for this account. Retry when one finishes. |
| 429 | RATE_LIMITED |
Too many requests. Please retry after the indicated delay. |
| 500 | INTERNAL_ERROR |
An unexpected error occurred. Quote the request_id when contacting support. |
| 502 | ENGINE_UNAVAILABLE |
The routing engine is temporarily unreachable. Please retry. |