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

# Directions and routing

> Fetch a route from the Directions API and draw it with MapLibre.

[Directions](/services/directions) returns one or more routes between two or more points,
each carrying its geometry as an encoded polyline plus distance and time estimates.

## Requesting a route

```javascript theme={null}
import polyline from "@mapbox/polyline";
import { baatoRequest } from "./baato";

export async function getDirections(points, mode = "car") {
  const params = new URLSearchParams({
    key: baatoToken,
    mode,
    instructions: "true",
    alternatives: "true",
  });

  // points[] is repeated once per waypoint, each as "lat,lon"
  points.forEach(([lat, lon]) => params.append("points[]", `${lat},${lon}`));

  const response = await fetch(`https://api.baato.io/api/v1/directions?${params}`);
  const { data } = await response.json();

  return data.map((route) => ({
    ...route,
    geojson: polyline.toGeoJSON(route.encodedPolyline),
  }));
}
```

<ParamField query="points[]" type="string[]" required>
  Waypoints as `"lat,lon"` strings. Repeat the parameter once per point; at least two are
  required, and intermediate points are supported.
</ParamField>

<ParamField query="mode" type="string" required>
  One of `car`, `bike` or `foot`.
</ParamField>

<ParamField query="alternatives" type="boolean" default="false">
  Return alternative routes alongside the best one.
</ParamField>

<ParamField query="instructions" type="boolean" default="false">
  Include a turn-by-turn instruction list. Without this, `instructionList` is `null`.
</ParamField>

<Note>
  `points[]` uses `"lat,lon"` order, unlike the `[lon, lat]` arrays MapLibre expects.
  `polyline.toGeoJSON()` produces renderer-ready `[lon, lat]` coordinates, so the conversion
  only bites on the request side.
</Note>

## Drawing the route

```javascript theme={null}
<MapLibreGL.ShapeSource id="routeSource" shape={route.geojson}>
  <MapLibreGL.LineLayer
    id="routeLine"
    style={{
      lineColor: "#008148",
      lineWidth: 6,
      lineJoin: "round",
      lineCap: "round",
    }}
  />
</MapLibreGL.ShapeSource>
```

To frame the whole route, fit the camera to its bounds:

```javascript theme={null}
import { bbox } from "@turf/bbox";

const [minLon, minLat, maxLon, maxLat] = bbox(route.geojson);

camera.current?.fitBounds([minLon, minLat], [maxLon, maxLat], 50, 800);
```

## Reading the response

<ResponseField name="encodedPolyline" type="string">
  Route geometry in encoded polyline format. Decode with `@mapbox/polyline` before rendering.
</ResponseField>

<ResponseField name="distanceInMeters" type="number">
  Total route distance.
</ResponseField>

<ResponseField name="timeInMs" type="integer">
  Estimated travel time in **milliseconds** — divide by 1000 before formatting as seconds.
</ResponseField>

<ResponseField name="instructionList" type="array | null">
  Turn-by-turn instructions, or `null` unless you requested `instructions=true`.
</ResponseField>

```javascript theme={null}
const km = (route.distanceInMeters / 1000).toFixed(1);
const minutes = Math.round(route.timeInMs / 1000 / 60);

setSummary(`${km} km · ${minutes} min`);
```

## Next

<Columns cols={2}>
  <Card title="Directions API" icon="code" href="/services/directions">
    Full parameter reference and playground.
  </Card>

  <Card title="Core concepts" icon="lightbulb" href="/about/concepts#encoded-polylines">
    More on encoded polylines and coordinate order.
  </Card>
</Columns>
