Incident details

trafficIncidentDetails returns the current and planned traffic incidents of an area, or of a list of known incident IDs, as a GeoJSON FeatureCollection (TrafficIncidentDetails). Each incident is a Point or LineString feature, ready to process server-side or to draw with the Traffic Incident Details Module. The Node.js incident details example prints the incidents in Amsterdam right now.

Core concepts

An incident (TrafficIncident) carries:

Basic usage

A call takes exactly one of bbox, polygon or ids.

Query by bounding box

bbox takes a [west, south, east, north] tuple or any GeoJSON object. For an object, the SDK computes its bounding box:

import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
import { geocodeOne, trafficIncidentDetails } from '@tomtom-org/maps-sdk/services';

TomTomConfig.instance.put({ apiKey: 'YOUR_API_KEY' });

const place = await geocodeOne('Amsterdam');
const result = await trafficIncidentDetails({ bbox: place });

result.features.forEach((incident) => {
    const { category, magnitudeOfDelay, from, to } = incident.properties;
    console.log(`${category} — ${magnitudeOfDelay} delay: ${from} → ${to}`);
});

const inBox = await trafficIncidentDetails({ bbox: [4.728, 52.278, 5.08, 52.479] });

The bounding box covers at most 10,000 km².

Query by polygon

A bounding box covers more than any place that isn't a rectangle. Pass the place's boundary as polygon instead, such as the one geometryData returns:

import { geocodeOne, geometryData, trafficIncidentDetails } from '@tomtom-org/maps-sdk/services';

const place = await geocodeOne('Amsterdam');
const boundary = await geometryData({ geometries: [place] });
const result = await trafficIncidentDetails({ polygon: boundary });

Query by incident IDs

const result = await trafficIncidentDetails({
    ids: ['incident-id-1', 'incident-id-2', 'incident-id-3'],
});

Find the incident of a route traffic section

A route's traffic section (TrafficSectionProps) carries an eventId. It is the tail of the incident's id, not that id, so ids doesn't find it. Query the section's bounding box instead, and keep the incident whose id ends with the eventId:

import { getSectionBBox } from '@tomtom-org/maps-sdk/core';
import { calculateRoute, trafficIncidentDetails } from '@tomtom-org/maps-sdk/services';

const routes = await calculateRoute({ locations: [[2.3522, 48.8566], [4.8357, 45.764]] });
const route = routes.features[0];

for (const section of route.properties.sections.traffic ?? []) {
    const { eventId } = section;
    const bbox = getSectionBBox(route, section);
    if (!eventId || !bbox) continue;

    const incidents = await trafficIncidentDetails({ bbox });
    const incident = incidents.features.find(({ properties }) => properties.id.endsWith(eventId));
    console.log(incident?.properties.events[0]?.description);
}

Query one section at a time. The bounding box of a whole route can cover more than 10,000 km².

Filtering results

By category

categoryFilter keeps the given categories:

const result = await trafficIncidentDetails({
    bbox: [4.728, 52.278, 5.08, 52.479],
    categoryFilter: ['accident', 'road-closed'],
});

It takes the trafficIncidentRequestCategories (TrafficIncidentRequestCategory). The two other values of fullTrafficIncidentCategories, 'animals-on-road' and 'narrow-lanes', occur only on the traffic vector tiles, so this service neither accepts nor returns them.

Value Description
'accident' Traffic accident or collision
'broken-down-vehicle' Vehicle breakdown causing obstruction
'danger' Dangerous situation on the road
'flooding' Flooded road section
'fog' Fog reducing visibility
'frost' Frost or ice on the road
'jam' Traffic congestion or slow-moving traffic
'lane-closed' One or more lanes closed
'other' Other incidents
'rain' Heavy rain affecting driving conditions
'road-closed' Road closed or blocked
'roadworks' Construction or maintenance work
'wind' Strong wind affecting traffic

By time validity

By default, only 'present' incidents come back. Add 'future' for planned works and scheduled events:

const result = await trafficIncidentDetails({
    bbox: [4.728, 52.278, 5.08, 52.479],
    timeValidityFilter: ['present', 'future'],
});

The service has no past incidents, so you can't ask which incidents were in force on an earlier day.

By severity

The request has no magnitude filter, so filter the response on magnitudeOfDelay:

const severeIncidents = result.features.filter(({ properties }) =>
    properties.magnitudeOfDelay === 'major' || properties.magnitudeOfDelay === 'indefinite',
);

Working with incident data

Reading incident properties

const incident = result.features[0];

incident.geometry.type; // 'Point' | 'LineString'

const {
    id,
    category,
    magnitudeOfDelay,
    events,                  // [{ description, code, category }]
    from,
    to,
    lengthInMeters,
    delayInSeconds,
    roadNumbers,             // e.g. ['A10']
    timeValidity,            // 'present' | 'future'
    probabilityOfOccurrence, // 'certain' | 'probable' | 'risk_of' | 'improbable'
    startTime,               // Date | undefined
    endTime,                 // Date | undefined
    numberOfReports,
    lastReportTime,          // Date | undefined
} = incident.properties;

TrafficIncidentProperties lists which are always present.

Displaying on a map

The Traffic Incident Details Module draws the response in the style's incident look. Its setFocus highlights a subset:

import { TrafficIncidentDetailsModule } from '@tomtom-org/maps-sdk/map';

const incidentDetailsModule = await TrafficIncidentDetailsModule.create(map);
await incidentDetailsModule.show(result);

Error handling

A failed call rejects with an SDKError whose code says what went wrong. An API error rejects with an SDKServiceError, which also carries the HTTP status. An invalid request, such as one with both bbox and ids, rejects before it is sent (Error handling).

API reference

Related guides and examples

Related examples

Related guides