# Apify Logistics And Delivery Routes

> Plan and price logistics and delivery routes with the Apify Google Maps Directions API Actor (johnvc/google-maps-directions-api). Run one lane at a time (a depot to a stop, a technician to a job site, a store to a customer) and get distance, ETA, per-mode travel times, and turn-by-turn steps back as JSON, then loop lanes into a travel-time table, compare a depart-at against an arrive-by window, or refresh every corridor you watch on a schedule. Use when the user asks about logistics and delivery route planning, delivery ETA estimates, drive-time or travel-time matrices, field-service dispatch windows, service-area coverage checks, courier lane costing, or transit analysis for a commute. Pay-per-route billing, MCP-ready for Claude and other AI agents.

- Skill: `johnisanerd/apify-logistics-and-delivery-routes` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add johnisanerd/apify-logistics-and-delivery-routes`
- Raw SKILL.md: https://api.skillmd.com/api/skills/johnisanerd/apify-logistics-and-delivery-routes/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: johnisanerd (https://skillmd.com/u/johnisanerd)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/johnisanerd/apify-logistics-and-delivery-routes

---


# Logistics and Delivery: Route Times and ETAs You Can Plan Against

Turn a list of lanes into a table of distances and travel times. Each lookup returns the driving, transit, walking, and cycling options for one origin and destination pair, so you can quote a delivery window, size a service area, or set a dispatch schedule from real route data.

## When to use this skill

- The user is planning or pricing logistics and delivery routes and needs distance plus ETA per lane.
- They want a drive-time or travel-time matrix across depots, stores, job sites, or customers.
- They want to check whether an address falls inside a service area or a promised delivery window.
- They dispatch field teams and need arrive-by or depart-at timing for a work order.
- They want transit analysis for a commute, a shift start, or a lane where driving is not the default.

Not for: multi-stop route optimization or a traveling-salesman solver (this Actor routes one pair at a time), finding the stops themselves (use the Google Maps Places API Actor), or live vehicle tracking.

## What each lane returns

One row per origin and destination pair:

- Headline numbers: `best_duration` ("8 min"), `best_distance` ("1.1 miles"), `directions_found`, `directions_count`.
- `durations`: the per-mode summary, one entry per mode with `travel_mode`, `duration` in seconds, and `formatted_duration`. A Manhattan test lane returned Driving, Transit, Walking, and Cycling from a single lookup. This is the field to build a matrix from.
- `directions`: each route option with `travel_mode`, numeric `distance` (meters) and `duration` (seconds), `formatted_distance`, `formatted_duration`, and a `via` summary ("Broadway", "every 7 min"). Transit options add `cost` and `currency` for the fare, plus `start_time` and `end_time` when present. Some options carry an `elevation_profile` when present.
- `directions[].trips[]`: the legs, with `travel_mode`, `title`, distance, duration, and, for transit, `start_stop`, `end_stop`, `stops`, and `service_run_by` when present.
- `directions[].trips[].details[]`: turn-by-turn steps with `title`, `action` when present, per-step distance and duration, `extensions` notes, and `gps_coordinates` when present.
- `places_info`: the resolved `address`, `data_id`, and `gps_coordinates` for both endpoints. Cache these as canonical stop IDs.
- Bookkeeping: `start`, `end`, `travel_mode`, `gl`, `hl`, `fetched_at`, and `google_maps_directions_url` for a human to eyeball.

Failed lanes come back as `result_type` of `error` with `error_message` and `error_type`. Resolved lanes with no route come back with `directions_found` false and a short `note`.

## Prerequisites

- Apify account (sign up at https://apify.com?fpr=9n7kx3&fp_sid=skillrepo).
- Authentication via `apify login`, or an `APIFY_TOKEN` environment variable (Apify Console, Settings, Integrations).

## The Actor

- Store page: https://apify.com/johnvc/google-maps-directions-api?fpr=9n7kx3&fp_sid=skillrepo
- Actor ID: `johnvc/google-maps-directions-api`
- Pricing: pay per event, dominated by a per-lane lookup fee plus a per-run setup fee (see `references/gotchas.md`).

## Run it with the Apify CLI

One delivery lane, all modes, miles:

```bash
apify actors call "johnvc/google-maps-directions-api" -i '{"start_addr":"1000 Industrial Blvd, Dallas, TX","end_addr":"400 Main St, Fort Worth, TX","travel_mode":"best","distance_unit":"miles"}' \
  --json \
  --user-agent apify-awesome-skills/apify-logistics-and-delivery-routes \
  2>/dev/null
```

A dispatch window: what time must the van leave to arrive by 9 AM, avoiding tolls?

```bash
apify actors call "johnvc/google-maps-directions-api" -i '{"start_addr":"Depot, Newark, NJ","end_addr":"350 5th Ave, New York, NY","travel_mode":"driving","avoid_tolls":true,"time_type":"arrive_by","time_value":"2026-08-03T09:00:00","distance_unit":"miles"}' \
  --json \
  --user-agent apify-awesome-skills/apify-logistics-and-delivery-routes \
  2>/dev/null
```

Transit analysis for a shift start, favoring fewer transfers:

```bash
apify actors call "johnvc/google-maps-directions-api" -i '{"start_addr":"Croydon, London","end_addr":"Canary Wharf, London","travel_mode":"transit","transit_routing":"fewer_transfers","time_type":"depart_at","time_value":"2026-08-03T06:30:00","gl":"gb","hl":"en"}' \
  --json \
  --user-agent apify-awesome-skills/apify-logistics-and-delivery-routes \
  2>/dev/null
```

Loop a lane list into a matrix, one paid lookup per lane:

```bash
while IFS=, read -r origin dest; do
  apify actors call "johnvc/google-maps-directions-api" -i "{\"start_addr\":\"$origin\",\"end_addr\":\"$dest\",\"travel_mode\":\"best\",\"distance_unit\":\"miles\"}" \
    --json \
    --user-agent apify-awesome-skills/apify-logistics-and-delivery-routes \
    2>/dev/null
done < lanes.csv
```

Every call carries the three flags this repo expects: `--json` (or `--format json`), `--user-agent apify-awesome-skills/apify-logistics-and-delivery-routes`, and `2>/dev/null`.

## Run it from Claude or another AI agent (MCP)

The Actor is MCP-ready. Add the hosted server URL:

`https://mcp.apify.com/?tools=actors,docs,johnvc/google-maps-directions-api`

Then ask, for example: "For each of these five depots, how long is the drive to our Fort Worth customer, and which one should take the delivery?" MCP setup docs: https://docs.apify.com/platform/integrations/mcp

## Workflow

1. Write down the lanes. One row per origin and destination pair: depot to stop, technician to job site, store to customer. That list is also the cost list, since each lane is one paid lookup.
2. Canonicalize the endpoints once. Run each address, keep the `places_info` `data_id` and `gps_coordinates`, and reuse them as `start_data_id` and `end_data_id` on later runs. This kills ambiguous-address noise in a recurring pipeline.
3. Estimate the bill before the loop. Lanes times the per-lookup cost plus setup, see `references/gotchas.md`. Warn the user above $5 and confirm above $20.
4. Run the lanes. Keep `travel_mode` at `best` when you want a mode comparison in one paid call. Restrict it when the fleet only drives.
5. Build the table. Pull `start`, `end`, numeric `duration` and `distance` from the recommended option, plus the `durations` entries per mode. Sort by duration to pick the nearest depot, or filter by a threshold to define a service area.
6. Model the window. Re-run the same lane with `time_type` of `depart_at` and again with `arrive_by` to bracket a dispatch time. Compare the returned durations rather than assuming a fixed pad.
7. Keep it fresh. Save one Apify task per corridor and attach a schedule (daily 7 AM, or weekday mornings) so the table refreshes without rebuilding inputs. Age rows out with `fetched_at`.

## Inputs that matter for logistics

- `start_addr` / `end_addr`, or `start_coords` / `end_coords`, or `start_data_id` / `end_data_id` for the two endpoints
- `travel_mode`: `best` for a mode comparison, `driving` for fleet lanes, `transit` for commute and shift analysis, `cycling` or `two-wheeler` for last-mile couriers
- `distance_unit`: `miles` or `km` so the display strings match the operation
- `avoid_tolls`, `avoid_highways`, `avoid_ferries`: cost and vehicle-class preferences, not hard constraints
- `time_type` plus `time_value`: `depart_at` or `arrive_by` with an ISO 8601 datetime, the dispatch-window lever
- `transit_prefer` and `transit_routing`: `fewer_transfers`, `less_walking`, or `wheelchair` for accessible routing, transit mode only
- `gl` and `hl`: country and language for non-US operations

## Cost

Billing is per event: a setup fee per run plus one lookup fee per origin and destination pair, roughly two and a half cents per lane all in. A 100-lane matrix is around $2.50. Fifty lanes refreshed daily for a month is about 1,500 lookups, roughly $37. Cost tracks lanes, not route options, so a `best` run that returns four modes still bills as one lane. Full math in `references/gotchas.md`.

## Honest limits

- One lane per run. No waypoints, no multi-stop sequencing, no optimizer. A route with N stops is N minus 1 lookups, and the ordering is your job.
- No vehicle profile. There is no truck height, weight, or hazmat routing, and no cargo-class restriction.
- Avoidance flags are preferences. A toll road can still appear when no alternative exists.
- Durations reflect the time context you ask for. There is no historical traffic series and no confidence band, so bracket windows by running `depart_at` and `arrive_by` rather than expecting a range field.
- Transit fares and elevation data appear only on the options that carry them.
- This is a polled dataset, not a live tracking feed. Freshness is your schedule interval.

## Troubleshooting

- Lane returns `directions_found` false: that mode has no route between the points. Fall back to `best` and read `durations`.
- Wrong branch of a chain matched: the address was ambiguous. Add state or country, or switch that stop to coordinates or a place ID.
- Matrix has gaps: check for `result_type` of `error` rows before aggregating, and retry those lanes only.
- Numbers do not add up in a spreadsheet: use the numeric `distance` and `duration` (meters and seconds), not the formatted strings.
- Bill higher than expected: count distinct lanes, not runs you thought were batched. Deduplicate repeated pairs and cache static lanes.

See `references/gotchas.md` for cost guardrails and error recovery, and `references/actor-index.md` for the Actor routing table.

## Related mapping Actors

- Google Maps Places API: https://apify.com/johnvc/google-maps-places-api?fpr=9n7kx3&fp_sid=skillrepo
- Google Local API: https://apify.com/johnvc/google-local-api?fpr=9n7kx3&fp_sid=skillrepo
- Google Maps Contributor Reviews API: https://apify.com/johnvc/google-maps-contributor-reviews-api?fpr=9n7kx3&fp_sid=skillrepo

