Kadaster BRK versie 4.0

Hoi Pdok,

Ik ben de nieuw server aan het testen van het kadaster 4.0. Het valt mij op dat het aantal hits ten behoeve van pagenummering niet goed werkt. Het aantal numberMatched=“28316995” is voordurend hetzelfde en aan de veelste hoge kant. Kunnen jullie hiernaar kijken? Zie url

http://geodata.nationaalgeoregister.nl/kadastralekaart/wfs/v4_0?service=wfs&request=GetFeature&typeNames=kadastralekaartv4:kadastralegrens&bbox=213089,593892,217076,597981&version=2.0.0&resultType=hits

Beste,

Het aantal hits is alleen geïmplementeerd voor alle features in een layer. Wanneer je een bbox of filter opgeeft wordt “unknown” teruggegeven. Dit is gedaan omdat het tellen van features op basis van een bbox of filter een dure operatie is. Volgens de WFS standaard mag je in dergelijke gevallen een “unknown” teruggeven.

Voor welke use case heb je deze aantallen nodig? We bieden namelijk ook een download aan die wellicht beter bij deze use case past.

Beste Hulstg,

Voor het bepalen van het aantal paginering (startindex) bepaal ik eerst het totaal aantal hits (features) gezien het downloadlimiet van 1000 features per aanvraag.

Na het bepalen van het aantal resulthits pas ik een script toe die elke keer 1000 features download…voorbeeld

https://geodata.nationaalgeoregister.nl/kadastralekaartv3/wfs?&REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&TYPENAME=kadastralegrens&BBOX=" + bbox + “&SRSNAME=EPSG:28992&OUTPUTFORMAT=GML2&COUNT=1000&STARTINDEX=” + StartIndex

Kunnen jullie de resulttype=hits beschikbaar maken op de Versie4 server net als bij versie 3 van het kadaster?

Beste,

We kunnen helaas de resulttype=hits niet zomaar beschikbaar maken. De impact op de performance is simpelweg te hoog. Als ik het goed begrijp probeer je door middel van pagineren features te downloaden. Hiervoor is de WFS niet bedoelt. Je kan bijvoorbeeld ook geen startIndex gebruiken die boven de 10.000 is. De WFS is bedoelt om specifieke vragen aan te stellen. Als je de features wil downloaden kan je hiervoor de download functionaliteit gebruiken PDOK download viewer.

Is het dan mogelijk om via deze api download server een rmet een geofilter url rechtstreek een gebied te downloaden zonder eerst naar de viewer te gaan? Zo kan ik vector data rechtstreek inladen in bijvoorbeeld autocad

Ja dat kan. De viewer is slechts een frontend op de download API. Een beschrijving van deze API kun je hier vinden: PDOK API - Swagger UI

Hoi Reijer,

Heb je een voorbeeld url met polygon (geofilter) waarbij ik rechtstreeks een gebied kan download zonder gebruik te maken van de viewer? Voor mij is de api download nieuw en ik begrijp nog niet zoveel van.

Hoi Mark? de Bakker,

Een (rest) api zoals die van de kadastrale kaart is een manier om via urls op een systematische manier data op te halen. Hier kan je zien hoe je een custom download kan doen:

https://downloads.pdok.nl/kadastralekaart/api/v4_0/ui/#/Delta%20Custom/DeltaCustomDownload

Die url bestaat uit:

De beschrijving van die endpoints dus via het schema in deze link te vinden. Waarbij alleen de endpoints te lezen zijn. Om zo’n url te volgen moet je dus wel eerst de api root en versie voor het endpoint plakken: https://downloads.pdok.nl/kadastralekaart/api/v4_0/delta/custom.

Dat endpoint kan je vragen (requests) stellen. De meest voorkomende zijn GET en POST requests. GET requests zijn de requests die je je browser stelt als je naar een bepaalde webpagina gaat. POST requests zijn requests waarbij je wat informatie meegeeft. Die extra informatie bestaat (vaak) uit json. Dit is de json die in het voorbeeld in het bovengenoemde schema:

{
  "featuretypes": [
    "perceel",
    "kadastralegrens"
  ],
  "format": "gml",
  "geofilter": "POLYGON((211417.92 475752.4800000001,212390.64000000004 
475896.12,212916.48000000004 475818.84,212879.52000000005 475360.2,212950.08000000002 
475203.12,212839.2 475065.36,212819.04 474981.36,212819.04 474877.2,212772 474857.04,212792.16 
474769.68,212832.48 474705.84,212889.6 474695.76,213010.56000000003 474685.68,213044.16 
474611.76,213030.72 474450.48,212637.6 474423.6,212708.16 473956.56,211122.24000000002 
473849.04,210453.6 473896.08,210315.84000000003 473970,211417.92 475752.4800000001))"
}

Belangrijk onderdeel van de meegestuurde json is de geofilter. Deze bevat een polygoon van het gebied waar je data van wilt opvragen. Zo kan je van een gebied in een keer al je data opvragen. Deze polygoon is uitgedrukt in Well known text.

Een makkelijke manier om zonder code requests te doen (waaronder ook POST requests) is via postman. Dat helpt je om e.e.a. uit te proberen. Op die site is ook veel informatie te vinden over hoe postman werkt.

Je zou dit ook bijvoorbeeld met python kunnen doen:

import requests

url = "https://downloads.pdok.nl/kadastralekaart/api/v4_0/delta/custom"
data = {...}  # vul hier de bovenstaande json in.
response = requests.post(url, data)
print(response.json())

Als je een POST-request doet op het delta/custom endpoint krijg je niet direct de data terug, maar een url. We zijn namelijk bij het opvragen van de data je data aan het verwerken. De url die je van het postrequest terugkrijgt geeft de status aan van je download. Dat is een url die je met een GET-request kan benaderen (dus eventueel ook met je browser. Hier staat uitgelegd wat je terugkrijgt als je die url bevraagd. Onderdeel van de response van die url is de status:

"status": "RUNNING"

of de status:

"status": "COMPLETED"

Als de status completed is krijg je ook een download url te zien met de zip:

{
  "_links": {
    "download": {
      "href": "/lv/bgt/api/v1/extract/72f0d5d6-d34c-439b-a115-b53811aa8a72/extract.zip"
    }
  },
  "progress": 100,
  "status": "COMPLETED"
}

Die zip kan je dan weer uitpakken en bevat al je data.

Het is voor ons erg fijn als je op deze manier je data opvraagt. Het scheelt ons afhandelen van requests. Het geeft ons wat ruimte om even de tijd te nemen om de request te beantwoorden. En op deze manier kunnen we je precies het antwoord geven wat je nodig hebt.


Roel

3 likes

Dank je Roel voor de uitgebreide toelichting op de werking van de Restful api server. Ik programeer zelf in Csharp en heb inmiddels een vergelijkbaar oplossing gevonden voor de post en get aanvraag. Het is mij inmiddels op gevallen dat bij de GET aanvraag de download url (zip) niet meteen klaar staat. Er zit een vertraging in van ongeveer 3 seconden. Is dit op te lossen?

Ja dit is op te lossen, maar wel aan jouw zijde. Dit kan je doen door (asynchroon) te pollen.

Allereerst: de reden dat het een paar seconden duurt voor je data klaar staat, is dat we je data dynamisch voor je klaarzetten. Door dit te doen scheelt dat ons beiden netwerkverkeer. Het is makkelijker om in een keer een bestand bij elkaar te zoeken en over de lijn te sturen dan heel vaak kleine beetjes op te zoeken, waarbij we elke keer weer een connectie moeten maken, en op te sturen.

Je kan bijvoorbeeld om de seconde controleren tot de download gereed is. Let wel op dat je een wachttijd inbouwt. Als je dit zonder wachttijd doet, doe je namelijk een veel te groot beroep op onze service. Als je dat asynchroon doet, kan je zelf ook andere zaken oppakken. Als je queries stelt die gemiddeld langer duren kan je de wachttijd langer zetten.

Dit is een voorbeeld hoe ik ooit het asynchroon pollen op een andere api heb opgelost in Python.

Deze oplossing is uiteindelijk voor jou en voor ons het meest efficiënt. Over asynchroon in C# programmeren is hier informatie te vinden.

ik heb inmiddels een asyc-script voor het pollen van data…maar krijg sinds gisteren de melding terug dat de verificatie is mislukt omdat de andere partij (pdok) de transportstroom heeft gesloten

Bij het downloaden van de zip? Mogelijk helpt deze stackoverflow vraag je?
En vooral dit antwoord?

bij de POST request krijg ik de error. Afgelopen dagen ging het wel goed…Sinds gisteren niet meer…Ik gebruik het volgende script

        //Post aanvraag op de API server 
        using (var httpClientPost = new HttpClient())
        {
            using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://downloads.pdok.nl/kadastralekaart/api/v4_0//full/custom"))
            {
                request.Headers.TryAddWithoutValidation("Accept", "application/json");

                request.Content = new StringContent("{\"featuretypes\":[\"perceel\",\"kadastralegrens\",\"pand\",\"openbareruimtelabel\"],\"format\":\"gml\",\"geofilter\":\"POLYGON((211417.92 475752.4800000001,212390.64000000004 475896.12,212916.48000000004 475818.84,212879.52000000005 475360.2,212950.08000000002 475203.12,212839.2 475065.36,212819.04 474981.36,212819.04 474877.2,212772 474857.04,212792.16 474769.68,212832.48 474705.84,212889.6 474695.76,213010.56000000003 474685.68,213044.16 474611.76,213030.72 474450.48,212637.6 474423.6,212708.16 473956.56,211122.24000000002 473849.04,210453.6 473896.08,210315.84000000003 473970,211417.92 475752.4800000001))\"}", Encoding.UTF8, "application/json");

                var response = await httpClientPost.SendAsync(request);

            }
        }

Allereerst: Die post request doe je effectief maar 1 keer per vraag. Die pol je ook niet. Doe je dat ook?
Heb je voor het pollen een wachttijd ingesteld? Om de hoeveel tijd pol je? Uiteindelijk doet het er trouwens niet heel erg toe of je het synchroon of asynchroon implementeert.

Ik zou op deze request dat asynchroon even laten zitten. Hier krijg je namelijk vrij direct antwoord op. Sorry dat was misschien wat te ingewikkeld. In pseudocode is het dus de bedoeling dat je het volgende doet:

# vraag maar een keer de download aan:
response = http.post("https://downloads.pdok.nl/kadastralekaart/api/v4_0/delta/custom", data)
response_content = response.json()

# die vraag geeft een url die je aangeeft of je download klaar staat
poll_url = response_content["_links"]["status"]["href"]

loop:
    # poll de url die aangeeft of je download klaarstaat iedere paar seconden:
    poll_response = http.get(poll_url)

    # check de status code
    als poll_response not in ["200", "201"]:
        raise error "data ophalen geeft een error" + poll_response.status_code
        stap uit loop

    poll_content = poll_response.json()
    status = poll_content["status"]

    als status == "COMPLETED":
        # de data staat klaar, download de data
        content_url = poll_content["_links"]["download"]["href"]
        stap uit loop

    wacht 5 seconden

 http.download_to_file(content_url, filename)

Nog een toevoeging. Als je pollt wil je ook controleren of de response een 200 of 201 statuscode teruggeeft. Als het een 500 of 404 is wil je stoppen met pollen.

– edit: dit heb ik aan de pseudocode toegevoegd

Hoi Roel,

Dank voor de tips…ik ga het de komende dagen ff uitproberen…