---
title: "Door-to-door journey planning (the core)."
method: GET
path: "/v1/plan"
tags: ["routing"]
---

# Door-to-door journey planning (the core).

`GET /v1/plan`

## Request

- Base URL: `https://pt-api.internal.example`
- URL: `https://pt-api.internal.example/v1/plan`
- Auth: none declared

## Query parameters

- `from` string, required
- `to` string, required
- `time` string
- `arrive_by` boolean
- `results` integer
- `max_transfers` integer
- `modes` string
- `cursor` string
- `lang` string
- `snap_radius_m` integer

## Response `200`

Journey planning result (possibly empty).

- PlanResponse
  - `itineraries` Itinerary[], required
    - `start` string, nullable, required
    - `end` string, nullable, required
    - `duration_s` integer, nullable, required
    - `transfers` integer, required
    - `legs` Leg[], required
      - `mode` 'WALK' | 'BIKE' | 'CAR' | 'RAIL' | 'BUS' | 'COACH' | 'TRAM' | 'SUBWAY' | 'FERRY' | 'AIRPLANE' | 'FUNICULAR' | 'AERIAL_LIFT' | 'TRANSIT' | 'OTHER', required
      - `from` Endpoint, required
        - `name` string, nullable, required
        - `lat` number, nullable, required
        - `lon` number, nullable, required
        - `stop_id` string: opaque; do not parse
        - `departure` StopEvent
          - `scheduled` string, nullable, required
          - `realtime` string, nullable, required: null until v2 RT overlay
          - `platform` string, nullable
        - `arrival` StopEvent
          - `scheduled` string, nullable, required
          - `realtime` string, nullable, required: null until v2 RT overlay
          - `platform` string, nullable
      - `to` Endpoint, required
        - `name` string, nullable, required
        - `lat` number, nullable, required
        - `lon` number, nullable, required
        - `stop_id` string: opaque; do not parse
        - `departure` StopEvent
          - `scheduled` string, nullable, required
          - `realtime` string, nullable, required: null until v2 RT overlay
          - `platform` string, nullable
        - `arrival` StopEvent
          - `scheduled` string, nullable, required
          - `realtime` string, nullable, required: null until v2 RT overlay
          - `platform` string, nullable
      - `start` string, nullable, required
      - `end` string, nullable, required
      - `duration_s` integer, nullable, required
      - `distance_m` integer
      - `geometry` string, nullable: encoded polyline (present on WALK legs too)
      - `role` 'first_mile' | 'last_mile' | 'transfer' | 'direct': WALK legs only. first/last_mile = walk from/to the door; transfer = between transit legs; direct = a walk-only itinerary (no transit). Consecutive WALK legs are always merged into one.
      - `distance_kind` 'walk' | 'straight': WALK legs: street-routed vs straight-line estimate
      - `route` Route
        - `id` string, nullable
        - `short_name` string, nullable: Raw route_short_name from the feed (may be an internal code, e.g. CZ CIS '766420').
        - `long_name` string, nullable
        - `display_name` string, nullable: Public-facing line designation to show the traveller (what is marked on the vehicle / in national timetables), e.g. "420", "R12", "S8". Derived from short_name with per-feed internal-code cleanup (CZ CIS six-digit -> line number); equals short_name where it is already public. Pair with `mode` (e.g. render "Bus 420"). Null only when the feed carries no usable name.
        - `agency` string, nullable
        - `headsign` string, nullable
      - `trip_id` string, nullable
      - `intermediate_stops` integer
  - `cursors` Cursors, required
    - `earlier` string, nullable
    - `later` string, nullable
  - `diagnostics` string, nullable: Set (non-null) only when itineraries is empty — a clear human reason, never a silent empty.
  - `resolved_from` ResolvedFrom: Per-endpoint station substitution (fix #3). `from`/`to` are null when the endpoint was used as requested; otherwise they report the served station the planner actually departed from / arrived at, so the UI can show "departing from <used_name>, <distance_m> m away". On a street-routed graph the planner sends the RAW coordinates to the engine, which walks door<->stop itself, so a coordinate endpoint is used as-is and this stays null — the first_mile/last_mile WALK legs carry the real access path. It is only populated when the resolve-then-route FALLBACK actually substituted a stop (e.g. an unroutable node) and that itinerary is the best option.
    - `from` ResolvedEndpoint
      - `requested` string, required: The original stop id or 'lat,lon' the client sent.
      - `used_stop_id` string, required: The served stop actually routed from/to (opaque).
      - `used_name` string, nullable, required
      - `distance_m` integer, required: Metres from the requested point to the used station.
    - `to` ResolvedEndpoint
      - `requested` string, required: The original stop id or 'lat,lon' the client sent.
      - `used_stop_id` string, required: The served stop actually routed from/to (opaque).
      - `used_name` string, nullable, required
      - `distance_m` integer, required: Metres from the requested point to the used station.
  - `attributions_url` string, required

## Other responses

- `400`: RFC 7807 problem.

---

[API](https://skmtc.dev/alltimetables/apis/european-journey-planner-api.md) · [All operations](https://skmtc.dev/alltimetables/apis/european-journey-planner-api/llms.txt) · [OpenAPI document](https://skmtc.dev/alltimetables/apis/european-journey-planner-api/revisions/3216e9384a8b?raw)
