Schnellstart

In 3 Schritten einsatzbereit:

1. API-Schlüssel anfordern

Registrieren Sie sich unter portal.napspan.com, um einen kostenlosen API-Schlüssel zu erhalten (14-Tage-Testphase, 1.000 Anfragen/Tag).

2. Erste Anfrage senden

curl
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://api.napspan.com/api/v1/events?jurisdiction=DEU&limit=5"

3. Antwort verarbeiten

Antwort-JSON
{
  "data": [
    {
      "id": "de-evt-a100-001",
      "type": "construction",
      "sub_type": "roadwork",
      "severity": "minor",
      "title": "Roadworks on A100 Berlin",
      "description": "Lane closure between Spandauer Damm and Kaiserdamm...",
      "latitude": 52.5167,
      "longitude": 13.2833,
      "jurisdiction": "DE",
      "start_time": "2026-03-23T07:00:00Z"
    }
  ],
  "total": 90,
  "limit": 5,
  "has_more": true
}

OpenAPI-Spezifikation

Die vollständige maschinenlesbare API-Spezifikation — enthält ausschließlich Daten-Endpunkte (Ereignisse, Funktionen, Karte, Analytik, LKW-Korridor, Kraftstoffpreise, Metadaten). Erzeugen Sie damit Clients, importieren Sie die Spezifikation in Postman oder Insomnia oder nutzen Sie die interaktive Referenz.

Authentifizierung

Alle API-Anfragen erfordern einen API-Schlüssel. Übergeben Sie ihn über den X-API-Key-Header (empfohlen) oder den api_key-Query-Parameter.

Header (empfohlen)
curl -H "X-API-Key: sk_live_abc123" https://api.napspan.com/api/v1/events
Query-Parameter
curl "https://api.napspan.com/api/v1/events?api_key=sk_live_abc123"

Fehler & Rate-Limits

Die API liefert Standard-HTTP-Statuscodes zurück. Rate-Limit-Header sind in jeder Antwort enthalten.

StatusBedeutung
200Erfolgreich
400Fehlerhafte Anfrage (fehlende/ungültige Parameter)
401Fehlender oder ungültiger API-Schlüssel
403Tarif-Limit überschritten (Zuständigkeitsbereich, Funktionssperre, abgelaufene Testphase)
429Rate-Limit überschritten — bitte nach Retry-After Sekunden erneut versuchen
500Serverfehler — bitte erneut versuchen oder Support kontaktieren

Jede Fehlerantwort enthält ein lesbares error-Feld. Ein 403 aufgrund einer Tarifgrenze enthält zusätzlich einen stabilen code, damit Ihre Integration darauf reagieren kann, ohne den Meldungstext auszuwerten — werten Sie code aus und zeigen Sie error an.

{
  "error": "add a jurisdiction filter to this request, e.g. ?jurisdiction=DE-BY (up to 1 per request, comma-separated). The Free plan scopes queries to specific jurisdictions; a higher plan can query all jurisdictions at once.",
  "code": "plan_jurisdiction",
  "plan": "free",
  "plan_name": "Free",
  "upgrade_url": "https://portal.napspan.com/billing",
  "docs_url": "/reference.html"
}

Codes: plan_jurisdiction, plan_batch_size, plan_event_time_range, plan_event_status, plan_archived_event, plan_inactive_features, plan_geojson, plan_analytics, plan_truck, trial_expired, subscription_expired. Bei anderen Fehlern fehlen diese Felder, behandeln Sie sie daher als optional.

Ereignisse

Verkehrsereignisse umfassen Vorfälle, Baustellen, Sperrungen, Wetterwarnungen, Beschränkungen und Sonderveranstaltungen in allen aktiven Zuständigkeitsbereichen.

GET /api/v1/events

ParameterTypBeschreibung
idsstringKomma-getrennte Ereignis-IDs für die Stapelabfrage. Ist ids gesetzt, werden alle anderen Filter ignoriert und die Paginierung deaktiviert — die Antwort enthält stets alle Ergebnisse in einer Seite, unabhängig vom status. Begrenzt durch max_batch_size des Tarifs.
jurisdictionstringFilter nach ISO-Länder-/Regionscode (z. B. DE, FR, AT) im Free-Tarif erforderlich. Abfragen eines Primärcodes erweitern sich automatisch auf alle Mitglieder seiner Gruppe, sofern eine existiert.
typestringFilter nach Ereignistyp: incident, construction, closure, weather, special_event, advisory, restriction
severitystringFilter: minor, moderate, major, critical
lat, lng, radius_kmnumberUmkreissuche (z. B. lat=52.52&lng=13.40&radius_km=50)
bboxstringBegrenzungsrahmen: minLng,minLat,maxLng,maxLat
limitintErgebnisse pro Seite (Standard 100, Maximum je nach Tarif)
offsetintPaginierungs-Offset
Stapelabfrage — bekannte Ereignis-IDs in einer Anfrage abrufen
curl -H "X-API-Key: $KEY" \
  "https://api.napspan.com/api/v1/events?ids=de-evt-a9-001,fr-evt-a1-002,at-evt-a4-015"
# Ereignisse in der Nähe von Berlin, DE
curl -H "X-API-Key: $KEY" \
  "https://api.napspan.com/api/v1/events?jurisdiction=DEU&lat=52.52&lng=13.40&radius_km=100"
import requests

resp = requests.get("https://api.napspan.com/api/v1/events", params={
    "jurisdiction": "DE",
    "lat": 52.52, "lng": 13.40, "radius_km": 100
}, headers={"X-API-Key": KEY})
events = resp.json()["data"]
const res = await fetch(
  `https://api.napspan.com/api/v1/events?jurisdiction=DEU&lat=52.52&lng=13.40&radius_km=100`,
  { headers: { "X-API-Key": KEY } }
);
const { data, total } = await res.json();
req, _ := http.NewRequest("GET",
    "https://api.napspan.com/api/v1/events?jurisdiction=DEU&lat=52.52&lng=13.40&radius_km=100", nil)
req.Header.Set("X-API-Key", key)
resp, _ := http.DefaultClient.Do(req)
{
  "data": [
    {
      "id": "de-evt-a100-001",
      "source_id": "EVT-2026-04521",
      "source": "de",
      "jurisdiction": "DE",
      "type": "incident",
      "severity": "major",
      "status": "active",
      "title": "Multi-vehicle collision on A100 westbound near Spandauer Damm",
      "description": "Two right lanes blocked. Emergency services on scene.",
      "affected_roads": ["A100"],
      "direction": "westbound",
      "lanes_affected": "2 of 4 lanes blocked",
      "start_time": "2026-03-29T14:30:00Z",
      "end_time": null,
      "estimated_end_time": "2026-03-29T17:00:00Z",
      "latitude": 52.5167,
      "longitude": 13.2833,
      "road_class": "motorway",
      "last_updated": "2026-03-29T14:45:00Z",
      "created_at": "2026-03-29T14:30:00Z"
    }
  ],
  "total": 42,
  "limit": 100,
  "offset": 0,
  "has_more": false
}

GET /api/v1/events/{id}

Einzelnes Ereignis nach ID. Liefert das vollständige Ereignis mit allen Metadatenfeldern zurück.

Antwort
{
  "id": "de-evt-a100-001",
  "source_id": "EVT-2026-04521",
  "source": "de",
  "jurisdiction": "DE",
  "type": "incident",
  "severity": "major",
  "status": "active",
  "title": "Multi-vehicle collision on A100 westbound near Spandauer Damm",
  "description": "Two right lanes blocked. Emergency services on scene.",
  "location": { "type": "Point", "coordinates": [13.2833, 52.5167] },
  "affected_roads": ["A100"],
  "direction": "westbound",
  "lanes_affected": "2 of 4 lanes blocked",
  "start_time": "2026-03-29T14:30:00Z",
  "end_time": null,
  "estimated_start_time": null,
  "estimated_end_time": "2026-03-29T17:00:00Z",
  "source_created_at": "2026-03-29T14:28:55Z",
  "source_updated_at": "2026-03-29T14:45:00Z",
  "latitude": 52.5167,
  "longitude": 13.2833,
  "road_class": "motorway",
  "metadata": { "vehicles_involved": 3 },
  "last_updated": "2026-03-29T14:45:00Z",
  "created_at": "2026-03-29T14:30:00Z",
  "archived_at": null,
  "archive_reason": null
}

archive_reason ist null, solange das Ereignis aktiv ist. Sobald ein Ereignis archiviert wird, trägt es einen von zwei Werten:

  • observed — der Upstream-Feed lieferte eine erfolgreiche Antwort und das Ereignis war nicht mehr enthalten, also haben wir es regulär archiviert. Das ist der Normalfall.
  • stale_sweep — der reguläre Archivierungspfad konnte das Ereignis nicht zurückziehen (Upstream-Antworten waren leer oder fehlerhaft) und ein Sicherheits-Sweep hat es nach etwa poll_interval × sweep_factor (Standardfaktor 15) ohne neue Beobachtung erzwungen archiviert. Behandeln Sie archived_at für solche Datensätze als „vermutlich beendet bis"-Zeitstempel, nicht als exaktes Ende. Ein dauerhaft hoher stale_sweep-Anteil bei einer Quelle ist ein Signal, dass der Upstream-Feed Beendigungs-Records unzuverlässig liefert.

GET /api/v1/events/geojson Starter+

Gleiche Parameter wie /events, liefert eine GeoJSON-FeatureCollection zurück. Direkt verwendbar mit Leaflet, Mapbox oder jedem GeoJSON-fähigen Tool. Content-Type: application/geo+json.

Antwort
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": { "type": "Point", "coordinates": [13.2833, 52.5167] },
      "properties": {
        "id": "de-evt-a100-001",
        "source": "de",
        "jurisdiction": "DE",
        "type": "incident",
        "severity": "major",
        "status": "active",
        "title": "Multi-vehicle collision on A100 westbound near Spandauer Damm",
        "affected_roads": ["A100"],
        "direction": "westbound",
        "start_time": "2026-03-29T14:30:00Z"
      }
    }
  ]
}

Funktionen

Funktionen (Features) sind Nicht-Ereignis-Daten: Kameras, Wetterstationen, Rastplätze, Schilder, LKW-Parkplätze, EV-Ladestationen und mehr. Alle Typen nutzen denselben Endpunkt — geben Sie einen einzelnen type an, oder verwenden Sie group, um alle Typen einer Kategorie auf einmal abzurufen (z. B. liefert group=trucking neun LKW-bezogene Typen in einer Anfrage).

GET /api/v1/features

ParameterTypBeschreibung
typestringFunktionstyp (siehe Funktionstypen). Entweder type oder group ist erforderlich.
groupstringFunktionsgruppen-ID (siehe Funktionsgruppen). Bequeme Erweiterung auf alle Typen der Gruppe. Wenn zusammen mit radius_km verwendet, ist der Radius auf 200 km begrenzt — eine weitere Suche über alle Typen einer Gruppe lässt sich nicht rechtzeitig beantworten und liefert 400 statt einer Zeitüberschreitung. Für unbegrenzte Umkreissuchen einen einzelnen type abfragen.
jurisdictionstringFilter nach Zuständigkeitscode. Abfragen eines Primärcodes erweitern sich automatisch auf alle Mitglieder seiner Gruppe, sofern eine existiert.
activebooltrue, um nur aktive Funktionen zurückzugeben
lat, lng, radius_kmnumberUmkreissuche
bboxstringBegrenzungsrahmen: minLng,minLat,maxLng,maxLat
starts_after, starts_beforestringZeitfensterfilter auf den geplanten Beginn (fällt auf den tatsächlichen Beginn zurück). RFC3339 oder YYYY-MM-TT.
ends_after, ends_beforestringZeitfensterfilter auf das geplante Ende. Zeitlich offene Einträge (bekannter Beginn, kein Ende) erfüllen ends_after, aber nie ends_before.
limit, offsetintPaginierung

Die Zeitfensterfilter gelten für zeitlich begrenzte Feature-Typen — future_construction, alerts, special_events, truck_restrictions und ähnliche. Werden beide Grenzen gesetzt, liefert die Abfrage alle Einträge, die sich mit dem Zeitraum überschneiden: ?starts_before=2026-09-01&ends_after=2026-08-01 gibt jeden Eintrag zurück, der im August 2026 zu irgendeinem Zeitpunkt aktiv ist. Features ganz ohne Datumsangaben werden aus Zeitfensterabfragen ausgeschlossen.

Hinweis zur Abdeckung: Bislang veröffentlicht keine NAPSPAN-Quelle geplante Start- und Enddaten. Diese Filter liefern daher derzeit bei jedem EU-Feature-Typ ein leeres Ergebnis. Die Parameter gehören zum gemeinsamen API-Vertrag und liefern automatisch Ergebnisse, sobald eine Quelle Zeitpläne veröffentlicht — bis dahin sollten Sie nicht mit EU-Daten aus diesen Filtern rechnen.

Jeder Datensatz enthält ein boolesches has_details-Feld. Bei true liefert die Quelle mehr Daten, als die Listenzeile mitführt — rufen Sie GET /features/{id}/details auf (oder bündeln Sie Aufrufe mit POST /features/details/batch weiter unten), um sie zu erhalten. Bei false enthält die Listenzeile bereits alles, was die Quelle für dieses (source, feature_type)-Paar veröffentlicht.

Beispiel: Kameras in der Nähe von Madrid
curl -H "X-API-Key: $KEY" \
  "https://api.napspan.com/api/v1/features?type=cameras&jurisdiction=ESP&lat=40.42&lng=-3.70&radius_km=50"
Beispiel: Alle LKW-Layer in Deutschland (eine Anfrage)
curl -H "X-API-Key: $KEY" \
  "https://api.napspan.com/api/v1/features?group=trucking&jurisdiction=DEU"

Die Form von properties variiert je nach feature_type. Die folgenden Beispiele zeigen die typischen Felder für die häufigsten Typen — wählen Sie einen Tab aus.

{
  "data": [
    {
      "id": "de-cam-a8-muc-01",
      "source": "de",
      "jurisdiction": "DE",
      "feature_type": "cameras",
      "name": "A8 Munich Ost",
      "latitude": 48.1391,
      "longitude": 11.6754,
      "road_name": "A8",
      "direction": "eastbound",
      "is_active": true,
      "properties": {
        "url": "https://verkehr.bayern.de/cameras/a8_muc_ost.jpg",
        "video_url": null
      },
      "last_updated": "2026-03-29T14:50:00Z",
      "has_details": true
    }
  ],
  "total": 2080, "limit": 100, "offset": 0, "has_more": true
}
{
  "data": [
    {
      "id": "at-wx-a4-vie",
      "jurisdiction": "AT",
      "feature_type": "weather_stations",
      "name": "A4 Vienna Weather Station",
      "latitude": 48.2082, "longitude": 16.3738,
      "road_name": "A4",
      "is_active": true,
      "properties": {
        "temperature": 12.4,
        "wind_speed": 18.2,
        "wind_direction": "NW",
        "precipitation": "light_rain",
        "road_surface": "wet",
        "humidity": 78,
        "visibility": 12.0
      },
      "last_updated": "2026-03-29T14:45:00Z",
      "has_details": false
    }
  ],
  "total": 2150, "limit": 100, "offset": 0, "has_more": true
}
{
  "data": [
    {
      "id": "fr-dms-a4-paris-512",
      "jurisdiction": "FR",
      "feature_type": "signs",
      "name": "A4 EB DMS at PR 12",
      "latitude": 48.8566, "longitude": 2.4500,
      "road_name": "A4",
      "direction": "eastbound",
      "is_active": true,
      "properties": {
        "message": "ACCIDENT 5 KM / 2 VOIES FERMÉES / RALENTISSEMENTS",
        "posted_at": "2026-03-29T14:35:00Z",
        "sign_type": "DMS"
      },
      "last_updated": "2026-03-29T14:50:00Z",
      "has_details": true
    }
  ],
  "total": 3120, "limit": 100, "offset": 0, "has_more": true
}
{
  "data": [
    {
      "id": "nl-ev-amsterdam-a2-12",
      "source": "ndw",
      "jurisdiction": "NL",
      "feature_type": "ev_charging",
      "name": "Fastned Amsterdam Zuid",
      "latitude": 52.3399, "longitude": 4.8732,
      "is_active": true,
      "properties": {
        "network": "Fastned",
        "connector_types": ["CCS2", "CHAdeMO", "Type2"],
        "max_kw": 300,
        "port_count": 8,
        "access": "public",
        "pricing": "€0.69/kWh"
      },
      "last_updated": "2026-03-15T00:00:00Z",
      "has_details": true
    }
  ],
  "total": 42100, "limit": 100, "offset": 0, "has_more": true
}
{
  "data": [
    {
      "id": "de-bridge-a8-iller",
      "source": "bast",
      "feature_type": "bridge_clearances",
      "name": "A8 Iller Viaduct",
      "latitude": 48.21, "longitude": 10.05,
      "is_active": true,
      "properties": {
        "min_vertical_clearance_m": 4.50,
        "posting_status": "open",
        "weight_limit_tons": null,
        "year_built": 1972,
        "structure_kind": "prestressed concrete",
        "bridge_number": "BAST-7811-A8"
      },
      "last_updated": "2026-01-15T00:00:00Z",
      "has_details": false
    }
  ],
  "total": 39800, "limit": 100, "offset": 0, "has_more": true
}
{
  "data": [
    {
      "id": "de-tp-a7-soltau",
      "jurisdiction": "DE",
      "feature_type": "truck_parking",
      "name": "A7 Truck Parking Soltau-Ost",
      "latitude": 52.99, "longitude": 9.83,
      "is_active": true,
      "properties": {
        "capacity": 62,
        "available": 12,
        "availability_pct": 19,
        "amenities": ["restrooms", "vending", "lighting"],
        "observed_at": "2026-03-29T14:30:00Z"
      },
      "last_updated": "2026-03-29T14:50:00Z",
      "has_details": false
    }
  ],
  "total": 580, "limit": 100, "offset": 0, "has_more": true
}

GET /api/v1/features/types

Liefert jeden aktiven feature_type mit Gesamt- und Aktiv-Zählwerten. 2 Minuten gecacht. Nützlich, um eine UI-Auswahl auf tatsächlich vorhandene Datentypen zu beschränken.

Antwort
[
  { "type": "cameras",           "count": 8120,  "active_count": 7842 },
  { "type": "weather_stations",  "count": 2150,  "active_count": 2098 },
  { "type": "signs",             "count": 3120,  "active_count": 2987 },
  { "type": "ev_charging",       "count": 42100, "active_count": 42100 },
  { "type": "bridge_clearances", "count": 39800, "active_count": 39800 }
]

GET /api/v1/features/groups

Liefert die 16-Gruppen-Funktionstaxonomie mit den zugehörigen Funktionstypen. Verwenden Sie das Feld id als group-Parameter bei /features. 1 Stunde lang gecacht. Die vollständige Tabelle finden Sie unter Funktionsgruppen.

Antwort (gekürzt auf 2 von 16 Gruppen)
[
  {
    "id": "imagery",
    "name": "Imagery",
    "description": "Live traffic camera feeds",
    "sort_order": 1,
    "feature_types": ["cameras"]
  },
  {
    "id": "trucking",
    "name": "Trucking & Commercial Vehicles",
    "description": "Truck restrictions, routes, parking, inspections",
    "sort_order": 8,
    "feature_types": [
      "truck_restrictions", "weight_restrictions", "bridge_clearances",
      "truck_routes", "freight_corridors", "truck_parking",
      "truck_rest_areas", "weigh_stations", "inspection_stations"
    ]
  }
]

GET /api/v1/features/{id}/details

Lazy-geladene Details für eine einzelne Funktion. Einige Quellen liefern in der Listenansicht nur kompakte Felder; dieser Endpunkt liefert das vollständige properties-Objekt sowie ein detail_available-Flag und einen cache-Hinweis (hit / miss / none / poll / error). Anhand des has_details-Feldes der Listenantwort lässt sich entscheiden, ob dieser Aufruf sinnvoll ist.

Antwort
{
  "data": {
    "id": "de-cam-a8-muc-01",
    "feature_type": "cameras",
    "name": "A8 Munich Ost",
    "latitude": 48.1391, "longitude": 11.6754,
    "properties": {
      "url": "https://verkehr.bayern.de/cameras/a8_muc_ost.jpg",
      "video_url": "https://verkehr.bayern.de/cameras/a8_muc_ost.m3u8",
      "views": [
        { "name": "Eastbound", "url": "https://verkehr.bayern.de/cameras/a8_muc_ost_eb.jpg" },
        { "name": "Westbound", "url": "https://verkehr.bayern.de/cameras/a8_muc_ost_wb.jpg" }
      ]
    }
  },
  "detail_available": true,
  "cache": "miss"
}

POST /api/v1/features/details/batch

Details für viele Funktionen in einem Aufruf abrufen. Das Pro-ID-Caching ist identisch mit dem Einzelaufruf-Endpunkt (Redis-basiert, nach ID indiziert) — eine Stapelanfrage, die sich mit vorherigen Aufrufen überschneidet, verursacht für den Überlappungsteil keine zusätzlichen Kosten. Teilerfolge bleiben erhalten: Schlägt ein einzelner Upstream-Abruf fehl, wird in dessen Eintrag cache: "error" gesetzt, ohne dass die gesamte Anfrage scheitert; fehlende IDs erscheinen mit not_found: true. Die Stapelgröße ist durch max_batch_size des Tarifs begrenzt.

Anfrage
curl -X POST -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["de-cam-a8-muc-01", "de-cam-a9-nbg-04", "missing-id"]}' \
  "https://api.napspan.com/api/v1/features/details/batch"
Antwort (paralleles Array, ein Eintrag pro angefragter ID, in derselben Reihenfolge)
{
  "count": 3,
  "data": [
    {
      "id": "de-cam-a8-muc-01",
      "data": { "id": "de-cam-a8-muc-01", "name": "A8 Munich Ost", "properties": { "url": "…", "views": ["…"] } },
      "detail_available": true,
      "cache": "hit"
    },
    {
      "id": "de-cam-a9-nbg-04",
      "data": { "id": "de-cam-a9-nbg-04", "name": "A9 Nürnberg Nord" },
      "detail_available": true,
      "cache": "miss"
    },
    {
      "id": "missing-id",
      "detail_available": false,
      "cache": "",
      "not_found": true
    }
  ]
}

LKW-Korridor Pro+

Finden Sie alle LKW-Beschränkungen entlang einer Route. Erzeugt einen gepufferten Korridor zwischen zwei Punkten und liefert jede Brückendurchfahrtshöhe, Gewichtsbeschränkung, LKW-Route und Restriktion zurück, die diesen schneidet. Verwendet PostGIS-Geo-Abfragen für eine präzise Großkreis-Pufferung.

GET /api/v1/truck/corridor

ParameterTypBeschreibung
from_lat ErforderlichnumberAusgangs-Breitengrad
from_lng ErforderlichnumberAusgangs-Längengrad
to_lat ErforderlichnumberZiel-Breitengrad
to_lng ErforderlichnumberZiel-Längengrad
buffer_kmnumberPufferabstand um Korridor (Standard 5, Maximum 50 km)
heightnumberFahrzeughöhe in Metern — filtert Durchfahrtshöhen darunter
weightnumberFahrzeuggewicht in metrischen Tonnen — filtert Gewichtsgrenzen darunter
jurisdictionstringAuf einen Zuständigkeitsbereich beschränken
limitintMaximale Ergebnisse (Standard 500, Maximum 2000)
Sucht in: bridge_clearances, bridges, weight_restrictions, truck_restrictions, truck_routes, freight_corridors, truck_parking
Beispiel: A8 München nach Salzburg
curl -H "X-API-Key: $KEY" \
  "https://api.napspan.com/api/v1/truck/corridor?\
from_lat=48.14&from_lng=11.58&\
to_lat=47.81&to_lng=13.05&\
buffer_km=10"
Antwort
{
  "corridor": {
    "from": [48.14, 11.58],
    "to": [47.81, 13.05],
    "buffer_km": 10,
    "distance_km": 142.5
  },
  "data": [
    {
      "id": "de-bridge-a8-iller",
      "feature_type": "bridge_clearances",
      "name": "A8 Iller Viaduct",
      "latitude": 48.21,
      "longitude": 10.05,
      "properties": {
        "posting_status": "open",
        "year_built": 1972,
        "_distance_km": "2.31"
      }
    },
    {
      "id": "at-trk-a1-salzburg",
      "feature_type": "truck_restrictions",
      "name": "Salzburg West",
      "properties": {
        "restriction": "Section ban for trucks > 7.5 t on weekends",
        "_distance_km": "0.45"
      }
    }
  ],
  "total": 98,
  "limit": 500
}

GET /api/v1/truck/corridor/geojson Pro+ GeoJSON

Gleiche Abfrage, liefert GeoJSON FeatureCollection zurück. Verwenden Sie dies, um Korridor-Ergebnisse direkt auf einer Leaflet- oder Mapbox-Karte darzustellen.

// LKW-Korridor auf Leaflet-Karte darstellen
const url = `https://api.napspan.com/api/v1/truck/corridor/geojson`
  + `?from_lat=48.14&from_lng=11.58&to_lat=47.81&to_lng=13.05&buffer_km=10`;

fetch(url, { headers: { "X-API-Key": KEY } })
  .then(r => r.json())
  .then(geojson => {
    L.geoJSON(geojson, {
      pointToLayer: (f, ll) => L.circleMarker(ll, { radius: 6 }),
      onEachFeature: (f, layer) => {
        layer.bindPopup(`<b>${f.properties.name}</b><br>${f.properties.feature_type}`);
      }
    }).addTo(map);
  });
import requests

resp = requests.get("https://api.napspan.com/api/v1/truck/corridor", params={
    "from_lat": 48.14, "from_lng": 11.58,
    "to_lat": 47.81,  "to_lng": 13.05,
    "buffer_km": 10
}, headers={"X-API-Key": KEY})

for feat in resp.json()["data"]:
    if feat["feature_type"] == "bridge_clearances":
        print(f"Bridge: {feat['name']} ({feat['properties'].get('posting_status', 'unknown')})")
Antwort (FeatureCollection)
{
  "type": "FeatureCollection",
  "corridor": {
    "from": [48.14, 11.58],
    "to": [47.81, 13.05],
    "buffer_km": 10,
    "distance_km": 142.5
  },
  "features": [
    {
      "type": "Feature",
      "geometry": { "type": "Point", "coordinates": [10.05, 48.21] },
      "properties": {
        "id": "de-bridge-a8-iller",
        "feature_type": "bridge_clearances",
        "name": "A8 Iller Viaduct",
        "min_vertical_clearance_m": 4.50,
        "posting_status": "open",
        "_distance_km": "2.31"
      }
    }
  ]
}

Analytik Pro+

Historische Analysen und Trends zu Ereignissen, Funktionen und Quell-Gesundheit. Alle Endpunkte erfordern den Pro- oder Enterprise-Tarif.

GET /api/v1/analytics/history/{id}

Lebenszyklus-Zeitleiste eines einzelnen Ereignisses — Erstellung, Schweregradänderungen, Spuränderungen, Endzeitänderungen, Archivierung.

Antwort
[
  { "id": 1, "event_id": "de-evt-a100-001",
    "change_type": "created",
    "old_value": null, "new_value": "active",
    "changed_at": "2026-03-29T14:30:00Z" },
  { "id": 2, "event_id": "de-evt-a100-001",
    "change_type": "severity_change",
    "old_value": "moderate", "new_value": "major",
    "changed_at": "2026-03-29T14:35:00Z" }
]

GET /api/v1/analytics/changes

Feed aktueller Änderungen über alle Ereignisse hinweg. Paginiert. Geeignet, um eine nachgelagerte Kopie des Ereigniszustands zu synchronisieren, ohne jedes Ereignis einzeln abzufragen.

Antwort
{
  "data": [
    { "id": 45, "event_id": "de-evt-a100-001",
      "change_type": "severity_change",
      "old_value": "moderate", "new_value": "major",
      "jurisdiction": "DE",
      "event_title": "Multi-vehicle collision on A100 westbound",
      "changed_at": "2026-03-29T14:35:00Z" }
  ],
  "total": 128, "limit": 100, "offset": 0, "has_more": true
}

GET /api/v1/analytics/clearance

P50- / P95- / Durchschnitts-Räumungszeiten nach Zuständigkeitsbereich und Ereignistyp. Berechnet aus start_timearchived_at.

Antwort
[
  { "jurisdiction": "DE", "event_type": "incident",
    "total_events": 320,
    "p50_minutes": 42.5, "p95_minutes": 175.0, "avg_minutes": 59.4 },
  { "jurisdiction": "AT", "event_type": "construction",
    "total_events": 150,
    "p50_minutes": 4320.0, "p95_minutes": 21600.0, "avg_minutes": 7200.0 }
]

GET /api/v1/analytics/corridors

Pro-Straße-Ereignishäufigkeit und durchschnittliche Räumungszeit. Bestes Signal dafür, „welcher Korridor heute unzuverlässig ist“.

Antwort
[
  { "road": "A100", "jurisdiction": "DE",
    "total_events": 245,
    "avg_clearance_minutes": 52.3,
    "incident_count": 180, "construction_count": 65 }
]

GET /api/v1/analytics/trends

Tägliche Ereigniszählungen mit Aufschlüsselung nach Typ.

Antwort
[
  { "period": "2026-03-29", "total": 142,
    "by_type": { "incident": 58, "construction": 62, "closure": 12, "weather": 10 } },
  { "period": "2026-03-28", "total": 128,
    "by_type": { "incident": 45, "construction": 60, "closure": 15, "weather": 8 } }
]

GET /api/v1/analytics/hotspots

Geografische Cluster von Ereignissen mit dem dominanten Typ und der dominanten Straße pro Cluster.

Antwort
[
  { "cluster_id": 1,
    "latitude": 52.5167, "longitude": 13.2833,
    "event_count": 28, "radius_km": 2.5,
    "top_type": "incident", "top_road": "A100" }
]

GET /api/v1/analytics/weather

Historische Messwerte von Wetterstationen — die Datenbasis für die Wetter-Ereignis-Korrelation.

Antwort
[
  { "station_id": "at-wx-a4-vie",
    "name": "A4 Vienna Weather Station",
    "latitude": 48.2082, "longitude": 16.3738,
    "temperature": 12.4, "wind_speed": 18.2, "wind_direction": "NW",
    "precipitation": "light_rain", "road_surface": "wet",
    "humidity": 78, "visibility": 12.0,
    "recorded_at": "2026-03-29T14:45:00Z" }
]

Weitere Analytik-Endpunkte

Gleiche Form wie die obigen Beispiele — vollständige Schemas siehe interaktive Referenz.

EndpunktBeschreibung
/analytics/feature-historyLebenszyklusänderungen von Funktionen (erstellt, deaktiviert, reaktiviert).
/analytics/event-weather/{id}Wetter-Snapshot zum Zeitpunkt der Ereigniserstellung (PostGIS-Suche der nächsten Station).
/analytics/weather-correlationAggregierte Korrelation zwischen Ereignissen und Wetter.

Metadaten & Status

Leichte Katalog- und Status-Endpunkte. Diese sind öffentlich (kein API-Schlüssel erforderlich) — nur /fuel-prices erfordert einen API-Schlüssel, ist aber nicht durch Tarifgrenzen beschränkt.

GET /api/v1/jurisdictions

Aktive Zuständigkeitsbereiche mit Code, Name, Land und scope. Standardmäßig werden nur reale geografische Zuständigkeitsbereiche zurückgegeben (scope=state). Mit ?scope=federal erhalten Sie übergreifende nationale Quellen, mit ?scope=regional sub-nationale Feeds und mit ?scope=all alles.

Ist group_id nicht null, gehört der Zuständigkeitsbereich zu einer Gruppe (siehe /api/v1/jurisdictions/groups unten). Eine Abfrage mit ?jurisdiction=<primary> auf /events oder /features wird transparent auf alle Mitglieder ausgedehnt; um dies zu deaktivieren, geben Sie einen Nicht-Primärcode oder eine kommagetrennte Liste an. Die EU-Bereitstellung führt derzeit keine Gruppen – alle Zeilen liefern group_id: null –, das Feld ist jedoch dokumentiert, damit Clients es übernehmen können, sobald parallele Feeds entstehen.

Antwort
[
  { "code": "DE", "name": "Germany", "country": "DE", "scope": "state", "group_id": null, "is_active": true },
  { "code": "AT", "name": "Austria", "country": "AT", "scope": "state", "group_id": null, "is_active": true }
]

GET /api/v1/jurisdictions/groups

Kanonische Bündel für Zuständigkeitsbereiche, deren Feed über mehrere Codes verteilt ist. Der primary_jurisdiction_code ist der Code, den Sie auf /events und /features verwenden – die Abfrage wird transparent auf alle members ausgedehnt. Die EU-Bereitstellung gibt derzeit ein leeres Array zurück; der Endpunkt wird ausgeliefert, damit Clients sich darauf verlassen können, sobald Mobilithek oder andere nationale Quellen gebündelt werden müssen.

Antwort
[]

GET /api/v1/stats/summary

Umfassende Sammelstatistiken — werden auf den Marketing-Seiten für Live-Zähler genutzt. Schwerere Abfrage als /stats; 60 s gecacht.

Antwort
{
  "jurisdictions": { "total": 28, "active": 26, "by_country": { "DE": 1, "AT": 1, "FR": 1 } },
  "events": {
    "active": 3120,
    "by_type": { "incident": 820, "construction": 1450, "closure": 280 },
    "by_severity": { "minor": 1080, "moderate": 1450, "major": 510, "critical": 80 }
  },
  "features": { "total": 96450, "by_type": { "cameras": 8120, "ev_charging": 42100 } },
  "last_sync": "2026-03-29T14:55:00Z",
  "uptime": "72h15m"
}

GET /api/v1/fuel-prices

Europäische Kraftstoffpreise (sofern lizenzierte Quellen verfügbar sind). Mit latest=true nur die jeweils aktuellsten Werte je jurisdiction + fuel_type.

Antwort
{
  "data": [
    { "jurisdiction": "DE", "country": "DE", "fuel_type": "diesel",
      "price": 1.69, "currency": "EUR", "unit": "litre",
      "observed_at": "2026-05-05", "source": "BAFA" },
    { "jurisdiction": "FR", "country": "FR", "fuel_type": "diesel",
      "price": 1.74, "currency": "EUR", "unit": "litre",
      "observed_at": "2026-05-05", "source": "DGEC" }
  ],
  "total": 128, "limit": 100, "offset": 0, "has_more": true
}

GET /api/v1/status

Öffentlicher Status-Schnappschuss — geeignet für eine unauthentifizierte Statusseite oder externe Uptime-Monitore. Aggregierte Kennzahlen plus Aufschlüsselung pro Zuständigkeit mit 7-Tage-Verfügbarkeit. 60 s Cache.

Antwort (gekürzt)
{
  "overall": "operational",
  "generated_at": "2026-05-08T14:00:00Z",
  "worker": { "last_seen": "2026-05-08T13:59:50Z", "staleness_seconds": 10, "healthy": true },
  "total_resources": 186, "healthy": 175, "warning": 8, "critical": 3,
  "jurisdictions": [
    { "code": "DE", "name": "Germany", "country": "DE",
      "status": "operational", "total_resources": 12, "open_circuits": 0,
      "uptime_7day_percent": 99.8 }
  ]
}

Webhooks Pro+

Abonnieren Sie Echtzeit-Ereignisänderungen. Wenn ein Verkehrsereignis erstellt wird, seinen Schweregrad oder Status ändert oder archiviert wird, sendet die API einen HMAC-SHA256-signierten POST an Ihren Endpunkt. Pro- und Enterprise-Kunden konfigurieren Abonnements im Portal — portal.napspan.com/webhooks. Das automatisch generierte Secret wird beim Anlegen einmalig angezeigt; kopieren Sie es dann.

Jeder Webhook wird nach Zuständigkeit (verpflichtend, Mehrfachauswahl — wählen Sie eine oder mehrere) und optional nach Ereignistyp, Untertyp und Schweregrad (ebenfalls Mehrfachauswahl) gefiltert. Filter werden über Dimensionen UND-verknüpft; innerhalb einer Dimension feuert der Webhook, sobald das Ereignis einem der ausgewählten Werte entspricht.

Der optionale sub_type-Filter grenzt innerhalb eines Typs ein — z. B. liefert type: ["incident"] + sub_type: ["accident"] nur Unfälle, keine Pannen oder Fahrbahnhindernisse. Er ist additiv: Lassen Sie ihn weg (oder senden Sie ein leeres Array), erhalten Sie wie bisher jeden Untertyp. sub_type ist außerdem ein Feld in jedem Ereignis sowie ein ?sub_type=-Abfrageparameter auf /events. Das vollständige Vokabular finden Sie in der API-Referenz.

Der optionale cause-Filter funktioniert ähnlich, aber typübergreifend. Da sub_type einem type untergeordnet ist (der Untertyp einer Sperrung beschreibt die Sperrung, nicht ihre Ursache), trägt ein Unfall, den eine Quelle als Sperrung meldet, type: "closure", sub_type: "lane_closure" — und cause: "accident". Damit erfasst cause: ["accident"] unfallbedingte Ereignisse unabhängig davon, wie die Quelle sie modelliert hat — was sub_type: ["accident"] allein verpassen würde. Wie sub_type ist cause ein Feld in jedem Ereignis, ein ?cause=-Abfrageparameter auf /events und eine additive Webhook-Filterdimension.

Ereignistypen

EreignisWird ausgelöst, wenn
event.createdEin neues Verkehrsereignis aus einer nationalen Mobilitätsdatenquelle eintrifft.
event.severity_changeSich der Schweregrad eines bestehenden Ereignisses ändert (z. B. moderatemajor).
event.status_changeSich der Status ändert (z. B. activearchived).
event.archivedDas Ereignis beendet ist.
testWird nur über den „Test"-Button im Portal gesendet — feuert sofort, wird nie im Zustellverlauf erfasst.

Sofort-Payload (Standard)

Ein POST pro Änderung. Geeignet, wenn Sie die geringstmögliche Latenz benötigen und Ihr Empfänger Lastspitzen verarbeiten kann.

Webhook-POST-Body
{
  "event": "event.severity_change",
  "timestamp": "2026-03-29T14:35:00Z",
  "data": {
    "event_id": "de-evt-a100-001",
    "jurisdiction": "DE",
    "type": "incident",
    "sub_type": "accident",
    "cause": "accident",
    "severity": "major",
    "road_name": "A100",
    "changes": {
      "old_severity": "moderate",
      "new_severity": "major"
    }
  }
}

Gebündelter Payload

Setzen Sie batch_window_seconds (1–300) beim Anlegen des Webhooks, um Änderungen für dieses Fenster zu sammeln und als einen POST auszuliefern. Reduziert das HTTP-Volumen bei gesprächigen Empfängern (Slack, Teams, Lambda) — auf Kosten von bis zu window_seconds zusätzlicher Latenz.

Gebündelter POST-Body (batch_window_seconds=60)
{
  "batch": {
    "window_seconds": 60,
    "started_at": "2026-03-29T14:30:00Z",
    "ended_at": "2026-03-29T14:31:00Z",
    "event_count": 2
  },
  "events": [
    {
      "event": "event.created",
      "timestamp": "2026-03-29T14:30:15Z",
      "data": { "event_id": "de-evt-a8-002", "jurisdiction": "DE", "type": "construction", "sub_type": "roadwork", "severity": "minor", "road_name": "A8" }
    },
    {
      "event": "event.severity_change",
      "timestamp": "2026-03-29T14:30:42Z",
      "data": { "event_id": "de-evt-a100-001", "jurisdiction": "DE", "type": "incident", "sub_type": "accident", "severity": "major", "road_name": "A100", "changes": { "old_severity": "moderate", "new_severity": "major" } }
    }
  ]
}

Empfänger verzweigen anhand des batch-Schlüssels:

Empfänger-Pseudocode
if ("batch" in body) {
  // gebündelt: über body.events iterieren
  for (const ev of body.events) handle(ev);
} else {
  // sofort: den Body selbst verarbeiten
  handle(body);
}

Ein einzelner Batch ist auf 100 Ereignisse begrenzt; längere Warteschlangen werden im selben Fenster auf mehrere POSTs aufgeteilt.

Signatur prüfen

Jede Zustellung enthält einen X-Webhook-Signature-Header mit dem HMAC-SHA256 (Hex, lowercase) des Anfragerumpfs, signiert mit Ihrem Webhook-Secret. Lehnen Sie Anfragen ab, deren Signatur nicht übereinstimmt.

Node.js-Empfänger
import crypto from "crypto";

app.post("/napspan-webhook", (req, res) => {
  const sig = req.headers["x-webhook-signature"];
  const expected = crypto
    .createHmac("sha256", process.env.WEBHOOK_SECRET)
    .update(req.rawBody)            // rohe Bytes, NICHT JSON.stringify(req.body)
    .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    return res.status(401).end();
  }
  // req.body verarbeiten…
  res.status(200).end();
});

Zuverlässigkeit

Fehlgeschlagene Zustellungen werden bis zu 3-mal mit exponentiellem Backoff (10s, 30s, 90s) wiederholt. Nach 10 aufeinanderfolgenden Fehlschlägen wird das Abonnement automatisch deaktiviert — reaktivieren Sie es im Portal, sobald Ihr Endpunkt wieder gesund ist. Verwenden Sie die Test-Schaltfläche je Zeile im Portal, um sofort ein test-Ereignis auszulösen und die Erreichbarkeit zu prüfen, bevor Sie sich produktiv auf einen Webhook verlassen.

LKW-Routing Pro+

Eine LKW-gerechte Route von Start nach Ziel — die Routinggeometrie kommt aus unserer Routing-Engine (einschließlich ADR-Tunnelkategorie-Beschränkungen für Gefahrgut) und wird anschließend mit jeder nahegelegenen Gefahr angereichert, die unsere Datenbank kennt: Live-RTTI-/SRTI-Vorfälle, geplante Bauarbeiten, Brückendurchfahrtshöhen gefiltert nach der angefragten Fahrzeughöhe, LKW- und Gewichtsbeschränkungen, Wetter entlang des Korridors und aktive Warnungen — sofern der jeweilige NAP die zugrunde liegenden Daten veröffentlicht.

POST /api/v1/routing/route

FeldTypBeschreibung
origin Erforderlichobject{ "lat": ..., "lng": ... }
destination Erforderlichobject{ "lat": ..., "lng": ... }
truck ErforderlichobjectFahrzeugblock — profile (tractor, straight, box), weight_t, height_m, optional length_m, width_m, axle_count, hazardous[]
truck.profile_idstringVerweist auf ein gespeichertes LKW-Profil aus Ihrer Flottenbibliothek (im Portal unter Meine LKW verwaltet), statt den vollständigen Block erneut zu senden. Inline mitgesendete truck.*-Felder werden darüber tief zusammengeführt (Inline-Werte gewinnen pro Feld). Der aufgelöste Block wird als resolved_truck zurückgegeben. Siehe Wiederverwendbare LKW-Profile.
alternativesintAnzahl alternativer Routen (0–3, Standard 0)
avoidarrayOptional: tolls, ferries, tunnels
includearrayOptionale Detailkanäle. Fügen Sie tolls hinzu, damit die Routing-Engine die Mautsysteme der Route für Ihren LKW bepreist — die Kosten werden als summary.toll_costs[] (ein Eintrag pro Währung) und sections[].tolls[] (pro System) zurückgegeben. polyline und summary sind immer enthalten. Fügen Sie toll_alternative hinzu (kostenpflichtige Tarife; impliziert tolls), um zusätzlich eine zweite, mautfreie Route zu berechnen und den Vergleich zu bepreisen — siehe Mautbewusste Alternative; dies wird als 2 Routing-Aufrufe abgerechnet. Die Mautberechnung verursacht zusätzliche Upstream-Kosten und ist daher nur auf Anfrage aktiv.
currencystringISO-4217-Währung für Mautgebühren — nur wirksam mit include: ["tolls"]. Weglassen, um die native Währung jedes Mautsystems zu erhalten.
enrichmentobjectFeintuning des Warnungsfilters nach dem Routing — keines dieser Felder wird an die Routing-Engine übermittelt. Unterfelder: exclude_types, min_severity, buffer_m (10–1000, Standard 100), clearance_pad_m (0–1, Standard 0.15), skip_temporal_filter, max_distance_m.
cargoobjectLadungsmetadaten, auf der gespeicherten Route abgelegt. Unterfeld: hazmat_class (ADR-Klasse, z. B. "1.3D").
truck.permit_numberstringSchwerlast-/Sondertransport-Genehmigungsnummer. In der Antwort zurückgegeben.
customer_route_idstringBeliebiger Korrelationsschlüssel (≤128 Zeichen). Wird wortwörtlich zurückgegeben.
tagsarrayFrei wählbare Labels für Flotten-/Lane-Analyse (max. 16 Einträge, jeweils ≤64 Zeichen).
Jeder erfolgreiche Aufruf wird auf Ihr monatliches Routing-Kontingent angerechnet — zunächst aus dem Abonnement-Topf, danach aus eventuellen Aufladepaketen in FIFO-Reihenfolge. Erneute Abrufe gespeicherter Routen (siehe unten) verbrauchen kein Kontingent.
Beispiel: Berlin → München, 20 t Zugmaschine, 4,0 m Höhe
curl -X POST -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  https://api.napspan.com/api/v1/routing/route \
  -d '{
    "origin":      { "lat": 52.5200, "lng": 13.4050 },
    "destination": { "lat": 48.1351, "lng": 11.5820 },
    "truck": {
      "profile":  "tractor",
      "weight_t": 20,
      "height_m": 4.0
    },
    "include":  ["tolls"],
    "currency": "EUR"
  }'
Antwort
{
  "route_id":   "rt_01HXYZ4K8Q2V7R9N3M5P6T8W0E",
  "expires_at": "2026-05-18T14:32:00Z",
  "routes": [
    {
      "summary": {
        "distance_km":   585.4,
        "duration_min":  352,
        "toll_costs":   [ { "currency": "EUR", "value": 38.70 } ]
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [13.4050, 52.5200],
          [12.3700, 51.3400],
          [11.5820, 48.1351]
        ]
      },
      "warnings": [
        {
          "type":           "bridge_clearance",
          "severity":       "critical",
          "feature_id":     "DE-bridge-A9-K1247",
          "name":           "A9 Überführung bei Leipzig",
          "latitude":       51.3400,
          "longitude":      12.3700,
          "clearance_m":    4.0,
          "truck_height_m": 4.2,
          "message":        "Ausgeschilderte Durchfahrtshöhe liegt unter der angefragten Fahrzeughöhe."
        }
      ]
    }
  ]
}

Mautbewusste Alternative

Fügen Sie toll_alternative zu include hinzu (es impliziert tolls), und die Antwort erhält einen toll_alternative-Block auf oberster Ebene: eine zweite Route, die unter Vermeidung von Mautstraßen berechnet wird, plus den bepreisten Vergleich — wie viele zusätzliche Meter und Sekunden der mautfreie Weg kostet und wie viel Mautgeld pro Währung er einspart. So kann ein Disponent in einer einzigen Anfrage abwägen: „Maut zahlen oder außen herum fahren“.

Abrechnung: Da hierbei eine zweite Route berechnet wird, wird dies als 2 Routing-Aufrufe gezählt (die primäre Route + die mautfreie Alternative) — oder als 1, wenn die gesamte Antwort aus dem Cache bedient wird. Die Funktion ist nur in kostenpflichtigen Tarifen verfügbar; eine Anfrage im Free-Tarif liefert die primäre Route plus toll_alternative_omitted: "plan_upgrade_required". Kann die Alternative aus einem anderen Grund nicht erzeugt werden, wird dennoch die primäre Route zurückgegeben, mit dem Grund in toll_alternative_omitted (quota_exhausted, upstream_error oder no_alternative).

Antwort: der toll_alternative-Block (neben routes[])
  "toll_alternative": {
    "summary": {
      "distance_m":  372000,
      "duration_s":  13800,
      "toll_costs":  []
    },
    "geometry":        { "type": "LineString", "coordinates": [ /* … */ ] },
    "extra_distance_m": 22000,
    "extra_duration_s": 1200,
    "savings":         [ { "currency": "EUR", "value": 38.70 } ],
    "cached":          false
  }

Warnungstypen

Jeder Eintrag in warnings[] trägt einen type, einen severity (info / warning / critical), die Distanz entlang der Route, eine voraussichtliche Ankunftszeit und einen typspezifischen properties-Block. Nutzen Sie das enrichment-Objekt, um nach Schweregrad zu filtern oder Typen wegzulassen, die Sie nicht interessieren. Die Verfügbarkeit jedes Typs hängt davon ab, was der NAP für diesen Korridor veröffentlicht.

TypTypischer SchweregradWird ausgelöst, wenn
bridge_clearancecriticalAusgeschilderte Durchfahrtshöhe < Fahrzeughöhe + clearance_pad_m, oder Tragfähigkeit < Fahrzeuggewicht
truck_restrictioncriticalEine ausgeschilderte Höhen-/Breiten-/Längen-/Gewichtsbeschränkung auf der Route liegt unter dem Wert des LKW (pro Dimension markiert)
weight_restrictioncriticalEine ausgeschilderte Gewichtsbeschränkung auf der Route liegt unter dem Fahrzeuggewicht
traffic_eventcritical–infoEin Live-RTTI-/SRTI-Vorfall, eine Sperrung oder ein Bauarbeitenereignis schneidet den Korridor innerhalb des Reisefensters
future_constructionwarningGeplante Bauarbeiten überschneiden sich an dieser Stelle der Route mit der voraussichtlichen Reisezeit
special_eventinfoEine geplante Sperrung oder ein Sonderereignis berührt die Route
alertinfoEine allgemeine Warnung der Zuständigkeit gilt entlang des Korridors
weatherinfoWetterbedingungen / Warnungen, die von Stationen nahe der Route gemeldet werden
border_crossingcritical–infoEin Grenzübergang liegt auf der Route. Sofern der Datenanbieter eine Wartezeit für die Nutzfahrzeugspur meldet, richtet sich die Dringlichkeit danach (info unter 15 Min., warning ab 15, critical über 45 oder bei geschlossenem Übergang)

ADR-Tunnelkategorie-Beschränkungen werden vom Router selbst angewandt (über die Tunnelkategorie und Gefahrgutklasse des LKW), sodass verbotene Tunnel in der Routengeometrie gemieden statt als Warnung gemeldet werden. Aktivieren Sie den separaten features[]-Kanal mit enrichment.include_features, um zusätzlich nahegelegene Einrichtungen entlang der Route zu erhalten — truck_parking, truck_rest_areas, LKW-taugliche rest_areas, service_plazas und ev_charging. Die Anzahl der gleichzeitig anforderbaren Einrichtungstypen ist tarifabhängig begrenzt (Free: keine; das Limit steigt mit dem Tarif; Enterprise: unbegrenzt) — Ihr Limit wird als routing_max_feature_types unter GET /api/v1/customer/plans veröffentlicht. Eine Überschreitung führt zu 403 feature_types_limit.

Lenk- und Ruhezeiten-Planung

Fügen Sie einen truck.hos-Block hinzu — die aktuellen Lenk- und Ruhezeiten des Fahrers bei Abfahrt — und die Antwort erhält einen hos[]-Kanal: die Punkte, an denen der Fahrer nach der gewählten Regelung eine Pause einlegen oder die Fahrt beenden muss, jeweils mit den vor diesem Limit noch erreichbaren LKW-Parkplätzen und Rastplätzen. Abgedeckt sind die EU (Verordnung 561/2006), die USA (FMCSA) und Kanada (südlich und nördlich des 60. Breitengrads — canada_south / canada_north), und es ist in jedem Tarif kostenlos. Lassen Sie ruleset weg, um auf die Region Ihres Deployments zurückzufallen (hier eu).

Jedes *_remaining_s-Feld ist die verbleibende Zeit in Sekunden gegen das jeweilige Limit — lassen Sie eines weg, um einen ausgeruhten Fahrer anzunehmen. Ein wiederverwendbares LKW-Profil sollte nur ruleset speichern; senden Sie die fahrtbezogenen Zähler inline.

Anfrage: Lenk- und Ruhezeiten des Fahrers zum truck-Block hinzufügen
    "truck": {
      "profile":  "tractor",
      "weight_t": 20,
      "height_m": 4.0,
      "hos": {
        "ruleset":           "eu",
        "drive_remaining_s": 32400,
        "since_break_s":     9000
      }
    }
Antwort: der hos[]-Kanal (neben warnings[] / features[])
      "hos": [
        {
          "reason":                 "break_required",
          "distance_along_route_m": 112000,
          "projected_time":         "2026-05-18T13:30:00Z",
          "legal_deadline":         "2026-05-18T13:30:00Z",
          "feasible":               true,
          "suggested_stops": [
            { "type": "truck_parking", "name": "Autohof Montabaur A3", "distance_along_route_m": 106000, "available_spots": 22, "capacity": 45, "as_of": "2026-05-18T13:25:00Z" }
          ]
        }
      ],
      "hos_summary": {
        "adjusted_arrival_time": "2026-05-19T02:10:00Z",
        "delay_s":               39600,
        "meets_arrival_window":  false
      }

reason ist einer von break_required, drive_limit, duty_window oder cycle_limit. suggested_stops sind zuerst nach freien Plätzen, dann nach Nähe zur Frist sortiert, damit der Fahrer die meiste legale Fahrzeit ausschöpft, bevor er anhält; wenn ein Parkplatz-Feed die Belegung meldet, trägt jeder Halt available_spots / capacity, und feasible: false bedeutet, dass vor diesem Limit jeder erreichbare Parkplatz voll (oder keiner erreichbar) ist. hos_summary fasst die Projektion gegen Ihre Ankunftszeit zusammen — adjusted_arrival_time ist die Ankunft nach den vorgeschriebenen Ruhezeiten, delay_s die dadurch hinzugefügte Zeit und meets_arrival_window (nur vorhanden, wenn Sie arrival_time senden), ob der Fahrer dieses Zeitfenster noch legal einhält. Ein unbekanntes ruleset liefert 400 invalid_hos_ruleset.

Gespeicherte Routen

Jeder Aufruf wird unter seiner route_id automatisch 30 Minuten lang gespeichert. Rufen Sie die Route innerhalb dieses Zeitfensters jederzeit über GET /api/v1/routing/route/saved/{id} erneut ab, um die Warnungen gegen den aktuellen Live-Zustand neu zu bewerten — solche Refetches verbrauchen kein Routing-Kontingent. Um eine Route über die 30 Minuten hinaus zu behalten, rufen Sie POST /api/v1/routing/route/saved/{id}/persist auf; dauerhaft gespeicherte Routen werden auf das Slot-Limit Ihres Tarifs angerechnet.

Rufen Sie Points of Interest entlang einer gespeicherten Route bei Bedarf über GET /api/v1/routing/route/saved/{id}/features?types=cameras,fuel_stations,truck_parking ab. Dies ist die bedarfsgesteuerte Ergänzung zu include_features: Der Aufruf verbraucht kein Routing-Kontingent und liefert die angeforderten POI-Typen — nach Entfernung entlang der Route sortiert — einschließlich Verkehrskameras und Tankstellen, die nur hier und nicht im eingebetteten features[]-Kanal verfügbar sind (beide sind dichte landesweite Ebenen, die den synchronen Routing-Aufruf verlangsamen würden). Sofern ein nationaler Datenfeed Preise pro Tankstelle veröffentlicht, werden diese in den properties des Features mitgeliefert. Jedes Feature ist mit distance_along_route_m, dem senkrechten detour_m-Abstand zur Route und der side (left/right) der Fahrtrichtung versehen. Die Anzahl unterschiedlicher Typen unterliegt demselben routing_max_feature_types-Limit, und die Ergebnisse werden pro Route zwischengespeichert und wie ein Refetch ratenbegrenzt.

Wiederverwendbare LKW-Profile

Wenn Sie dieselbe Handvoll Fahrzeuge immer wieder routen, speichern Sie jeden LKW einmal, statt seinen vollständigen Block bei jedem Aufruf erneut zu senden. Erstellen und verwalten Sie benannte Profile in Ihrem Portal unter Meine LKW und verweisen Sie dann per ID über truck.profile_id auf eines:

Ein gespeichertes Profil referenzieren, ein Feld überschreiben
curl -X POST -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  https://api.napspan.com/api/v1/routing/route \
  -d '{
    "origin":      { "lat": 48.2082, "lng": 16.3738 },
    "destination": { "lat": 48.3069, "lng": 14.2858 },
    "truck": {
      "profile_id": "9f1c2e7a-6b3d-4a21-9f0e-2c5d8b7a1e34",
      "weight_t":   38
    }
  }'

Der Server lädt das gespeicherte Profil und führt alle inline mitgesendeten truck.*-Felder tief zusammen — Inline-Werte gewinnen Feld für Feld, sodass Sie ein Basisprofil behalten und z. B. weight_t für eine beladene Fahrt überschreiben können. Der vollständig aufgelöste LKW-Block wird als resolved_truck zurückgegeben, sodass Sie genau bestätigen können, was die Routing-Engine gesehen hat:

Antwort (Auszug)
{
  "route_id": "rt_01HXYZ4K8Q2V7R9N3M5P6T8W0E",
  "resolved_truck": {
    "profile_id": "9f1c2e7a-6b3d-4a21-9f0e-2c5d8b7a1e34",
    "profile":    "tractor",
    "weight_t":   38,
    "height_m":   4.0,
    "axle_count": 5
  },
  "routes": [ /* … */ ]
}

Eine unbekannte ID liefert 400 profile_not_found. Ein gespeichertes Profil darf selbst kein profile_id enthalten.

Erweiterte Vermeidung & Routendetails

Über avoid hinaus akzeptiert die Anfrage feinere Routensteuerungen: avoid_areas (Sperrung von Bounding-Box-, Kreis- oder Polygon-Sperrzonen), avoid_zones (environmental, congestion_pricing), avoid_truck_roads, avoid_countries sowie das striktere exclude_countries (ISO-3-Codes) und details[] für streckenabschnittsbezogene Straßenattribute (Tempolimits, Functional Class, Fahrspuren …). Jede Route trägt außerdem die notices[] des Routing-Engines selbst — Hinweise wie violatedVehicleRestriction, wenn kein vollständig regelkonformer Weg existiert. Die vollständige Feldliste finden Sie in der Referenz.

Vollständiges Request-/Response-Schema (alle LKW-Profilfelder, alle Warnungs-Typen, Fehler-Envelopes): siehe die interaktive Referenz unter /reference.html.

Funktionsgruppen

60+ Funktionstypen, organisiert in 16 Gruppen. Verwenden Sie die id als group-Parameter bei /features, um alle Mitglieder in einer einzigen Anfrage abzurufen.

Gruppen-IDNameMitglieder
imageryBildmaterialcameras
weatherWetter & Umweltweather_stations, regional_weather, weather_forecasts, weather_alerts, wind_warnings
road_conditionsStraßenzustandroad_conditions, ice_roads, snow_plans
traffic_performanceVerkehrsflusstraffic_segments, speed_data, travel_times, express_lanes, hov_lanes
planned_eventsGeplante Ereignisse & Sperrungenworkzones, future_construction, future_roadwork, special_events, seasonal_loads
alerts_advisoriesWarnungen & Hinweisealerts, emergency_alerts, advisories, general_info
wildfiresWaldbrändewildfires, wildfire_incidents, wildfire_perimeters
truckingLKW-Verkehr & Nutzfahrzeugetruck_restrictions, weight_restrictions, bridge_clearances, truck_routes, freight_corridors, truck_parking, truck_rest_areas, weigh_stations, inspection_stations
traveler_servicesReisedienste & POIsrest_areas, service_centres, info_centres, visitor_locations, parks, communities, carpool_lots, airports
fuel_chargingKraftstoff & Ladungev_charging, alt_fuel_stations
bordersGrenzübergängeborder_crossings, ports_of_entry
ferriesFährenferries, coastal_ferries
transitÖffentlicher Verkehrtransit_hubs, transit_stops
tollsMauttolls
static_infrastructureInfrastruktur & Überwachungbridges, signs, roundabouts, speed_cameras
operationsBetriebservice_vehicles

Funktionstypen

Übergeben Sie einen dieser Werte als type-Parameter an /features.

camerasVerkehrskamera-Aufnahmen mit Bild-URLs
weather_stationsRWIS-Sensoren: Temperatur, Wind, Luftfeuchtigkeit, Straßenzustand
rest_areasRastplätze mit Ausstattung (Toiletten, WLAN, Wohnmobil-Entsorgung)
signsDynamische Anzeigetafeln mit aktuellem Text
road_conditionsSegmentbezogene Fahrbahnoberflächenzustände
ev_chargingEV-Ladestationen (nationale Ladepunkt-Register)
bridge_clearancesVertikale Brückendurchfahrtshöhen, Lastbewertungen, Beschilderungsstatus
truck_restrictionsHöhen-/Gewichtsbeschränkungen, Gefahrgutzonen, Genehmigungen
weight_restrictionsSaisonale/dauerhafte Gewichtsgrenzen (Polylinien)
truck_routesAusgewiesene LKW-Routen (Polylinien)
freight_corridorsFrachtnetzkorridore, inkl. TEN-T (Polylinien)
truck_parkingLKW-Parkplätze mit Kapazität und Ausstattung
weigh_stationsStandorte und Status von Waagestationen
traffic_segmentsVerkehrsflusssensordaten (Geschwindigkeit/Volumen)
service_vehiclesSchneepflüge, DOT-Einsatzfahrzeuge (saisonal)
ferriesFährterminals und Routenstatus

Ereignistypen

TypSchweregradbereichBeschreibung
incidentmoderate–criticalUnfälle, liegengebliebene Fahrzeuge, Gefahren
constructionminor–moderateStraßenarbeiten, Wartung, Asphaltierung
closuremajor–criticalVollsperrungen
weathermoderate–criticalWetterbedingte Fahrbahnauswirkungen
special_eventminor–moderateGeplante Veranstaltungen (Paraden, Rennen)
advisoryminor–moderateReisehinweise, Warnungen
restrictionminor–moderateGewichts-, Höhen-, Geschwindigkeitsbeschränkungen

Tarife & Limits

LimitFree (14-Tage-Testphase)Starter (29 €/Monat)Pro (99 €/Monat)Enterprise
RPM603001.0005.000
Tägliche Anfragen1.00050.000500.000Unbegrenzt
API-Schlüssel131050
Zuständigkeitsbereiche/Anfrage210UnbegrenztUnbegrenzt
Ergebnisse/Seite1005001.000Unbegrenzt
GeoJSON-ExportNeinJaJaJa
AnalytikNeinNeinJaJa
LKW-KorridorNeinNeinJaJa
Datenverzögerung15 Min.EchtzeitEchtzeitEchtzeit

Kostenlosen API-Schlüssel anfordern