# Europe Truck Dispatch Guard - Germany, Switzerland & France (`kamerozkan/europe-truck-dispatch-guard`) Actor

Route-aware 2026 truck-ban decisions for Germany, Switzerland, France, and cross-border journeys, with official sources and safer departure times.

- **URL**: https://apify.com/kamerozkan/europe-truck-dispatch-guard.md
- **Developed by:** [Kamer Ozkan](https://apify.com/kamerozkan) (community)
- **Categories:** Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $80.00 / 1,000 route-aware restriction decisions

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Europe Route-Aware Truck Dispatch Guard

Decide whether a truck can complete a supplied German, Swiss, or French route without entering a Sunday, public-holiday, night, regional, or seasonal driving-ban window. The Actor evaluates the full journey timeline, applies caller-supplied statutory exemptions, and returns route conflicts and safer departure alternatives together with the official legal basis.

This Actor is designed for dispatch agents, transport-management systems, freight forwarders, 3PL workflows, and delivery-promise automation.

Version 0.6 remains backward-compatible with country-specific workflows and adds `country: "AUTO"` for one combined DE-CH-FR route decision. Add `route` when the decision must cover the whole journey.

### What the Actor answers

- Is this vehicle within the statutory truck-ban scope?
- Will a Sunday or StVO-listed public-holiday ban begin while the vehicle is moving?
- Which German states does the supplied geometry cross, and at what estimated times?
- Does a July-August Saturday window overlap a listed road span?
- Will a Swiss route enter the nationwide 22:00-05:00 night ban or a Sunday/holiday window?
- Will a French route overlap the ordinary weekend ban, a 2026 summer/winter window, or an Île-de-France directional restriction?
- Which supported countries does a cross-border route enter, and what is the joint legal departure?
- Does maintained temporary-order evidence cover the complete journey?
- Does a cargo, combined-transport, operational, military, or permit exemption apply?
- What is the first later route departure with no evaluated conflict?
- Is there an earlier exclusive deadline that clears the route before the restriction?
- Which rule and official source produced the decision?

Every result uses one of four decisions:

- `ALLOWED` - no evaluated prohibition remains.
- `PROHIBITED` - a definite statutory prohibition applies.
- `CONDITIONAL` - missing route facts or an exemption document must be verified.
- `ERROR` - this query could not be validated.

### Important scope

The Actor contains three independently versioned rule sets:

- `DE-2026.07.26-v2.2` for Germany;
- `CH-2026.07.26-v1.1` for Switzerland;
- `FR-2026.07.26-v1.1` for France.

Every departure and estimated route arrival must fall inside 2026. Dates outside the versioned rule period fail with `ERROR`; the Actor never silently reuses annual rules for another year.

Germany coverage:

- StVO § 30 Sunday and listed public-holiday restrictions.
- Regional StVO holiday scope for Corpus Christi, Reformation Day, and All Saints' Day.
- The 1 July-31 August Saturday restriction on the road list published by the German Federal Ministry of Transport on 1 July 2026.
- GeoJSON LineString or precision-5/6 encoded-polyline routes.
- Supplied OSRM, Google Routes, HERE Routing v8, and TomTom Routing responses.
- Per-coordinate-segment durations and planned intermediate stops.
- State visits detected from Eurostat GISCO NUTS 2024 boundaries.
- Routing-provider road spans matched to operational representations of all listed 2026 summer corridors.
- Statutory exemptions represented by explicit caller assertions.

Switzerland coverage:

- The VRV heavy-vehicle night ban from 22:00 to 05:00.
- Sundays and VRV-listed holidays, including the special 26 December condition.
- Explicit handling of the rule that a listed holiday does not apply where it is not observed; use `swissHolidayObserved` to resolve the canton/canton-part fact.
- Heavy trucks over 3.5 t, articulated combinations over 5 t, and vehicles towing a trailer over 3.5 t.
- Zero-emission excess-weight allowances and caller-asserted Art. 91a exemptions.
- The broadened live-animal, one-day perishable-goods, and infrastructure-maintenance exemptions effective 1 July 2026.
- Swiss route entry/exit detection from a generalized GISCO 2024 country boundary.

France coverage:

- Goods vehicles or combinations over 7.5 tonnes, with explicit specialized/agricultural exclusions.
- The nationwide Saturday/holiday-eve 22:00 start and Sunday/public-holiday 22:00 end rules.
- The official 2026 nationwide summer Saturday dates from 07:00 to 19:00.
- The official 2026 Auvergne-Rhône-Alpes winter Saturday dates from 07:00 to 18:00, with fail-closed restricted-network usage.
- Permanent directional Île-de-France windows on the listed A6A/A6B/A106/A6/A10/A13/A12 sections; Article 4 exemptions are not applied to these windows.
- Caller-asserted Article 4 categories and prefectural derogations, always requiring documentary review.
- French country, Île-de-France, and Auvergne-Rhône-Alpes detection from generalized GISCO 2024 boundaries.
- Automatic negative resolution of the regional road lists when complete non-inferred `roadSpans` prove that no listed road is used.

Cross-border coverage:

- `country: "AUTO"` detects Germany, Switzerland, and France from one route and returns a conservative combined decision plus `countryAssessments`.
- The next legal departure is searched jointly across every detected supported country.
- A route that enters none of the supported countries fails instead of guessing.

Temporary orders:

- `temporaryOrderCheck` accepts evidence from a maintained official-order feed as `VERIFIED_CLEAR`, `APPLICABLE_PROHIBITION`, or `APPLICABLE_EXEMPTION`.
- `VERIFIED_CLEAR` must cover the departure through estimated arrival.
- Without journey-wide clearance, an otherwise `ALLOWED` in-scope movement becomes `CONDITIONAL`, and unverified later-departure suggestions are withheld.

It does not yet:

- calculate a route from coordinates;
- map-match raw geometry to road names by itself;
- call routing providers or fetch live traffic itself;
- calculate legally required EU driver working/rest periods;
- verify permits or cargo documents;
- fetch live road closures, environmental zones, or temporary orders itself;
- cover European countries other than Germany, Switzerland, and France.

The Actor deliberately returns `CONDITIONAL` instead of guessing when those facts matter. Connect your own official-order monitor through `temporaryOrderCheck` for operational use.

### Real decisions from live runs

Both records below are unedited output from live runs on 2026-07-28.

A Sunday-window departure is refused with the statute attached. Every restriction
carries its certainty level and an official source with URL, section, and access date,
so a dispatcher or an agent can audit the refusal instead of trusting it:

```json
{
  "queryId": "freiburg-geneva-lyon-auto",
  "country": "AUTO",
  "decision": "PROHIBITED",
  "departureTime": "2026-07-13T21:00:00+02:00",
  "nextLegalDeparture": null,
  "subjectToTruckBanRules": true,
  "routeStates": [
    "DE-BW"
  ],
  "restrictions": [
    {
      "code": "CH_VRV_91_NIGHT_BAN",
      "title": "Swiss heavy-vehicle night driving ban",
      "certainty": "DEFINITE",
      "startsAt": "2026-07-13T22:00:00+02:00",
      "endsAt": "2026-07-14T05:00:00+02:00",
      "affectedStates": [],
      "affectedRoads": [],
      "explanation": "The Swiss heavy-vehicle night driving ban applies from 22:00 to 05:00.",
      "source": {
        "title": "Federal Roads Office (ASTRA) - Sunday and night journeys",
        "url": "https://www.astra.admin.ch/de/sonntags-und-nachtfahrten",
        "section": "General 22:00-05:00 night ban and Sunday ban",
        "accessedOn": "2026-07-26"
      }
    },
    {
      "code": "FR_ART1_HOLIDAY_NATIONAL_DAY",
      "title": "French National Day French goods-vehicle driving ban",
      "certainty": "DEFINITE",
      "startsAt": "2026-07-14T00:00:00+02:00",
      "endsAt": "2026-07-14T22:00:00+02:00",
      "affectedStates": [],
      "affectedRoads": [],
      "explanation": "French National Day is a national French public holiday; the nationwide restriction applies from 00:00 to 22:00.",
      "source": {
        "title": "French order of 16 April 2021 on goods-vehicle driving restrictions",
        "url": "https://www.legifrance.gouv.fr/loda/id/JORFTEXT000043416004/",
        "section": "Articles 1-5 and Annexes I-III",
        "accessedOn": "2026-07-26"
      }
    }
  ],
  "exemptionsApplied": [],
  "warnings": [
    "[DE] State crossings use generalized NUTS 2024 boundaries and may differ slightly near borders.",
    "[DE] route.roadSpansComplete is not true. Summer-road coverage may require manual review.",
    "[CH] Swiss entry and exit points use a generalized GISCO 2024 country boundary and may differ slightly near borders.",
    "[FR] French country and regional entry/exit points use generalized GISCO 2024 boundaries and may differ slightly near borders.",
    "No temporary-order clearance covers the complete journey. A competent authority or maintained live-order feed must verify temporary bans and exemptions."
  ],
  "manualReviewRequired": true,
  "routeAnalysis": "(routeAnalysis, shortened here)",
  "journeyConflicts": "(journeyConflicts, shortened here)",
  "departureOptions": [],
  "ruleSetVersion": "DE-2026.07.26-v2.2 + CH-2026.07.26-v1.1 + FR-2026.07.26-v1.1",
  "evaluatedAt": "2026-07-28T13:47:48.897Z",
  "error": null,
  "ruleValidity": {
    "validFrom": "2026-01-01T00:00:00+01:00",
    "validThrough": "2026-12-31T23:59:59.999+01:00",
    "journeyCovered": true
  },
  "countryAssessments": "(countryAssessments, shortened here)",
  "temporaryOrderAssessment": {
    "status": "NOT_VERIFIED",
    "clearanceCoversJourney": false,
    "checkedAt": null,
    "validFrom": null,
    "validThrough": null,
    "authority": null,
    "referenceUrl": null
  }
}
````

The same route on a Tuesday morning hits no statutory ban, and the Actor still does
not hand out a naked green light. It returns `CONDITIONAL` with zero restrictions,
names exactly what remains unverified (generalized border geometry, incomplete road
spans, temporary orders), and sets `manualReviewRequired` accordingly. When the answer
depends on evidence the Actor does not have, it says so:

```json
{
  "queryId": "freiburg-geneva-lyon-tuesday-morning",
  "country": "AUTO",
  "decision": "CONDITIONAL",
  "departureTime": "2026-07-28T10:00:00+02:00",
  "nextLegalDeparture": null,
  "subjectToTruckBanRules": true,
  "routeStates": [
    "DE-BW"
  ],
  "restrictions": [],
  "exemptionsApplied": [],
  "warnings": [
    "[DE] State crossings use generalized NUTS 2024 boundaries and may differ slightly near borders.",
    "[DE] route.roadSpansComplete is not true. Summer-road coverage may require manual review.",
    "[CH] Swiss entry and exit points use a generalized GISCO 2024 country boundary and may differ slightly near borders.",
    "[FR] French country and regional entry/exit points use generalized GISCO 2024 boundaries and may differ slightly near borders.",
    "No temporary-order clearance covers the complete journey. A competent authority or maintained live-order feed must verify temporary bans and exemptions."
  ],
  "manualReviewRequired": true,
  "routeAnalysis": {
    "distanceKm": 350.46,
    "durationMinutes": 330,
    "estimatedArrivalTime": "2026-07-28T15:30:00+02:00",
    "detectedCountries": [
      "DE",
      "CH",
      "FR"
    ],
    "countryVisits": "(per-border entry and exit timestamps, shortened here)"
  },
  "journeyConflicts": [],
  "departureOptions": [],
  "ruleSetVersion": "DE-2026.07.26-v2.2 + CH-2026.07.26-v1.1 + FR-2026.07.26-v1.1",
  "evaluatedAt": "2026-07-28T21:22:18.361Z",
  "error": null,
  "ruleValidity": {
    "validFrom": "2026-01-01T00:00:00+01:00",
    "validThrough": "2026-12-31T23:59:59.999+01:00",
    "journeyCovered": true
  },
  "countryAssessments": "(countryAssessments, shortened here)",
  "temporaryOrderAssessment": {
    "status": "NOT_VERIFIED",
    "clearanceCoversJourney": false,
    "checkedAt": null,
    "validFrom": null,
    "validThrough": null,
    "authority": null,
    "referenceUrl": null
  }
}
```

This Actor is also exposed to AI agents through Apify's MCP server
(mcp.apify.com): an agent can discover it by search and run it with the same
pay-per-event billing, with no separate integration.

### Input

Pass one or more queries in a `queries` array. Batch queries reduce Actor startup cost.

```json
{
  "queries": [
    {
      "queryId": "a8-journey-crosses-summer-ban",
      "country": "DE",
      "departureTime": "2026-07-11T04:30:00+02:00",
      "vehicle": {
        "isTruck": true,
        "maximumPermissibleWeightTonnes": 18,
        "hasTrailer": true
      },
      "transport": {
        "isCommercialOrPaidGoodsTransport": true,
        "cargoCategory": "GENERAL"
      },
      "route": {
        "geometry": {
          "type": "LineString",
          "coordinates": [
            [8.44, 48.97],
            [9.11, 48.79],
            [10.03, 48.45],
            [10.83, 48.36],
            [11.47, 48.18]
          ]
        },
        "segmentDurationsMinutes": [45, 55, 80, 60],
        "plannedStops": [
          {
            "coordinateIndex": 2,
            "durationMinutes": 30,
            "label": "Driver break"
          }
        ],
        "roadSpans": [
          {
            "roadRef": "A8",
            "startCoordinateIndex": 0,
            "endCoordinateIndex": 4
          }
        ],
        "roadSpansComplete": true
      },
      "includeNextLegalDeparture": true
    }
  ]
}
```

Times without a UTC offset are interpreted in `Europe/Berlin` for Germany,
`Europe/Zurich` for Switzerland, and `Europe/Paris` for France.

Use `country: "AUTO"` only with a route. The geometry is evaluated against all supported countries and the strictest country result wins.

#### Temporary-order evidence

An annual calendar cannot prove that a temporary authority order does not apply. Supply a check created by your maintained official-order workflow:

```json
{
  "status": "VERIFIED_CLEAR",
  "checkedAt": "2026-07-13T20:55:00+02:00",
  "validFrom": "2026-07-13T20:00:00+02:00",
  "validThrough": "2026-07-14T06:00:00+02:00",
  "authority": "Name of the competent authority or maintained feed",
  "referenceUrl": "https://authority.example/order-register"
}
```

Do not mark a check `VERIFIED_CLEAR` unless its source covers every relevant jurisdiction and the complete journey interval. Applicable exemptions always remain `CONDITIONAL` pending documentary review.

#### Route geometry and timing

Supply exactly one route representation:

- `route.geometry`: GeoJSON `LineString` coordinates in `[longitude, latitude]` order;
- `route.encodedPolyline`: Google-style encoded polyline, with `polylinePrecision` set to `5` or `6`;
- `route.providerRoute`: an already-fetched OSRM, Google Routes, HERE Routing v8, or TomTom response.

For raw geometry, choose one timing model:

- `durationMinutes`: backward-compatible fallback distributed proportionally over route distance;
- `segmentDurationsMinutes`: one non-negative value for every pair of consecutive coordinates. This is the preferred model for traffic-aware or provider-derived timestamps.

If both are supplied, `durationMinutes` must equal the segment-duration sum. The total journey, including stops, may not exceed 10,080 minutes.

Add `plannedStops` to delay subsequent movement:

```json
{
  "coordinateIndex": 2,
  "durationMinutes": 30,
  "label": "Driver break"
}
```

A stop must reference an intermediate coordinate. Stationary time shifts later state and road arrival times but is excluded from the moving intervals checked against driving bans.

#### Routing-provider adapters

The Actor normalizes supplied provider responses locally; it does not call a paid routing API or require API keys.

```json
{
  "providerRoute": {
    "provider": "OSRM",
    "routeIndex": 0,
    "polylinePrecision": 5,
    "response": {
      "code": "Ok",
      "routes": []
    }
  }
}
```

Supported provider values:

- `OSRM`: step geometry, step duration, and structured `ref` values;
- `GOOGLE_ROUTES`: route/step polylines and duration strings. Road numbers extracted from navigation text remain inferred, so summer-road decisions stay `CONDITIONAL` without explicit structured spans;
- `HERE_ROUTING_V8`: flexible polylines, section durations, and `spans[].routeNumbers`;
- `TOMTOM_ROUTING`: Orbis/v2 leg paths or polylines, leg durations, and indexed instruction road numbers.

Request full step/section geometry and road-number fields from the provider when a definite summer-road decision is required. Caller-supplied `roadSpans`, segment durations, and aggregate duration override adapter-derived values.

#### Road spans

Raw geometry does not prove which of two nearby or parallel roads the vehicle uses. For a definite summer-road decision, provide ordered routing-provider metadata:

```json
{
  "roadRef": "A8",
  "startCoordinateIndex": 0,
  "endCoordinateIndex": 4
}
```

Set `roadSpansComplete: true` only when the spans cover the full coordinate sequence without gaps. Geometry without complete road-span coverage remains `CONDITIONAL` during a summer Saturday window instead of producing an unsafe `ALLOWED`.

For B31 and B96, also set `outsideBuiltUpArea: true` on the relevant span when the matched part is confirmed to be outside built-up areas.

#### German state codes

Use ISO 3166-2 codes:

`DE-BW`, `DE-BY`, `DE-BE`, `DE-BB`, `DE-HB`, `DE-HH`, `DE-HE`, `DE-MV`, `DE-NI`, `DE-NW`, `DE-RP`, `DE-SL`, `DE-SN`, `DE-ST`, `DE-SH`, `DE-TH`.

#### Swiss vehicle and exemption fields

For the common heavy-truck case, `maximumPermissibleWeightTonnes > 3.5` is sufficient. Lighter towing or articulated combinations should also supply:

- `vehicle.isArticulated`;
- `vehicle.maximumPermissibleCombinationWeightTonnes`;
- `vehicle.trailerMaximumPermissibleWeightTonnes`.

For the narrow zero-emission excess-weight exemption, assert both
`hasZeroEmissionDrive` and `excessWeightOnlyDueToZeroEmissionDrive`.

`transport.swissExemptionCategory` accepts:

- `NONE`
- `PERSON_TRANSPORT`
- `AGRICULTURE_OR_FORESTRY`
- `EMERGENCY_CUSTOMS_OR_MILITARY`
- `POSTAL_BASIC_SERVICE`
- `QUALIFYING_PERISHABLE_FOOD`
- `LIVE_ANIMALS`
- `PERISHABLE_WITHIN_ONE_DAY`
- `NEWS_OR_CURRENT_REPORTING`
- `BREAKDOWN_OR_WINTER_SERVICE`
- `INFRASTRUCTURE_OR_PUBLIC_SPACE_MAINTENANCE`

These values are caller assertions. Categories whose factual or documentary conditions cannot be verified from input produce `CONDITIONAL`.

On a listed Swiss holiday, set `swissHolidayObserved: true` only when the day is observed in the affected canton or canton part; set it to `false` when it is not. Omit it for a fail-closed `CONDITIONAL`.

#### French vehicle, regional-route, and exemption fields

Set `transport.isGoodsTransport` when the movement is goods transport but is
not accurately described by `isCommercialOrPaidGoodsTransport`. If omitted,
the existing commercial/paid-goods flag is used.

`vehicle.franceVehicleCategory` accepts:

- `STANDARD_GOODS`
- `SPECIALIZED`
- `AGRICULTURAL`

For a listed 2026 winter Saturday, set
`franceUsesRestrictedWinterNetwork: true` only when the route uses one of the
Auvergne-Rhône-Alpes sections in the annual order. Set it to `false` after
route verification. A route entering that region without this assertion stays
`CONDITIONAL` during the 07:00-18:00 window.

For permanent Île-de-France motorway restrictions, use:

- `franceIleDeFranceRestrictedRoadUsage`;
- `franceIleDeFranceDirection`: `PARIS_TO_PROVINCE` or
  `PROVINCE_TO_PARIS`.

Geometry detects entry into Île-de-France, but it cannot by itself prove use
of the legally listed part of a parallel motorway or the legal direction.
Complete structured road spans can prove that no listed road is used.
If a listed road is present but direction is missing, the result remains
`CONDITIONAL`. Article 4 exemptions do not override these particular motorway
windows.

`transport.franceExemptionCategory` accepts:

- `NONE`
- `LIVE_ANIMALS_OR_PERISHABLES`
- `AGRICULTURAL_HARVEST`
- `AUTHORIZED_EVENT`
- `PRESS_OR_ELECTION_MATERIAL`
- `OFFICE_OR_FACTORY_RELOCATION`
- `MOBILE_SALE`
- `FAIR_OR_MARKET`
- `AIR_FREIGHT`
- `HEALTHCARE_OR_MEDICAL`
- `INDUSTRIAL_GAMMAGRAPHY`
- `EMERGENCY_NETWORK_REPAIR`
- `TRANSPORT_INFRASTRUCTURE_SAFETY`
- `QUALIFYING_FUEL_SUPPLY`
- `QUALIFYING_WASTE_COLLECTION`

French exemptions depend on cargo, loading, geographic, timing, or document
conditions the Actor cannot independently verify, so an asserted category
returns `CONDITIONAL` and identifies the evidence that must be checked.

#### Cargo categories

- `GENERAL`
- `FRESH_MILK_OR_DAIRY`
- `FRESH_MEAT`
- `FRESH_OR_LIVE_FISH`
- `PERISHABLE_FRUIT_OR_VEGETABLES`
- `SPECIFIED_ANIMAL_BYPRODUCTS`
- `LIVE_BEES`
- `RECOVERY_TOW_OR_BREAKDOWN`
- `EMPTY_RUN_RELATED_TO_EXEMPT_TRANSPORT`
- `FEDERAL_REQUISITION`
- `AUTHORIZED_MILITARY_TRANSPORT`

Cargo categories are caller assertions. Carry and verify the legally required freight and supporting documents.

#### Legacy departure-only mode

Queries without `route` continue to support `routeStates`, `routeRoads`, and `routeIncludesRestrictedSummerSegment`.

- Set `routeIncludesRestrictedSummerSegment: true` only after route geometry confirms a listed section.
- Set it to `false` only after confirming that no listed section is used.
- Omit it to receive a safe `CONDITIONAL` decision when a listed road might match.

### Output

```json
{
  "queryId": "a8-journey-crosses-summer-ban",
  "country": "DE",
  "decision": "PROHIBITED",
  "departureTime": "2026-07-11T04:30:00+02:00",
  "nextLegalDeparture": "2026-07-11T20:00:00+02:00",
  "subjectToTruckBanRules": true,
  "routeStates": ["DE-BW", "DE-BY"],
  "restrictions": [
    {
      "code": "DE_FERREISEV_SUMMER_SATURDAY",
      "certainty": "DEFINITE",
      "startsAt": "2026-07-11T07:00:00+02:00",
      "endsAt": "2026-07-11T20:00:00+02:00",
      "source": {
        "url": "https://www.bmv.de/SharedDocs/DE/Artikel/StV/Strassenverkehr/lkw-fahrverbot-in-der-ferienreisezeit.html"
      }
    }
  ],
  "routeAnalysis": {
    "distanceKm": 241.72,
    "durationMinutes": 270,
    "drivingDurationMinutes": 240,
    "plannedStopDurationMinutes": 30,
    "timingMethod": "SEGMENT_DURATIONS",
    "estimatedArrivalTime": "2026-07-11T09:00:00+02:00",
    "detectedStates": ["DE-BW", "DE-BY"],
    "detectedSummerSegments": [
      {
        "road": "A8",
        "certainty": "DEFINITE"
      }
    ]
  },
  "journeyConflicts": [
    {
      "restrictionCode": "DE_FERREISEV_SUMMER_SATURDAY",
      "conflictAt": "2026-07-11T07:00:00+02:00",
      "road": "A8"
    }
  ],
  "departureOptions": [
    {
      "type": "DEPART_BEFORE",
      "time": "2026-07-11T03:00:00+02:00",
      "inclusive": false
    },
    {
      "type": "DEPART_AT_OR_AFTER",
      "time": "2026-07-11T20:00:00+02:00",
      "inclusive": true
    }
  ],
  "exemptionsApplied": [],
  "manualReviewRequired": false,
  "ruleSetVersion": "DE-2026.07.26-v2.2"
}
```

### Official sources

- [German Road Traffic Regulations, StVO § 30](https://www.gesetze-im-internet.de/stvo_2013/__30.html)
- [Federal Ministry of Transport: summer holiday-season truck ban and 2026 road list](https://www.bmv.de/SharedDocs/DE/Artikel/StV/Strassenverkehr/lkw-fahrverbot-in-der-ferienreisezeit.html)
- [Federal Office for Logistics and Mobility: Sunday and holiday restrictions](https://www.balm.bund.de/DE/Themen/RechtsentwicklungRechtsvorschriften/Rechtsvorschriften/Strassenverkehrsrecht/LKW-Fahrverbote/LKW-Fahrverbote.html)
- [Eurostat GISCO: NUTS 2024 geographic data](https://gisco-services.ec.europa.eu/distribution/v2/nuts/)
- [Swiss Traffic Rules Ordinance (VRV), Art. 91-92](https://www.fedlex.admin.ch/eli/cc/1962/1364_1409_1420/de)
- [ASTRA: Sunday and night journeys](https://www.astra.admin.ch/de/sonntags-und-nachtfahrten)
- [ASTRA: holidays with driving ban](https://www.astra.admin.ch/de/feiertage-mit-fahrverbot)
- [ASTRA: changes effective 1 July 2026](https://www.astra.admin.ch/de/anpassungen-zu-fahrverboten-und-rundstreckenrennen)
- [French order of 16 April 2021: general, seasonal, Île-de-France, and exemption rules](https://www.legifrance.gouv.fr/loda/id/JORFTEXT000043416004/)
- [French order of 26 December 2025: additional restrictions for 2026](https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000053324056)
- [Bison Futé: official 2026 heavy-vehicle calendar](https://www.bison-fute.gouv.fr/IMG/pdf/26056_BROCHURE_2026_FR.pdf)

### Run locally

```bash
npm install
npm run build
npm test
npm run rules:audit
npm run release:check
```

`rules:audit` fetches seven primary German, Swiss, and French official sources, compares
semantic fingerprints, verifies required legal anchors, and diffs the complete
German summer road list. It exits non-zero with `CHANGED` or `UNREACHABLE`, making it suitable
for a scheduled CI or Apify maintenance monitor. A detected change is an alert
for human legal review; it never rewrites the rule set automatically.

To run through local Apify storage:

```bash
mkdir -p storage/key_value_stores/default
cp examples/input.json storage/key_value_stores/default/INPUT.json
npm start
```

Results are written to the local default dataset.

### Pay per event

The publish bundle defines two custom events in `.actor/pay_per_event.json`:

- `restriction-check`: $0.02 for a validated departure-only result;
- `route-restriction-check`: $0.08 for a validated route-aware result, including `AUTO`.

The Actor saves and charges each successful result in one `Actor.pushData` call and stops when the user's charge limit is reached.

Invalid input rows are returned as `ERROR` results without the custom event charge.

### Disclaimer

This Actor provides automated decision support, not legal advice or a permit to drive. State boundaries are generalized, summer corridors are operational matching geometry, and timing quality depends on the supplied route data. Before dispatch, verify route geometry, road-span metadata, temporary orders, official permits, vehicle classification, cargo classification, and supporting documents with the responsible authority or qualified transport-compliance professional.

# Actor input Schema

## `queries` (type: `array`):

Paste one or more query objects. The Actor performs strict nested runtime validation. Supply exactly one of route.geometry, route.encodedPolyline, or route.providerRoute. Times use ISO 8601 and must fall inside 2026. Maximum batch size is 250 and complete input is limited to 10 MiB. Billing: $0.02 per point-in-time restriction check and $0.08 per full route decision with border-crossing timing; a decision always includes its statutory citations, and when evidence is missing the answer is CONDITIONAL with manualReviewRequired instead of a guess.

## Actor input object example

```json
{
  "queries": [
    {
      "queryId": "freiburg-geneva-lyon-auto",
      "country": "AUTO",
      "departureTime": "2026-07-13T21:00:00+02:00",
      "vehicle": {
        "isTruck": true,
        "maximumPermissibleWeightTonnes": 18,
        "hasTrailer": false,
        "franceVehicleCategory": "STANDARD_GOODS"
      },
      "transport": {
        "isCommercialOrPaidGoodsTransport": true,
        "isGoodsTransport": true,
        "cargoCategory": "GENERAL",
        "swissExemptionCategory": "NONE",
        "franceExemptionCategory": "NONE"
      },
      "route": {
        "geometry": {
          "type": "LineString",
          "coordinates": [
            [
              7.85,
              47.99
            ],
            [
              7.59,
              47.56
            ],
            [
              6.14,
              46.2
            ],
            [
              4.84,
              45.76
            ]
          ]
        },
        "segmentDurationsMinutes": [
          30,
          180,
          120
        ]
      },
      "includeNextLegalDeparture": true
    }
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("kamerozkan/europe-truck-dispatch-guard").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("kamerozkan/europe-truck-dispatch-guard").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call kamerozkan/europe-truck-dispatch-guard --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=kamerozkan/europe-truck-dispatch-guard",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Europe Truck Dispatch Guard - Germany, Switzerland & France",
        "description": "Route-aware 2026 truck-ban decisions for Germany, Switzerland, France, and cross-border journeys, with official sources and safer departure times.",
        "version": "0.6",
        "x-build-id": "Ov9M3jptgujNU4KNe"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/kamerozkan~europe-truck-dispatch-guard/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-kamerozkan-europe-truck-dispatch-guard",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/kamerozkan~europe-truck-dispatch-guard/runs": {
            "post": {
                "operationId": "runs-sync-kamerozkan-europe-truck-dispatch-guard",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/kamerozkan~europe-truck-dispatch-guard/run-sync": {
            "post": {
                "operationId": "run-sync-kamerozkan-europe-truck-dispatch-guard",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "queries"
                ],
                "properties": {
                    "queries": {
                        "title": "Restriction queries",
                        "minItems": 1,
                        "maxItems": 250,
                        "type": "array",
                        "description": "Paste one or more query objects. The Actor performs strict nested runtime validation. Supply exactly one of route.geometry, route.encodedPolyline, or route.providerRoute. Times use ISO 8601 and must fall inside 2026. Maximum batch size is 250 and complete input is limited to 10 MiB. Billing: $0.02 per point-in-time restriction check and $0.08 per full route decision with border-crossing timing; a decision always includes its statutory citations, and when evidence is missing the answer is CONDITIONAL with manualReviewRequired instead of a guess.",
                        "items": {
                            "type": "object"
                        },
                        "default": [
                            {
                                "queryId": "freiburg-geneva-lyon-auto",
                                "country": "AUTO",
                                "departureTime": "2026-07-13T21:00:00+02:00",
                                "vehicle": {
                                    "isTruck": true,
                                    "maximumPermissibleWeightTonnes": 18,
                                    "hasTrailer": false,
                                    "franceVehicleCategory": "STANDARD_GOODS"
                                },
                                "transport": {
                                    "isCommercialOrPaidGoodsTransport": true,
                                    "isGoodsTransport": true,
                                    "cargoCategory": "GENERAL",
                                    "swissExemptionCategory": "NONE",
                                    "franceExemptionCategory": "NONE"
                                },
                                "route": {
                                    "geometry": {
                                        "type": "LineString",
                                        "coordinates": [
                                            [
                                                7.85,
                                                47.99
                                            ],
                                            [
                                                7.59,
                                                47.56
                                            ],
                                            [
                                                6.14,
                                                46.2
                                            ],
                                            [
                                                4.84,
                                                45.76
                                            ]
                                        ]
                                    },
                                    "segmentDurationsMinutes": [
                                        30,
                                        180,
                                        120
                                    ]
                                },
                                "includeNextLegalDeparture": true
                            }
                        ]
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
