# Migrate a Valhalla client to geolith routing (in development)

> What changes when a Valhalla client points at the geolith router: a new base URL and kebab-case paths (/sources-to-targets, /trace-route, /trace-attributes); request and response bodies stay the same. Routing is in development and not deployed.

---
title: Migrate a Valhalla client to geolith routing (in development)
description: 'What changes when a Valhalla client points at the geolith router: a new base URL and kebab-case paths (/sources-to-targets, /trace-route, /trace-attributes); request and response bodies stay the same. Routing is in development and not deployed.'
date: '2026-11-08'
tags: [routing, valhalla, migration, javascript]
minutes: 6
product: routing
faqs:
  - q: Do the request and response bodies change?
    a: No. The router takes Valhalla's request bodies and returns Valhalla's response bodies; on Berlin the JSON was byte-identical to Valhalla 3.9.1 on every measured request.
  - q: Which costing models work?
    a: auto, pedestrian and bicycle.
---

**Status: routing is in development and not deployed.** There is no hosted routing endpoint and no routing plan, price or key. This guide lists what changes so a client is ready when a router is.

The geolith router speaks Valhalla's API. A client written for Valhalla changes two things: **the base URL** and **the paths**, which are kebab-case.

## Path mapping

| Valhalla              | geolith               |
| --------------------- | --------------------- |
| `/route`              | `/route`              |
| `/isochrone`          | `/isochrone`          |
| `/sources_to_targets` | `/sources-to-targets` |
| `/trace_route`        | `/trace-route`        |
| `/trace_attributes`   | `/trace-attributes`   |

Only the kebab-case paths are served: `/sources_to_targets` does not answer.

## Before and after

```js
// Before: Valhalla.
const VALHALLA = 'https://valhalla.example.com';
const res = await fetch(`${VALHALLA}/sources_to_targets`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sources, targets, costing: 'auto' }),
});
```

```js
// After: a geolith router you run (ROUTER_HOST); the body is unchanged.
const ROUTER = 'https://ROUTER_HOST';
const res = await fetch(`${ROUTER}/sources-to-targets`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sources, targets, costing: 'auto' }),
});
```

## What stays the same

- Request bodies: `locations`, `sources`, `targets`, `shape`, `costing`, `contours`, `shape_match`, `date_time`, `units`.
- Response bodies: the trip object, `sources_to_targets`, the isochrone GeoJSON, and the trace results.
- Error bodies: `error_code`, `error`, `status_code` and `status`, with the HTTP status of the same number.
- Traffic: historical speeds in Valhalla's CSV format, used for requests with a `date_time`. See [traffic and live data](/routing/traffic).

## What to check

- Costing: `auto`, `pedestrian` and `bicycle` only.
- Spoken (`verbal_*`) instructions are in progress.
- Accuracy per endpoint is on [routing accuracy](/routing/accuracy).


Routing is in development and not deployed; there is no endpoint to call yet, and no routing plan, price or key. Read the routing docs: https://docs.geolith.app/routing
