Example Requests
All the data providers use OGC standard interfaces to provide access to their data. This means that everything you see in the portals can be accessed using service requests. You can run all these requests from your browser's address bar, or you can programmatically retrieve the data using python.
The two requests below use the road network WMS endpoint. The first request retrieves an image containing the roads in a particular area of the country. To understand the image, the second request retrieves the corresponding legend.
Image of road segments (wegvakken) within a specific bounding box (1):https://service.pdok.nl/rws/nwbwegen/wms/v1_0
?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=true&STYLES=&LAYERS=wegvakken&CRS=EPSG:28992&WIDTH=1651&HEIGHT=971&BBOX=161394.36645978806,445201.2912702344,175711.13939109148,453621.3921280755

Road network layer legend:https://service.pdok.nl/rws/nwbwegen/wms/v1_0/legend/wegvakken/wegvakken.png
Similarly, the following requests target the land cover WMS and WFS endpoints. This time besides the legend and an image of the dataset, we request a description of the service, and also retrieve features. First we retrieve some arbitrary features using a simple count limit, and then a more specific set of features using a combination of spatial and thematic filters.
Service metadata of the land cover WMS service:https://service.pdok.nl/cbs/bestandbodemgebruik/2017/wms/v1_0
?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities
Land cover layer legend (2):https://service.pdok.nl/cbs/bestandbodemgebruik/2017/wms/v1_0/legend/bestandbodemgebruik_2017_hoofdgroep/bestand_bodemgebruik_2017_hoofdgroep.png
?

Image of land cover classes (Bestand bodemgebruik 2017) within a given bounding box (3):https://service.pdok.nl/cbs/bestandbodemgebruik/2017/wms/v1_0
?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=true&STYLES=&LAYERS=bestandbodemgebruik_2017_hoofdgroep&CRS=EPSG:28992&WIDTH=300&HEIGHT=200&BBOX=250000,465000,265000,475000

Five arbitrary features from the land cover layer, encoded using GML:https://service.pdok.nl/cbs/bestandbodemgebruik/2017/wfs/v1_0
?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAME=bestandbodemgebruik:BBG2017&MAXFEATURES=5
Three features of the 'Water' land cover class intersecting with a given bounding box encoded in GML:https://service.pdok.nl/cbs/bestandbodemgebruik/2015/wfs/v1_0
?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&TYPENAME=bestand_bodemgebruik_2015_bodemgebruik&FILTER=<Filter><And><PropertyIsEqualTo><PropertyName>bestandbodemgebruik2015:bodemgebruik</PropertyName><Literal>Water</Literal></PropertyIsEqualTo><Intersects><PropertyName>GEOMETRY</PropertyName><gml:Box><gml:coord><gml:X>252100</gml:X> <gml:Y>467100</gml:Y></gml:coord><gml:coord><gml:X>260700</gml:X> <gml:Y>474200</gml:Y></gml:coord></gml:Box></Intersects></And></Filter>&MAXFEATURES=3
The OSM data can be downloaded in various formats and using various APIs. The following request uses Geofabrik to download a zip file containing the data as a collection of shapefiles. Explore the files to identify the one containing the bikes paths data. See 4 for an overview of the bikes paths in Overijssel.
OSM data for the Overijssel region:https://download.geofabrik.de/europe/netherlands/overijssel-latest-free.shp.zip

In terms of air quality data, RIVM uses the OGC's SensorThings API. This API gives you access to different elements available within the sensor network. See 5 and 1 for a quick overview of the API's conceptual elements. For more detailed information visit the OGC's website (OGC SensorThings API).

SensorThings API - Model elements
Entity | Description |
---|---|
Thing | A Thing is an object of the physical world (physical things) or the information world (virtual things) which is capable of being identified and integrated into communication network. |
Location | A Location entity georeferences the Thing or the Things it is associated with. |
Datastream | A Datastream groups a collection of Observations measuring the same ObservedProperty and produced by the same Sensor. |
Sensor | An instrument that observes a property or phenomenon with the goal of producing an estimate of the value of the property. |
ObservedProperty | An ObservedProperty specifies the phenomenon of an Observation. |
Observation | An Observation is the act of measuring or otherwise determining the value of a property. |
FeatureOfInterest | An Observation results in a value being assigned to a phenomenon. The phenomenon is a property of a feature, the latter being the FeatureOfInterest of the Observation. |
The requests below use different components of the API to obtain observations from the network. The first example filters by the name of the network instrument where the sensors are installed. The second one filters using a geometry object, in this case a simple polygon. The third example focuses on the identifier of one of the network instruments and retrieves all entities of other types associated with it. This request uses as a filter the identifier of the network instrument, the Thing. The last request gets the data of an available parameter by means of the DataStream identifier.
List all Things whose identifiying mane starts with the prefix 'SSK_LH':https://api-samenmeten.rivm.nl/v1.0/Things
?$filter=startswith(name,'SSK_LH')
List available Locations that intersect with a given polygon:https://api-samenmeten.rivm.nl/v1.0/Locations
?$filter=st_intersects(location, geography'POLYGON((6.7157 52.1472, 7.0210 52.1472, 7.0210 52.2995, 6.7157 52.2995, 6.7157 52.1472))')
Get the list of entities associated with a Thing using the Thing's unique identifier:https://api-samenmeten.rivm.nl/v1.0/Things(1768)
?$expand=Locations,Datastreams,Datastreams/Sensor,Datastreams/ObservedProperty
Get available Obervations of a Datastream over a given time period:https://api-samenmeten.rivm.nl/v1.0/Datastreams(26927)/Observations
?$filter=date(phenomenonTime) gt date('2021-11-03')
A similar approach can be used to exploit the OpenSenseMap API, however this API does not have many features.
One of ITC's managed SenseBoxes:https://opensensemap.org/explore/5dc6d9f67d4ff7001a11fcb1
?
Metadata of the same SenseBox:https://api.opensensemap.org/boxes/5dc6d9f67d4ff7001a11fcb1
?format=json
At some point your requests will be too elaborated to execute them through the browser. In some cases, complex queries will require a long response time and the browser will simply give up waiting. In other cases, the response body might be too large for the browser to handle. Or maybe you are just feeling like you can script your way out of trouble. 1 shows a simple script using Python to send a request and process the response. Since the data that is received by the script is encoded using JSON, a dictionary is used to operate on the data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
import urllib3 import json http = urllib3.PoolManager() # Bounding Box min_lat = 52.1472 max_lat = 52.2995 min_lng = 6.7157 max_lng = 7.0210 output_path = "samenmeten_locations.csv" service_url = "https://api-samenmeten.rivm.nl/v1.0/Locations?$top=200&$skip=0" # main with open(output_path, "w") as file: file.write("id,name, description, lng, lat\n") while (service_url != ""): request = http.request('GET', service_url) data = json.loads(request.data.decode('utf-8')) for item in data["value"]: lng = item["location"]["coordinates"][0] lat = item["location"]["coordinates"][1] if ((min_lat <= lat <= max_lat) and (min_lng <= lng <= max_lng)): file.write("{0},{1},{2},{3},{4}\n" .format(item["@iot.id"], item["name"], item["description"], lng, lat)) # Update the request with new page parameters if ("@iot.nextLink" in data): service_url = data["@iot.nextLink"] else: service_url = "" # end |