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

# Explain a route

> One sentence explaining how the SuperSafe cycling route differs from the most direct route

## Overview

Compares the SuperSafe cycling route between two points against the most direct cycling route and returns one sentence describing the key difference, for example `"Takes the C13 cycleway and avoids moderately busy Goldsmiths' Row"`.

Use it to caption a SuperSafe route in your own UI. Call it alongside [`POST /directions/`](/api-reference/routing/directions) rather than before it: the sentence is a label for a route you are already showing, and it takes 1 to 2 seconds longer to produce than the route itself.

The sentence is generated text, capped at 120 characters, in English. It is not deterministic: the same origin and destination can produce different wording on different calls. Display it, do not parse it, and do not use it as a cache key.

SuperSafe routing is available in supported cities (NYC, LA, SF Bay Area, Chicago, London).

### Authentication

This endpoint requires an API key. Include it in the `Authorization` header:

```
Authorization: Bearer YOUR_API_KEY
```

A valid user session is also accepted and grants higher rate limits.

### Rate limits

Each call runs two routes and generates text, so this endpoint is limited more tightly than the routing endpoints: 10 requests per minute for API keys, 20 requests per minute for user sessions. On `429`, honor the `Retry-After` header.

### What the sentence can say

The sentence names at most one street per side of the comparison, and only mentions streets that appear on one of the two routes. It names a signed cycle route reference (`C13`, `CS7`) in preference to the underlying street. It mentions street lighting only on nighttime comparisons, and temporary or recurring road closures only when one applies at the compared departure time.

## Request body

<ParamField body="origin" type="array" required>
  Start point as `[longitude, latitude]`.
</ParamField>

<ParamField body="destination" type="array" required>
  End point as `[longitude, latitude]`.
</ParamField>

<Accordion title="Optional parameters">
  <ParamField body="nighttime" type="boolean" default="false">
    Compare the routes on the nighttime cost tier, which prefers lit streets. Pass the `metadata.nighttime` value from the routes you are showing so the sentence describes the same pair of routes.
  </ParamField>

  <ParamField body="departure_time" type="string">
    Planned departure as `"YYYY-MM-DDTHH:mm"` with no timezone offset, interpreted in the route city's timezone. Determines which temporary road avoidances apply to the comparison. Pass the same value you routed with. Omit to compare for now. Unparseable values return `400`.
  </ParamField>
</Accordion>

## Response body

<ResponseField name="summary" type="string | null">
  The sentence describing the difference, at most 120 characters. When the two routes are the same it is the fixed sentence `"The most direct route as well as the quietest"`. `null` when no route exists, or when the difference could not be put into a sentence.
</ResponseField>

<ResponseField name="identical" type="boolean">
  `true` when the SuperSafe route and the most direct route follow the same roads, or differ only by fragments under 30 m. There is nothing to explain, and `summary` carries the fixed sentence above.
</ResponseField>

<ResponseField name="no_route" type="boolean">
  Present and `true` when at least one of the two routes could not be computed, for example when the origin or destination is too far from a road. Absent otherwise.
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST 'https://api.cyclemate.club/explain-supersafe/' \
    -H 'Authorization: Bearer YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "origin": [-0.0754, 51.5465],
      "destination": [-0.0605, 51.5265],
      "nighttime": true
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Routes differ theme={null}
  {
    "summary": "Takes the C13 cycleway and avoids moderately busy Goldsmiths' Row",
    "identical": false
  }
  ```

  ```json Routes are the same theme={null}
  {
    "summary": "The most direct route as well as the quietest",
    "identical": true
  }
  ```

  ```json No route theme={null}
  {
    "summary": null,
    "identical": false,
    "no_route": true
  }
  ```
</ResponseExample>

## Variants

### Night comparison

Riders choosing a route after dark are comparing different roads, because night routing prefers lit streets. Pass `nighttime` so the sentence can mention lighting:

```javascript JavaScript theme={null}
const response = await fetch('https://api.cyclemate.club/explain-supersafe/', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    origin,
    destination,
    nighttime: route.metadata.nighttime,
  }),
});
```

### Comparison at a future departure

Pass `departure_time` when the rider has picked a departure other than now, so closures that apply at that time are reflected in the sentence. A street market that closes a road on Saturday mornings is a difference worth naming, and only shows up when the comparison is made for that window:

```json theme={null}
{
  "origin": [-0.0625, 51.5335],
  "destination": [-0.0600, 51.5400],
  "departure_time": "2026-08-08T11:00"
}
```

## Error responses

### 400 Bad request

```json theme={null}
{
  "error": "origin and destination must be [lon, lat] arrays"
}
```

```json theme={null}
{
  "error": "nighttime must be a boolean"
}
```

```json theme={null}
{
  "error": "departure_time is not a valid wall-clock time: tomorrow"
}
```

Out-of-coverage routing carries a machine-readable `code`:

```json theme={null}
{
  "error": "Sorry! This route goes outside our coverage area.",
  "code": "CROSS_CITY_ROUTE"
}
```

### 401 Unauthorized

```json theme={null}
{
  "error": "Missing Authorization header"
}
```

### 405 Method not allowed

Method other than `POST`.

```json theme={null}
{
  "error": "Method not allowed"
}
```

### 429 Too many requests

Includes a `Retry-After` header with the seconds until the current window closes:

```json theme={null}
{
  "error": "Rate limit exceeded",
  "retry_after_seconds": 42
}
```

### 500 Internal server error

```json theme={null}
{
  "error": "Internal server error"
}
```
