Travel-time matrix for everyone to everywhere.

Every source against every target in one request: distance and duration for each pair, by car, bike or on foot. The question behind dispatch, store finders and delivery slots, answered as one table instead of a hundred routes.

10,000 units free every month. No credit card, no sales call.

Real response · by bike3 × 6 = 18 units
3 couriers
6 orders
minJordaanDe PijpOostWester.ZuidasIJburg
ACentraal7141382433
BMuseumplein10514141237
CAmstelstation221111251828

Highlighted: the nearest courier for each order.

POST /directions-matrix/v1 · 3 sources · 6 targets

18 pairs · one request · 18 units

Where it lands in your product.

Nobody ships an endpoint. They ship a dispatch board that knows who is closest, a store finder that sorts by minutes rather than kilometres, a checkout that promises a slot it can keep. This is what a matrix looks like from the outside.

Map of Amsterdam with three couriers and six orders, each order linked to its nearest courier

Three couriers, six orders, one request. Each order goes to the nearest courier by bike.

  • ACentraal
  • BMuseumplein
  • CAmstelstation
© OpenStreetMap contributors

Who is closest to each order?

One request returns the time from every courier to every order. Sort each column and the assignment falls out. No routing loop, no waiting on twenty-four separate answers.

The same road graph, routed
Dispatch · Open orders
  • JordaanACentraal7 min
  • De PijpBMuseumplein5 min
  • OostCAmstelstation11 min
  • WesterparkACentraal8 min
  • ZuidasBMuseumplein12 min
  • IJburgCAmstelstation28 min

The dispatcher's screen.

This is the same 3 × 6 table, read the way a dispatcher reads it: an order, the nearest courier, the minutes. Every number here is from the response, not typed in.

Then route the winner

A dispatcher’s morning, one request each time

2units for the whole table

1 couriers × 2 orders
2 pairs, 1 unit each

Priced per pair, sent as one.

A matrix costs one unit per source-target pair, the same as one route per pair. The difference is that it comes back as one table in one round trip, up to 2,500 pairs at a time.

See what a month costs
dispatch.ts
const { sourcesToTargets } = await rijwind.matrix({
  sources: couriers,
  targets: orders,
  costing: 'bicycle',
});

// nearest courier per order
const pick = orders.map((_, j) =>
  argmin(sourcesToTargets.map((row) => row[j].time)));

A table in, a table out.

Sources, targets and a profile go in; a row per source with a cell per target comes out, each cell carrying seconds, distance and the indexes of the pair. Unreachable pairs are null, not an error.

Read the quickstart

Rows for sources, cells for targets.

The response is the table you asked for: a row per source, a cell per target, each cell with seconds, distance and the indexes of the pair. Your inputs come back with it, so a row never gets matched to the wrong courier.

Every field, in the docs ↗
3 × 6, bicycle
  1. {
  2. "sourcesToTargets": [// one row per source, one cell per target
  3. [
  4. { "time": 402, "distance": 1.904, "fromIndex": 0, "toIndex": 0 },// seconds and kilometres: courier A to the Jordaan, 7 min
  5. { "time": 862, "distance": 3.978, "fromIndex": 0, "toIndex": 1 },// the indexes tell you which pair, whatever the order
  6. … 4 more cells
  7. ],
  8. [ … ], [ … ]// couriers B and C
  9. ],
  10. "sources": [{ "lat": 52.3791, "lon": 4.9003 }, …],// your inputs, echoed back
  11. "targets": [ … ],
  12. "units": "kilometers"// or miles, if you ask
  13. }

The short version.

Everything a developer scans a product page for, in one place, without the adjectives.

MatrixSources × targets. A 3 × 6 table is 18 units.
1 unit / pair
Per request50 × 50, 1 × 2,500, or anything between.
up to 2,500 pairs
ProfilesEach with its own rules, not a speed multiplier.
car · bike · foot
Per cellPlus the source and target indexes. Kilometres or miles.
seconds + distance
Unreachable pairsNot an error; the rest of the table still comes back.
null
Live traffic in the timesDurations come from the road graph. Rijwind Traffic is a separate map layer.
no
Free tierHard cap. No card, no sales call.
10,000 units / month
Paid plansOne unit pool across maps, geocoding and routing, plus a spending cap you set.
from €5 / month
ProcessingNo US-controlled provider in the request path. DPA and sub-processor list published.
EU, end to end

Numbers as of September 2026. The pricing page has the full ladder.

Matrices, answered.

What is a travel-time matrix?

A table of travel times and distances from a set of sources to a set of targets, computed in one request. Three couriers and six orders give a 3 × 6 table; each cell says how long that courier would take to reach that order. It is the input to dispatch, store finders, delivery-slot checks and anything else that starts with 'which of these is closest'.

How is it different from asking for routes?

The numbers are the same as you would get from one route per pair. The difference is one round trip and one table instead of dozens of calls, and no route geometry you would only throw away. When you then need the actual turn-by-turn route for the winning pair, ask the routing endpoint for that one.

How much does a matrix cost?

One unit per source-target pair, from the same monthly pool as maps, geocoding and routing. A 3 × 6 table is 18 units; a 10 × 10 table is 100.

How large can a matrix be?

Up to 2,500 pairs per request, so 50 × 50, or 1 × 2,500, or anything in between. Larger jobs are split into several requests.

Which travel profiles are supported?

Car, bicycle and pedestrian, each with its own rules. The matrix on this page is by bike; the same points by car had one target no car can reach, which comes back as null rather than as an error.

Are the times traffic-aware?

No. Durations come from the road graph (speed limits, road class, surface and turn costs), not from live traffic. Rijwind Traffic is a separate live layer for your map and does not feed into these numbers today.

What comes back exactly?

A row per source with a cell per target. Each cell carries the time in seconds, the distance in kilometres or miles, and the source and target indexes so you never have to trust the order. Unreachable pairs have null time and distance.

Is there a free tier?

Yes. The free plan includes 10,000 units a month with no card and no sales call, which is a 10 × 10 matrix a hundred times over. It is a hard cap, so a runaway loop cannot produce a bill.

Where are my requests processed?

In the European Union, end to end. No part of the request path touches a US-controlled provider, which is what makes the GDPR and data-residency conversation short. We publish a DPA and a full sub-processor list.

Ask everyone at once.

Ten thousand units a month, free. The same key covers maps, search and routing when you get to them.

3 couriers to 40 orders, by bikeGet an API key
No credit card. No sales call. A spending cap you set yourself.Read the quickstart