Document toolboxDocument toolbox

Documentatie SEARCH API

Inleiding 

Deze pagina beschrijft de API die je als gebruiker in staat stelt om zelf een aantal services te definiëren. Je vindt uitleg over de taal en syntax die je kan gebruiken en een oplijsting van de verschillende klassen en attributen die via de API bevraagbaar zijn. 

We werken aan de uitbouw van een aantal voorgedefinieerd services. Ondertussen stelt deze informatie je in staat zelf een aantal requests samen te stellen. Voor meer info, uitleg of ondersteuning kan je steeds contact opnemen met digitaal.vlaanderen@vlaanderen.be

Dynamische API-documentatie

https://api.wegwijs.vlaanderen.be/docs/api-documentation.html#tag/Zoeken

(Swaggerdocumentatie, downloadknop beschikbaar)

Technische documentatie (Github)

https://github.com/Informatievlaanderen/organisation-registry

Syntax en technische opbouw

De API’s in dit verhaal zijn standaard REST-gebaseerd en stuurt als respons JSON-files over HTTPS terug. Concreet spreken de verschillende mogelijke API’s een ‘index’ aan. Zo’n ‘index’ is op zijn beurt een representatie van (een deel van) het organisatieregister.  

In functie van de verschillende contexten/functionaliteiten kunnen verschillende ‘indices’ opgebouwd worden die – mits de correcte indexering – zeer performant kunnen inspelen op uw vraag.  

Centraal worden er vanuit Digitaal Vlaanderen een aantal indices ter beschikking gesteld die kunnen bevraagd worden via een reeks van requests. Tenzij anders vermeld zullen de indices standaard de totaliteit van het organisatieregister in termen van organisatie-scope bevatten. Per API wordt meegegeven wat deze omvat in termen van inhoud (welke velden, data). 

Eens je weet welke API het best aansluit bij je behoefte, is het zaak of een standaard geformuleerde request aan te spreken of eventueel zelf je request op te bouwen.

Voor het opbouwen moet er een bepaalde syntax gehanteerd worden. 

De standaardaanspreking is steeds als volgt : https://api.wegwijs.vlaanderen.be/, gevolgd door het versie-nummer van de api en de verdere zoekparameters. 

Regels en weetjes bij het gebruik van de API

Veel voorkomende bevragingen

Vraag

Query

Vraag

Query

zoeken naar een organisatie op basis van de OVO-code

https://api.wegwijs.vlaanderen.be/v1/search/organisations?q=ovoNumber:OVO002949 

zoeken naar een organisatie op basis van de naam van de organisatie (geen exacte match)

https://api.wegwijs.vlaanderen.be/v1/search/organisations?q=name:%22agentschap%20Digitaal%20Vlaanderen%22

zoeken naar een organisatie op basis van de naam van de organisatie (exacte match) hoofdlettergevoelig

https://api.wegwijs.vlaanderen.be/v1/search/organisations?q=name.keyword:"agentschap Digitaal Vlaanderen"

zoeken naar een organisatie op basis van het KBO-nummer

https://api.wegwijs.vlaanderen.be/v1/search/organisations?q=kboNumber:0244142664

zoeken naar een organisatie op basis van de Vlimpers-code (exacte match)

https://api.wegwijs.vlaanderen.be/v1/search/organisations?q=keys.value.keyword:"1 C 3E"

Organisatieregister API-v1

Conform afspraken binnen de URI-strategie werken we binnen het aanbod van webservices op het organisatieregister in verschillende versies.  

Versie 1 van de API is vooral gestuurd vanuit organisatie-standpunt. Je stelt een vraag en krijgt een volledige set van organisatiegerelateerde informatie terug.  

ondersteunt 2 commando’s:

  • een GET-command dat voorziet in eenvoudige URL-based queries om data op te zoeken 

  • een POST-command dat het mogelijk maakt om meer complexe queries te gaan opstellen 

Voor het GET-command is de structuur vrij simpel en laagdrempelig. Hiermee is het slechts mogelijk om per object (klasse zoals verder in dit document bepaald) één filter toe te passen. Je kan bvb. wel alle organisaties opzoeken wiens naam begint met de term ‘Beleidsdomein’, maar je kan dat niet combineren met een filter op tijd in hetzelfde object. 

Het POST-command is een meer gesofisticeerde manier om de databank te bevragen, maar vereist wel meer voorkennis en een console om de vraag te lanceren. Hiermee kun je geneste queries opstellen (bvb. alle organisaties waarvan de naam begint met ‘Beleidsdomein’, met daarbinnen enkel degene die een einddatum hebben). 

Het GET-command werkt als volgt :    

De algemene structuur – https://api.wegwijs.vlaanderen.be/v1 – gevolgd door : 

/search/{indexnaam}?q={zoekterm}&fields={filter}&offset={start}&limit={aantal} 

Waarbij: 

  • Indexnaam, met momenteel keuze uit 3 endpoints waarbinnen je kan zoeken:

    1. organisations (organisaties)

    2. people (personen, bv. hun functies of hoedanigheden)

    3. bodies (organen)

  • Zoekterm: Elasticsearch QueryString zoekterm 

  • [Optioneel] Filter: veldnamen die in respons zullen zitten 

  • [Optioneel] Offset: startpunt van zoekresultaten (voor paging bijvoorbeeld) 

  • [Optioneel] Limit: aantal resultaten, default 100 (ook voor paging) 

Bijvoorbeeld: 

/search/organisations?q=Vlaanderen&fields=name,ovoNumber&offset=10&limit=1000 

Het POST-commando geeft zoals vermeld veel meer mogelijkheden, oa. geneste zoekopdrachten binnen één klasse. Om een POST-opdracht te geven, kun je niet werken via een URL. Je moet een script op de cluster laten draaien via een scripting-tool (vb. POSTMAN). 

De standaardsyntax bestaat uit : 

/search/{indexnaam}? fields={filter}&offset={start}&limit={aantal}

…….. query object 

}  

Waarbij de parameters dezelfde zijn als bij het GET-commando, behalve dat je geen zoekterm, maar een volledig zoekobject kan meegeven in de body. 

Bijvoorbeeld:

    "nested" : {                               "path" : "capacities",                               "query" : {                                                   "bool" : {                                                                   "must" : [                                                                     { "match" : {"capacities.capacityName" : "HR business partner"} },                                                                     { "bool": {                                                                       "should": [                                                                         { "range" : {"capacities.validity.end" : {"gte" : "now/d"}} },                                                                         { "bool": {                                                                           "must_not": [ { "exists": { "field": "capacities.validity.end"}} ]                                                                         } }                                                                       ]                                                                     }}                                                                   ]                                                   }                                   }                    }    } 

Dit geeft dan bvb. een overzicht van alle HR business partners. 

Omgaan met grote hoeveelheden data

By default beperkt de api zich tot 100 hits en met de optie ‘&limit=’ kan dit opgetrokken worden tot 10.000. Maar wat als je om een bepaalde reden meer dan 10.000 organisaties wil opvragen in één request? 

Voor dat scenario kan je volgende werkwijze volgen :  

  • Maak een request zoals je normaal doet, maar maak geen gebruik van ‘offset’ of ‘limit’. Gebruik in plaats daarvan ‘scroll=true’

  • Dit geeft 100 resultaten die je gewoon kan verwerken. In aanvulling krijg je hierdoor ook een http-header x-search-metadata die een Scroll-Id bevat, samen met nog wat andere info. (deze header is een json-string). 

  • Na deze request heb je 30 seconden de tijd om een call te doen naar https://api.wegwijs.vlaanderen.be/v1/search/people/scroll?id=SCROLLID

  • Deze zal je de volgende pagina geven (opnieuw 100 items), samen met de x-search-metadata header en een nieuwe scrollId. 

  • Herhaal dit proces tot je geen nieuwe items meer krijgt. 

Deze methodiek geeft je de zekerheid dat je geen organisaties over het hoofd ziet door veranderingen tussen calls. Dit werkt op een snapshot genomen bij je eerste request.  

Als je om één of andere reden niet in de mogelijkheid bent 100 items te verwerken in 30 seconden, is het best zelf logica te voorzien om de data op te slaan en nadien te verwerken. 

Omgaan met wijzigingen in data (enkel wijzigingen opvragen)

Als je enkel wijzigingen wil binnenhalen op de reeds ingelezen data kan je gebruik maken van de changeId.

Maak een request voor alle organisaties met als zoekterm de laatste changeId + 1 om alle nadien gewijzigde informatie te verkrijgen. Het changeId geeft aan dat informatie m.b.t. de organisatie gewijzigd is (maar geeft niet aan welke informatie gewijzigd is, bv. een naamswijziging of een nieuwe woordvoerder).

"changeId": 628782,         "changeTime": "2020-04-13",         "id": "743efdbf-42a5-4b62-9c27-956bbbcfd66c",         "name": "Centrum voor Jeugdtoerisme",

Voorbeeld code

Onderstaande code, geschreven in Python, zal alle organisaties opvragen wiens naam het woord dienst bevat en voor deze organisaties een aantal gegevens tonen:

  • OVO-code

  • Naam van de organisatie

  • of deze actief is

  • de naam van de eventuele moeder-organisatie

import requests import json from datetime import date def main(): # Samenstellen van de URL base_url = "https://api.wegwijs.vlaanderen.be/v1/search/organisations" query_string = "?q=name:dienst" url_string = base_url + query_string + "&scroll=true" aantal_organisaties = 0 # Deze op het eerste zicht oneindige lus wordt in de code onderbroken wanneer er # geen verdere resultaten meer beschikbaar zijn. while True: response = requests.get(url_string) res = response.json() # lus afbreken als er geen verdere resultaten meer zijn if len(res) == 0: break aantal_organisaties += len(res) for org in res: print(org["ovoNumber"] , org["name"], "-", isvalid(org["validity"]), "-", getParent(org)) resp_header = json.loads(response.headers["x-search-metadata"]) url_string = base_url + "/scroll?id=" + resp_header["scrollId"] print(f'\n==> {aantal_organisaties} organisaties gevonden') def getParent(org): """ zoeken naar het attribuut parents en daarbinnen enkel de geldige lijn opzoeken Van deze lijn wordt de naam van de parent opgehaald Noot: in theorie is het niet mogelijk, maar bij wijze van code voorbeeld en uit veiligheidsoverwegingen wordt er ook rekening mee gehouden dat er 2 actieve parents zouden kunnen zijn. """ if "parents" in org: # wat volgt is de uitgeschreven versie van de volgende python constructie: # return "-".join([key[field] for key in org["parents"] if isvalid(key["validity"])]) resultaat = "" for key in org["parents"]: if isvalid(key["validity"]): if len(resultaat)>0: resultaat += "-" resultaat += key["parentOrganisationName"] return resultaat else: return "" def isvalid(val, compare=date.today()): valid = True if "start" in val: if date.fromisoformat(val["start"]) > compare: valid = False if "end" in val: if date.fromisoformat(val["end"]) < compare: valid = False return valid if __name__ == "__main__": main()