---
title: "Walking distance/duration from one origin to many destinations (JSON body variant)"
description: "Identical handler and response to the `GET`, with the inputs in a JSON body. The body form additionally accepts `dests` as an array of `<lat>,<lng>` strings.\n\nProxy over the box-local OSRM instance (foot profile): one origin, up to 300 destinations, walking distance (m) and duration (s) per destination, 1 decimal. Only in-bounds destinations are sent to OSRM; out-of-bounds ones come back as `null` at their original index. `null` also marks a destination OSRM could not route.\n\n**Caching.** Redis `routing:table:foot:<sha1>` keyed on the origin and the ORIGINAL destination list (order and out-of-bounds entries included, coordinates quantised to 5 dp ≈ 1 m), 30-day TTL; a hit is returned with `cached: true`.\n\nCORS is open (`*`) on this router and `OPTIONS` answers 200. Auth: `token` header or `?token=`; errors are always real status codes with JSON bodies (no `X-RES-API-Version` needed). `GET /res_api/routing/health` is the token-free OSRM probe."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.aireon.ch/llms.txt
> Use this file to discover all available pages before exploring further.

Path: RES API (public) › Score

`POST /res_api/routing/table`

Identical handler and response to the `GET`, with the inputs in a JSON body. The body form additionally accepts `dests` as an array of `<lat>,<lng>` strings.

Proxy over the box-local OSRM instance (foot profile): one origin, up to 300 destinations, walking distance (m) and duration (s) per destination, 1 decimal. Only in-bounds destinations are sent to OSRM; out-of-bounds ones come back as `null` at their original index. `null` also marks a destination OSRM could not route.

**Caching.** Redis `routing:table:foot:<sha1>` keyed on the origin and the ORIGINAL destination list (order and out-of-bounds entries included, coordinates quantised to 5 dp ≈ 1 m), 30-day TTL; a hit is returned with `cached: true`.

CORS is open (`*`) on this router and `OPTIONS` answers 200. Auth: `token` header or `?token=`; errors are always real status codes with JSON bodies (no `X-RES-API-Version` needed). `GET /res_api/routing/health` is the token-free OSRM probe.

## Authentication

Requires one of the following:

- `ResApiToken`, apiKey, in header, header `token`
- `ResApiTokenQuery`, apiKey, in query

## Request body

_Required._

- `origin` (`postRoutingTable.origin`; string, required): `<lat>,<lng>`; must lie within Switzerland (lat 45.5..48.1, lng 5.5..11.0).
  - pattern `^-?[0-9.]+,-?[0-9.]+$`; example `"47.3769,8.5417"`
- `dests` (`postRoutingTable.dests`; one of, required): 1..300 destinations as a semicolon-separated `<lat>,<lng>` list, or (POST body only) a JSON array of such strings, which is joined with `;`.
  - one of: `string`, `array<string>`
- `profile` (`postRoutingTable.profile`; string, optional): Only `foot` is available; any other value is a 400 `InvalidInput`.
  - one of `"foot"`; default `"foot"`

## Example request

```json
{
  "profile": "foot",
  "origin": "47.3769,8.5417",
  "dests": [
    "47.3780,8.5400",
    "47.3800,8.5450"
  ]
}
```

## Code samples

### cURL

```bash
curl --request POST \
  --url https://res.aireon.ch/res_api/routing/table \
  --header 'Content-Type: application/json' \
  --header 'token: <token>' \
  --data '
{
  "profile": "foot",
  "origin": "47.3769,8.5417",
  "dests": [
    "47.3780,8.5400",
    "47.3800,8.5450"
  ]
}
'
```

### TypeScript

```typescript
const url = 'https://res.aireon.ch/res_api/routing/table';
const options = {
  method: 'POST',
  headers: {'Content-Type': 'application/json', token: '<token>'},
  body: JSON.stringify({
    profile: 'foot',
    origin: '47.3769,8.5417',
    dests: ['47.3780,8.5400', '47.3800,8.5450']
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```

### Python

```python
import requests

url = "https://res.aireon.ch/res_api/routing/table"

payload = {
    "profile": "foot",
    "origin": "47.3769,8.5417",
    "dests": ["47.3780,8.5400", "47.3800,8.5450"]
}
headers = {
    "Content-Type": "application/json",
    "token": "<token>"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
```

## Responses

### 200

Origin→destination matrix, arrays aligned 1:1 with the request order.

#### Example

```json
{
  "generator": "RES routing",
  "engine": "osrm",
  "profile": "foot",
  "code": "Ok",
  "count": 2,
  "distances": [
    312.4,
    655.9
  ],
  "durations": [
    224.9,
    472.3
  ],
  "cached": false
}
```

- `generator` (`postRoutingTable.response.200.generator`; string, required)
- `engine` (`postRoutingTable.response.200.engine`; string, required)
- `profile` (`postRoutingTable.response.200.profile`; string, required)
- `code` (`postRoutingTable.response.200.code`; string, required)
- `count` (`postRoutingTable.response.200.count`; integer, required): Number of destinations, in request order.
- `distances` (`postRoutingTable.response.200.distances`; array<number | null>, required): Walking distance origin→dest in metres, 1 decimal; null for a destination outside Switzerland or unroutable.
- `durations` (`postRoutingTable.response.200.durations`; array<number | null>, required): Walking time origin→dest in seconds, 1 decimal; null as for `distances`.
- `cached` (`postRoutingTable.response.200.cached`; boolean, required): True when served from the Redis cache (key = SHA-1 of origin + dests at 5 dp, 30-day TTL).

### 400

`InvalidInput`: unsupported profile, malformed or out-of-Switzerland origin, missing/empty/over-300/malformed `dests`.

#### Example

```json
{
  "code": "InvalidInput",
  "message": "dests must contain 1..300 entries"
}
```

- `code` (`postRoutingTable.response.400.code`; string, required)
  - one of `"InvalidInput"`, `"EngineError"`, `"EngineUnavailable"`
- `message` (`postRoutingTable.response.400.message`; string, required)

### 401

Missing token.

#### Example

```json
{
  "error": "string",
  "message": "string"
}
```

- `error` (`postRoutingTable.response.401.error`; string, required): Human-readable error description.
- `message` (`postRoutingTable.response.401.message`; string, optional): Optional underlying error message.

### 403

Wrong token.

#### Example

```json
{
  "error": "string",
  "message": "string"
}
```

- `error` (`postRoutingTable.response.403.error`; string, required): Human-readable error description.
- `message` (`postRoutingTable.response.403.message`; string, optional): Optional underlying error message.

### 502

`EngineError`: OSRM answered an HTTP error or a non-`Ok` code.

#### Example

```json
{
  "code": "InvalidInput",
  "message": "string"
}
```

- `code` (`postRoutingTable.response.502.code`; string, required)
  - one of `"InvalidInput"`, `"EngineError"`, `"EngineUnavailable"`
- `message` (`postRoutingTable.response.502.message`; string, required)

### 503

`EngineUnavailable`: OSRM not reachable within 8 s.

#### Example

```json
{
  "code": "EngineUnavailable",
  "message": "routing engine not reachable"
}
```

- `code` (`postRoutingTable.response.503.code`; string, required)
  - one of `"InvalidInput"`, `"EngineError"`, `"EngineUnavailable"`
- `message` (`postRoutingTable.response.503.message`; string, required)


Source: https://docs.aireon.ch/res/post-routing-table/index.md
