# Get directions and optimize a multi-stop route with PickPoint's API

PickPoint's Routing API returns turn-by-turn directions, distance and travel time between two or more points for ten travel modes. Its optimized route reorders a set of stops and returns the directions for the new order. Each call is one request at $0.25 per thousand requests, however many stops it holds. Send `POST https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/v2/route` or `POST https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/v2/route/optimized` with `locations` and `costing`, and use an `Authorization: Bearer` credential that holds a plan.

## At a glance

- **Endpoints:** `POST https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/v2/route` for directions, `POST https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/v2/route/optimized` for multi-stop order, `POST https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/v2/route/locate` for matching points to roads
- **Body:** `locations` (two or more `{"lat", "lon"}` points, required), `costing` (travel mode, required), `units` (`km` or `mi`, default `km`), and optional `costing_options`, `directions_type` and `language`
- **Price:** $0.25 per thousand requests. One call is one request, so 1,000 calls cost $0.25.
- **Payment:** every call draws on a plan held by the credential you send, the Free trial or Pay as you go. There is no per-call payment.
- **Response:** `trip.summary` (`length` in your units, `time` in seconds), `trip.legs[].maneuvers[]` (`instruction`, `length`, `time`) and `trip.locations[]` with `original_index`
- **Limits:** coordinates only, no addresses. `alternates` works only on two-location routes without `date_time`.
- **Full purchase flow:** [the buyer skill](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/SKILL.md)

## Get directions between two points

1. Hold a credential with a plan that covers routing, the Free trial or Pay as you go. [The buyer skill](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/SKILL.md) and [auth.md](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/auth.md) have the steps for registering the credential and buying a plan.

2. Send the origin first and the destination last, with a travel mode:

   ```bash
   curl -s https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/v2/route \
     -H "Authorization: Bearer $ACCESS_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"locations": [{"lat": 30.2747, "lon": -97.7404}, {"lat": 30.267, "lon": -97.7729}], "costing": "auto", "units": "km"}'
   ```

3. Read `trip.summary` for the whole trip. The response names the unit in full: `units` is `kilometers` or `miles`. The example route between the two points is 5.014 km long, with a `time` of 569.673 seconds, about nine and a half minutes. The response, abridged:

   ```json
   {"trip": {
     "status": 0, "status_message": "Found route between points", "units": "kilometers",
     "summary": {"length": 5.014, "time": 569.673, "has_toll": false, "has_highway": false},
     "legs": [{"maneuvers": [
       {"instruction": "Drive west on State Capitol Driveway.", "length": 0.378, "time": 136.528, "street_names": ["State Capitol Driveway"]},
       "… 9 more"]}],
     "locations": [{"lat": 30.2747, "lon": -97.7404, "original_index": 0, "side_of_street": "left", "type": "break"}, "… 1 more"]
   }}
   ```

4. Read `trip.legs[].maneuvers` for turn-by-turn directions. Each maneuver has an `instruction`, a `length` in your units and a `time` in seconds. The example has one leg of ten maneuvers. To get maneuvers without text, set `directions_type` to `maneuvers`. Set `none` to omit them.

## Change the travel mode

Change `costing` and send the same points again. Cycling the same two points gives a longer, slower route than driving:

| `costing` | `summary.length` | `summary.time` | Maneuvers |
| --- | --- | --- | --- |
| `auto` | 5.014 km | 569.673 s | 10 |
| `bicycle` | 5.107 km | 1111.544 s | 13 |

In the bicycle response, the first instruction starts with "Bike west" instead of "Drive west".

| Trip | `costing` |
| --- | --- |
| Car, obeying car access and turn restrictions | `auto` |
| Delivery truck, with width, height and weight limits | `truck` |
| Lane access for buses or taxis | `bus`, `taxi` |
| Two-wheeled motor travel | `motorcycle`, `motor_scooter` |
| Cycling, preferring cycleways | `bicycle` |
| Walking, shortest walk avoiding stairs | `pedestrian` |
| Walking with a shared bicycle | `bikeshare` |
| Walking with public transit | `multimodal` |

## Tune the route with costing_options

`costing_options` is keyed by the costing name. Each option type affects the route in a different way:

| Option type | Effect | Examples |
| --- | --- | --- |
| Cost | Adds seconds to route cost and time | `gate_cost`, `toll_booth_cost`, `ferry_cost` |
| Penalty | Adds seconds to cost only | `maneuver_penalty`, `toll_booth_penalty` |
| Factor, 0.1 to 100000 | Multiplies the cost of a road type | `use_highways`, `use_tolls`, `use_ferry` |
| Vehicle | Describes the vehicle | `height`, `width`, `exclude_unpaved`, `top_speed` |
| `shortest: true` | Routes on distance alone | |

This body asks for a truck route that penalizes toll booths:

```json
{"locations": [{"lat": 30.2747, "lon": -97.7404}, {"lat": 30.267, "lon": -97.7729}], "costing": "truck", "units": "km", "costing_options": {"truck": {"toll_booth_penalty": 600}}}
```

## Optimize the order of multiple stops

1. Send every stop to `/v2/route/optimized`, with the origin first. The body has the same shape as a directions request:

   ```bash
   curl -s https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/v2/route/optimized \
     -H "Authorization: Bearer $ACCESS_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"locations": [{"lat": 30.2747, "lon": -97.7404}, {"lat": 30.1975, "lon": -97.6664}, {"lat": 30.267, "lon": -97.7729}], "costing": "auto", "units": "km"}'
   ```

2. Read `trip.locations` to get the stop order. Each entry's `original_index` ties it to a stop in the `locations` you sent. The three-stop example returns three locations, and the first has `original_index` 0, the origin sent first.

3. Read `trip.legs` for each part of the trip. A trip with n break locations has n-1 legs. The example returns two legs and a trip `summary` of 47.179 km and 2725.442 seconds, with `has_toll` and `has_highway` both true. Its first leg is 18.993 km.

## Match a point to the road network

`POST https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/v2/route/locate` takes one or more `locations` and a `costing`. It returns the road segments and intersections nearest each point, including which side of the street the point is on. Set `verbose` to `true` to get full edge and node attributes. Each locate call is one request at the same rate.

## What is charged

- Reading the storefront's documents, catalog and API reference costs nothing.
- A plan purchase is charged only when you pay its 402, the price quote.
- Each routing call draws one request from plan credit. The driving example drew $0.00025. The three-stop optimized example drew $0.00025.
- Results may be stored indefinitely. OpenStreetMap data carries the ODbL licence, which requires attribution wherever you display it.

## Errors

| Response | Meaning | Action |
| --- | --- | --- |
| `401 bearer_required` | The call carries no agent credential | Register at [auth.md](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/auth.md), then retry with `Authorization: Bearer <token>` |
| `401 invalid_token`, `token_expired` | The access token expired | Exchange your stored assertion for a fresh token |
| `403 plan_required` | No plan you hold covers routing | Buy a plan from the body's `plans`, then retry |
| `403 verified_email_required` | The Free trial needs a credential claimed with a verified email | Complete the claim, or buy Pay as you go |
| `usage_exhausted` | The plan's credit ran out | Top up with `POST https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/extend` |

Any other error status and body comes from PickPoint's API.

## Frequently asked questions

### Does an optimized multi-stop route cost more than a two-point route?

No. Every call is one request at $0.25 per thousand requests, however many stops it holds. The three-stop optimized example drew $0.00025 from credit.

### Can the Routing API plan truck routes?

Yes. Set `costing` to `truck` to apply width, height and weight limits. Use `costing_options.truck` for vehicle options such as `height` and `width`, and for toll and highway options.

### Can I pay for a single routing call without a plan?

No. Every call draws on a plan held by the credential you send. The Free trial grants $0.625 once per human with a verified email. Pay as you go starts at $0.01 on a wallet rail and $0.50 by card.

### Does the Routing API accept addresses?

No. Each location is a latitude and longitude. To route between addresses, convert them to coordinates first with the Geocoding service's forward geocoding on the same storefront.

### Can the directions API return miles?

Yes. Set `units` to `mi`. Then `summary.length` and each maneuver's `length` are in miles. `time` stays in seconds.

## Keep reading

- [Buyer skill](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/SKILL.md): the full purchase flow
- [Identity](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/auth.md): register and present the agent credential
- [How to pay](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/payment.md): plans, rails and top-ups
- [Routing API reference](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/services/routing/openapi.json): every request and response field
- [Error reference](https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/errors.md): every error code

---

Updated 2026-11-06. All PickPoint guides: https://agents.pickpoint.io/guides.md. Storefront: https://agents.pickpoint.io/zcj/h5cbj4ui9tzf/llms.txt.
