A route that’s legal in one country can be illegal across the border at the same hour. That’s the quiet trap in European long-haul: the driving is continuous, but the rulebook changes every time the truck crosses a line. Weekend and night driving bans, sectoral bans on Alpine transit corridors, low-emission zones in city centres, country-by-country weight and dimension limits, seasonal restrictions — none of them show up on a consumer navigation app, and each one carries a real penalty when you find out the hard way: a fine, a forced wait at the roadside, or a load turned back at the frontier.
We wrote about this as one of the five road-data problems every cross-border European fleet hits. This post is the detailed version: what the data actually looks like when you stop maintaining twenty-seven national rule-scrapers and query one normalized schema instead — and how the restrictions on a corridor come back attached to the route, not as a separate homework assignment.
The Need Isn’t “Every Rule in Europe”
It’s narrower and more useful than that. A dispatcher doesn’t want a searchable encyclopedia of every national regulation; they want to know about the restrictions and the signs on this corridor, for this truck, before the driver gets there. That’s a spatial question, and it’s the shape NAPSPAN answers.
Two normalized feature types carry it, both queried from the same /features endpoint the rest of the API speaks:
truck_restrictions— the weight, height, width, length, and access limits and bans that apply to heavy vehicles, from the official national feeds.signs— roadside signage including variable-message signs (VMS/DMS): the live text a gantry is displaying, normalized so a German panel and an Austrian one read the same way in your code.
Both are filterable by jurisdiction and by a bounding box, and both hang off the trucking and infrastructure feature groups you can browse with GET /features/groups. One schema for a German night ban and an Austrian sectoral ban means you check one place instead of twenty-seven.
Restrictions on a Corridor, by Bounding Box
Ask for the truck restrictions inside a bounding box in one jurisdiction. Here’s a stretch of Latvian trunk road:
curl -H "X-API-Key: $KEY" \
"https://api.napspan.com/api/v1/features?type=truck_restrictions&jurisdiction=LV&bbox=21.0,56.9,24.2,57.3"
Every row is a normalized feature: coordinates, the road it sits on, and a properties object carrying the limits that matter to a heavy vehicle. The limit fields are the ones a truck profile is actually checked against — max_weight_t, max_height_m, max_width_m, max_length_m:
{
"data": [
{
"id": "lv-restr-p128-0042",
"source": "lv",
"jurisdiction": "LV",
"feature_type": "truck_restrictions",
"name": "P128 weight restriction",
"latitude": 57.0891,
"longitude": 23.1140,
"road_name": "P128",
"is_active": true,
"properties": {
"restriction_type": "weight",
"max_weight_t": 7.0,
"description": "7 t weight limit"
},
"last_updated": "2026-07-06T21:10:00Z",
"has_details": false
}
],
"total": 230, "limit": 100, "offset": 0, "has_more": true
}
Swap type=truck_restrictions for group=trucking and the same call fans out across nine truck-related layers at once — restrictions, weight limits, bridge clearances, parking, rest areas, weigh and inspection stations — so a single request paints the whole commercial-vehicle picture for a bounding box.
The Variable-Message Signs
The signs type carries roadside signage, and for VMS/DMS gantries that includes the message the sign is currently displaying. Query it the same way — by jurisdiction, by bounding box:
curl -H "X-API-Key: $KEY" \
"https://api.napspan.com/api/v1/features?type=signs&jurisdiction=AT&bbox=9.5,46.4,17.2,49.0"
{
"data": [
{
"id": "at-vms-a13-brenner-07",
"jurisdiction": "AT",
"feature_type": "signs",
"name": "A13 Brenner VMS",
"latitude": 47.0620,
"longitude": 11.5083,
"road_name": "A13",
"direction": "southbound",
"is_active": true,
"properties": {
"message": "LKW ÜBERHOLVERBOT",
"sign_type": "VMS",
"posted_at": "2026-07-06T20:55:00Z"
},
"last_updated": "2026-07-06T21:00:00Z",
"has_details": true
}
],
"total": 3120, "limit": 100, "offset": 0, "has_more": true
}
The sign_type discriminates VMS/DMS gantries from static signage, and message is the normalized text so you don’t parse a different payload per country. The signs feed comes straight from the national access points — ASFINAG’s DATEX II VMS publication in Austria, the DGT in Spain, Digitraffic in Finland, and more — folded into this one shape.
The Part That Matters: Restrictions Ride the Route
Querying a bounding box is the manual path. The one that changes a dispatcher’s day is that truck restrictions come back attached to the route itself. Send a normal routing request to POST /api/v1/routing/route with the truck’s profile, and the corridor’s restrictions arrive in the warnings[] channel — no second call, no separate spatial join on your side.
And it’s not a data dump. The engine compares each restriction against the truck you actually sent and only warns when your vehicle trips the limit, one warning per dimension, so the dispatcher sees exactly which measurement is the problem:
{
"warnings": [
{
"type": "truck_restriction",
"severity": "critical",
"title": "Truck weight restriction",
"description": "weight limit 7t; your truck is 40t.",
"distance_along_route_m": 184300,
"projected_arrival_time": "2026-07-08T18:40:00Z",
"valid_from": "2026-07-08T22:00:00Z",
"valid_to": "2026-07-09T05:00:00Z",
"source": "lv",
"source_id": "lv-restr-p128-0042",
"geometry": { "type": "Point", "coordinates": [23.1140, 57.0891] }
}
]
}
Everything a dispatcher needs to act is in that one object: what the restriction is, where on the route it falls (distance_along_route_m), when the truck is projected to reach it (projected_arrival_time), and — when the source publishes a validity window — whether it’s even in force at that hour (valid_from / valid_to). A night ban the truck reaches at 18:40 but that only bites from 22:00 is a very different decision than one already in force, and the response lets you tell them apart.
This rides the same request as the corridor toll costs and the 561/2006 break planning. One cross-border query — say LV → PL → DE — hands back a drivable truck route, the restrictions that would stop it, where the driver must legally break, and what the trip costs in tolls: the operational picture before the truck rolls, not after the fine.
What to Expect From the Data
A few honest notes so the coverage behaves the way you expect:
- Coverage is per-NAP and growing. Today the normalized
truck_restrictionslayer is live for jurisdictions including Latvia and France, and thesigns/VMS layer for Austria, Spain, Finland, Slovenia, and Latvia — with more national access points folding into the same two feature types as we wire them. QueryGET /api/v1/features/typesfor the live per-type counts before you build against a jurisdiction. - Validity windows come from the source. Seasonal, weekend, and night bans surface as
valid_from/valid_towhen the upstream feed stamps them. Where a source publishes a restriction as a standing inventory without times, treat it as always-applicable rather than assuming a window. - Restrictions route; signs are queried. Truck restrictions ride the route in
warnings[]automatically. VMS/signs are not part of the routing enrichment — pull them for a corridor with abboxquery ontype=signs, keyed to the route’s bounding box. - It’s a planning input. The data is built for dispatch and pre-trip planning. It sharpens the plan; it doesn’t replace the driver’s obligation to obey the sign in front of them.
The Common Thread
Every national authority publishes its restrictions and signs its own way, on its own schedule, under its own license. Joining all of that to a route and keeping it fresh is solvable in-house — and, solved in-house, it becomes a permanent maintenance commitment that competes with the product you actually sell. NAPSPAN does that aggregation once and hands you one normalized schema: query a bounding box, or send a route and get the restrictions back on it, filterable by jurisdiction, served from Europe, every source license-classified before it ships.
Try It
- API docs —
/featureswithtype,group,jurisdiction, andbbox, plusPOST /routing/route - Live map — see the normalized restrictions and signs across the European NAPs
- Free API key — no card, 14-day trial
Know the ban before the border, not at it
National truck restrictions and variable-message signs, normalized into one schema — queryable by jurisdiction and bounding box, and surfaced automatically on your route. Free 14-day trial. No card.
Get Free API Key Read the Docs