Pendelzeit-API

Einstieg in 5 Minuten

Die Pendelzeit-API berechnet, wie lange man von einer Startadresse zu bis zu 100 Standorten braucht – mit PKW, ÖPNV, Fahrrad, E-Bike und zu Fuß. Sie ist zustandslos: Jede Anfrage enthält Start und Ziele vollständig, die API speichert weder Standorte noch Startadressen.

Der typische Ablauf hat zwei Schritte:

  1. Adresse auswählen lassen: Der Endnutzer tippt, die API liefert Vorschläge (GET /v1/address/suggest), der Endnutzer wählt einen aus. Dessen Koordinate ist der Start.
  2. Reisezeiten abfragen: Start und Ziele an POST /v1/travel-times schicken. Die Antwort ist nach Reisezeit sortiert.

Statt einer Adresse kann der Start auch direkt eine Koordinate sein, z. B. aus der Standortfreigabe des Browsers.

Was Sie brauchen

Mit curl (vom Server, geheimer Key)

Adressvorschläge zur Eingabe „Ulm Münsterplatz“:

Shell
curl -sS --fail-with-body 'https://api.pendelzeit.de/v1/address/suggest?q=Ulm+M%C3%BCnsterplatz&limit=3' \
  -H 'Authorization: Bearer pz_sk_IHR_GEHEIMER_KEY'

Die Antwort enthält je Vorschlag einen Anzeigetext (label) und die Koordinate (location):

JSON
{
  "suggestions": [
    {
      "label": "Münsterplatz 1, 89073 Ulm",
      "type": "house",
      "address": { "street": "Münsterplatz", "houseNumber": "1", "postcode": "89073", "city": "Ulm", "district": "Mitte", "state": "Baden-Württemberg", "countryCode": "DE" },
      "location": { "lat": 48.398511, "lon": 9.992502 }
    },
    { "label": "Münsterplatz, 89073 Ulm", "type": "street", "…": "…" }
  ],
  "attribution": [ { "text": "© OpenStreetMap-Mitwirkende, ODbL", "url": "https://www.openstreetmap.org/copyright" } ]
}

Reisezeiten von dort zu drei Standorten, sortiert nach ÖPNV:

Shell
curl -sS --fail-with-body 'https://api.pendelzeit.de/v1/travel-times' \
  -H 'Authorization: Bearer pz_sk_IHR_GEHEIMER_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "origin": { "lat": 48.39842, "lon": 9.99173 },
    "destinations": [
      { "id": "neu-ulm", "label": "Neu-Ulm Bahnhof", "location": { "lat": 48.39265, "lon": 10.01060 } },
      { "id": "blaubeuren", "label": "Blaubeuren", "location": { "lat": 48.41210, "lon": 9.78480 } },
      { "id": "guenzburg", "label": "Günzburg", "location": { "lat": 48.45360, "lon": 10.27740 } }
    ],
    "modes": ["transit", "car", "bike"],
    "sortBy": "transit"
  }'

Gekürzte Antwort:

JSON
{
  "results": [
    {
      "id": "neu-ulm",
      "label": "Neu-Ulm Bahnhof",
      "location": { "lat": 48.39265, "lon": 10.0106 },
      "modes": {
        "transit": {
          "status": "ok",
          "durationMinutes": 18,
          "arrivalWindow": { "from": "07:30", "to": "08:30", "date": "2026-10-13" },
          "details": { "transfers": 0, "walkToStopMinutes": 7, "departure": "2026-10-13T07:25:00+02:00", "arrival": "2026-10-13T07:43:00+02:00", "lines": ["71"] },
          "routeUrls": { "googleMaps": "https://www.google.com/maps/dir/?api=1&origin=48.39842%2C9.99173&destination=48.39265%2C10.01060&travelmode=transit" }
        },
        "car": {
          "status": "ok", "durationMinutes": 10, "distanceKm": 2.5,
          "trafficNote": { "code": "no_live_traffic", "text": "Übliche Fahrzeit im Berufsverkehr, ohne aktuelle Verkehrslage" },
          "routeUrls": { "googleMaps": "…" }
        },
        "bike": { "status": "ok", "durationMinutes": 9, "distanceKm": 2.2, "routeUrls": { "googleMaps": "…" } }
      }
    },
    { "id": "blaubeuren", "…": "transit 40 Min., car 42 Min., bike 77 Min." },
    { "id": "guenzburg", "…": "transit 40 Min., car 33 Min., bike over_limit" }
  ],
  "meta": {
    "counts": { "requested": 3, "returned": 3, "filtered": 0 },
    "referenceDate": "2026-10-13",
    "defaultArrivalWindow": { "from": "07:30", "to": "08:30" },
    "limits": { "maxDestinations": 100, "maxDurationMinutes": 90 }
  },
  "attribution": [
    { "text": "© OpenStreetMap-Mitwirkende, ODbL", "url": "https://www.openstreetmap.org/copyright" },
    { "text": "Fahrplandaten DELFI e. V., CC BY 4.0", "url": "https://www.delfi.de" }
  ]
}

Abgerufen gegen die lokale API (Fahrplan Oktober 2026); die Werte hängen vom aktuellen Fahrplan ab. Alle Felder beschreibt die API-Referenz.

Mit JavaScript (im Browser, öffentlicher Key)

Ein öffentlicher Key funktioniert nur auf den Domains, für die er freigegeben ist. Der Browser sendet die Domain automatisch im Origin-Header mit.

JavaScript
const API = 'https://api.pendelzeit.de';
const KEY = 'pz_pk_IHR_OEFFENTLICHER_KEY';

async function api(path, options = {}) {
  const response = await fetch(API + path, {
    ...options,
    headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json', ...options.headers },
  });
  if (!response.ok) {
    const problem = await response.json(); // Problem Details (RFC 9457)
    throw new Error(`${problem.status} ${problem.title}: ${problem.detail ?? ''}`);
  }
  return response.json();
}

// 1. Vorschläge zur Eingabe holen, der Endnutzer wählt einen aus (hier: den ersten)
const { suggestions } = await api('/v1/address/suggest?q=' + encodeURIComponent('Ulm Münsterplatz'));
const start = suggestions[0].location;

// 2. Reisezeiten zu den Standorten
const result = await api('/v1/travel-times', {
  method: 'POST',
  body: JSON.stringify({
    origin: start,
    destinations: [
      { id: 'neu-ulm', label: 'Neu-Ulm Bahnhof', location: { lat: 48.39265, lon: 10.0106 } },
      { id: 'blaubeuren', label: 'Blaubeuren', location: { lat: 48.4121, lon: 9.7848 } },
    ],
    modes: ['transit', 'walk'],
  }),
});

for (const r of result.results) {
  const t = r.modes.transit;
  console.log(r.label, t.status === 'ok' ? `${t.durationMinutes} Min. mit ÖPNV` : t.status);
}

Was Sie außerdem wissen sollten