---
title: "Plan an EV route with charging stops"
method: GET
path: "/ev-route"
tags: ["EV Routing"]
---

# Plan an EV route with charging stops

`GET /ev-route`

Plans a drivable route between two points for a specific electric vehicle and inserts the charging stops needed to complete it: which stations, arrival and departure state of charge, charge duration, energy used, and total trip time. The optimizer minimizes total trip time (drive + charge + plug overhead), not stop count. Charging cost is returned where the operator publishes a price — coverage is partial, so estCostEur can be null while the plan is complete. Europe only (lat 35..62, lon -11..35), routes up to 2500 km. Estimates depend on real conditions; verify charger availability before relying on a stop.

## Query parameters

- `originLat` number, required
- `originLon` number, required
- `destLat` number, required
- `destLon` number, required
- `vehicleId` string
- `batteryKwh` number
- `consumptionWhKm` number
- `connector` 'ccs' | 'chademo' | 'type2'
- `maxDcKw` number
- `initialSoc` number
- `minArrivalSoc` number
- `reserveSoc` number
- `ambientC` number
- `maxDetourKm` number
- `optimize` 'time'
- `includeGeometry` boolean

## Response `200`

A plan. Note that feasible:false is also a 200 — the request was valid, the trip just cannot be completed with this vehicle and the chargers we know about, and gap/reason explain where it breaks.

- EvRouteResponse
  - `feasible` boolean — False when the trip cannot be completed; see gap and reason
  - `summary` object, nullable — Null when feasible is false
    - `distanceKm` number
    - `driveMin` integer
    - `chargeMin` integer — Total time at chargers, including plug overhead
    - `totalMin` integer
    - `chargeActiveMin` integer — Time actually delivering energy
    - `plugOverheadMin` integer — Fixed per-stop cost of pulling in and plugging in
    - `offRouteMin` integer — Time spent leaving the direct route to reach chargers
    - `offRouteKm` number
    - `energyKwh` number
    - `arrivalSocPct` number
    - `chargeStops` integer
    - `estChargeCostEur` number, nullable — Sum over stops with a known price; null when no stop has one
    - `stopsWithKnownPrice` integer
  - `warnings` string[] — Non-fatal caveats about this plan, e.g. that the route through the chosen chargers is longer than the direct one
  - `stops` EvChargeStop[]
    - `name` string
    - `owners` string[]
    - `lat` number
    - `lon` number
    - `address` object
      - `street` string
      - `city` string
      - `zip` string, nullable
      - `country` string
    - `maxPowerKw` number, nullable
    - `stationCount` integer
    - `routeKm` number — Distance along the route where this stop sits
    - `arrivalSocPct` number
    - `departSocPct` number
    - `chargeMin` integer — Time at the stop, including plug-in overhead
    - `kwhAdded` number
    - `estCostEur` number, nullable — Null where the operator publishes no price for this connector
    - `detourKm` number — Extra distance to leave the route for this charger
    - `alternatives` object[] — Nearby chargers that could substitute for this stop
  - `legs` EvRouteLeg[]
    - `fromKm` number
    - `toKm` number
    - `distanceKm` number
    - `driveMin` integer
    - `energyKwh` number
  - `vehicle` object — The vehicle the plan was computed for, resolved from vehicleId or the custom parameters
    - `id` string, nullable
    - `label` string
    - `usableBatteryKwh` number
    - `consumptionWhPerKm` number
    - `dcMaxKw` number
    - `dcPorts` string[]
  - `gap` object — Present only when feasible is false: the stretch that cannot be crossed
    - `fromKm` number
    - `toKm` number
    - `neededKwh` number
  - `reason` string — Present only when feasible is false
  - `geometry` string — Encoded polyline of the final route; present only when includeGeometry=true
  - `attribution` string[] — Required credit for the data behind this response. Display it wherever you present the plan — it is a license condition of OpenStreetMap (ODbL), openrouteservice, and the Open EV Data catalog, not optional metadata.
  - `disclaimer` string

## Other responses

- `400` — Missing or invalid query parameter, a route outside the European service area, or one longer than 2500 km
- `403` — Invalid or missing API key, suspended account, or inactive subscription
- `429` — Monthly quota exhausted or per-minute rate limit exceeded. Quota responses carry resetDate; rate-limit responses carry a Retry-After header.
- `502` — Upstream routing or charging data unavailable. Also covers an upstream that stalled past our timeout.
- `503` — Routing provider quota exhausted. The budget is shared by every caller and resets daily, so the response carries retryAfterSeconds and a Retry-After header — retrying sooner will not succeed. Any other upstream failure is returned as 502.

---

[API](https://skmtc.dev/carapi/apis/carapi-dev-automotive-data-api.md) · [All operations](https://skmtc.dev/carapi/apis/carapi-dev-automotive-data-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/carapi/carapi-dev-automotive-data-api/revisions/cf1d4e12baca/schema)
