Datagedreven Inschrijven met de TenderNed API
Als opdrachtnemer in de wereld van aanbestedingen weten we als geen ander hoe cruciaal het is om goed geïnformeerd en strategisch te werk te gaan. De sleutel tot succes ligt vaak verscholen in de details, en daar komt de kracht van datagedreven werken om de hoek kijken.
In dit artikel wordt de werking van de TenderNed API beschreven, met als doel om het inschrijvingsproces naar een hoger niveau te tillen door data centraal te stellen. Met toegang tot de informatie en inzichten geboden door datagedreven werken is het mogelijk om beter en sneller te bepalen op welke opdrachten in te schrijven en vervolgens de inschrijving nauwkeurig af te stemmen op de behoeften en eisen, wat resulteert in een verhoogde kans op toekenning van de opdracht.
De kracht van datagedreven inschrijven
Datagedreven te werk gaan maakt het mogelijk om beslissingen te nemen op basis van feitelijke inzichten en trends. Deze aanpak stelt opdrachtnemers in staat om de omslag te maken van transactioneel naar strategisch handelen, gebaseerd op harde gegevens. Zo kan een opdrachtnemer beter en sneller bepalen op welke opdrachten in te schrijven en welke juist niet, bijvoorbeeld door de documenten van aanbestedingen geautomatiseerd te verwerken. Zodra bepaald is om op een opdracht in te schrijven maakt datagedreven werken het mogelijk om een op maat gemaakte inschrijving te doen, door informatie uit verschillende bronnen te combineren, waarmee de kans op succes aanzienlijk wordt vergroot. Het gebruik van de TenderNed API vormt een solide basis voor datagedreven werken binnen het aanbestedingsproces.
Het gebruiken van de API van TenderNed
De TenderNed API vormt een basis voor het implementeren van datagedreven inschrijvingsstrategieën in het aanbestedingsproces. Een API, of Application Programming Interface, is een set van regels en protocollen waarmee verschillende softwareapplicaties met elkaar kunnen communiceren. De TenderNed API biedt de mogelijkheid om real-time alle publicaties en bijbehorende documenten op te halen. De API bestaat uit twee verschillende onderdelen:
1. Publicatie Webservice (TNS)
2. TenderNed API
De publicatie webservice wordt gebruikt om publicaties op te halen, en maakt gebruik van JSON. Vervolgens wordt de TenderNed API aangeroepen om de daadwerkelijke publicatie op te halen in XML-formaat. De opgehaalde XML is in het eForms formaat beschikbaar gesteld. Dit formaat wordt gebruikt om publicaties naar Europa te sturen.
Om gebruik te maken van de TenderNed API is een gebruikersnaam en wachtwoord benodigd. Deze kan worden aangevraagd via functioneelbeheer@tenderned.nl. De Publicatie Webservice is openbaar toegankelijk.
Voor de volgende stappen is Python benodigd, bijv. Python 3.11.
Ophalen van relevante publicaties
Als eerste worden de publicaties opgehaald via de publicatie webservice (TNS). Het is van belang om hier te filteren op bijvoorbeeld datum en CPV-codes zodat enkel relevante publicaties worden opgehaald.
Om de API te benaderen wordt er gebruik gemaakt van de requests module. Deze module is een populaire en gebruiksvriendelijke tool waarmee ontwikkelaars HTTP-verzoeken kunnen maken en verwerken in hun programma's. Installeer de module met het volgende commando:
pip install requests
Met het volgende code blok wordt de TNS benaderd.
import requests
requests.get('https://www.tenderned.nl/papi/tenderned-rs-tns/v2/publicaties?page=0&size=50')
{
"first": true,
"last": false,
"totalElements": 119152,
"totalPages": 5958,
"size": 50,
"numberOfElements": 50,
"number": 0,
"contents": [...]
}
Dit resulteert in de bovenstaande JSON-geformatteerde reponse. Het contents attribuut bevat 50 publicaties. Het aantal publicaties dat opgevraagd wordt is aangegeven door de parameter size in de URL. Om de volgende 50 publicaties op te halen hogen we het paginanummer op met 1, zoals: publicaties?page=1&size=50. Op deze manier kunnen alle publicaties worden geënumereerd.
In dit voorbeeld zijn wij geïnteresseerd in de bouw sector, en kiezen we voor de hoofdcategorie CPV-codes: 45000000-7 en 71000000-8. Dit geven we aan met de parameter cpvCodes=45000000-7&cpvCodes=71000000-8. Ook is het mogelijk om te filteren op publicatietypes, bijvoorbeeld op 'Aankondiging gegunde opdracht'. Dit wordt bereikt met het filter publicatieType=AGO
Tenslotte halen we alleen publicaties op tussen 1 januari 2023 en 30 juni 2023, met behulp van de filters publicatieDatumVanaf=2023-01-01&publicatieDatumTot=2023-06-30.
requests.get('https://www.tenderned.nl/papi/tenderned-rs-tns/v2/publicaties?page=0&size=50&publicatieType=AGO&publicatieDatumPreset=AGP&publicatieDatumVanaf=2023-01-01&publicatieDatumTot=2023-06-30&cpvCodes=45000000-7&cpvCodes=71000000-8')
{
"first": true,
"last": false,
"totalElements": 792,
"totalPages": 16,
"size": 50,
"numberOfElements": 50,
"number": 0,
"contents": [...]
}
Deze filters resulteren in 792 publicaties. In de volgende stap worden de individuele publicaties opgehaald.
Ophalen van een publicatie
In het vorige stuk is beschreven hoe relevante publicaties kunnen worden opgehaald. Vervolgens kunnen we de informatie uit deze publicatie ophalen via de TenderNed API (XML). Als voorbeeld gebruiken we de aankondiging van gegunde opdracht van de aanbesteding 'Vervangen ontvangstkelder RWZI Nieuwveer' van Waterschap Brabantse Delta. Deze publicatie heeft publicatie id 288629.
In dit voorbeeld wordt gewerkt met omgevingsvariabelen. Lees hier hoe deze gebruikt kunnen worden veilig gebruikersnamen en wachtwoorden te verwerken in applicaties.
import os
import requests
API_USERNAME = os.environ['TENDERNED_API_USERNAME']
API_PASSWORD = os.environ['TENDERNED_API_PASSWORD']
PUBLICATIE_ID = 288629
publication_xml = requests.get(f'https://www.tenderned.nl/papi/tenderned-rs-tns/v2/publicaties/{PUBLICATIE_ID}/public-xml', auth=(API_USERNAME, API_PASSWORD)).text
Om de XML te parsen wordt er gebruik gemaakt van BeautifulSoup. Deze module maakt het eenvoudig om informatie uit HTML- en XML-documenten te extraheren. Installeer de module met het volgende commando:
pip install beautifulsoup4
Om de titel op te halen laden we eerst de XML in BS4. Vervolgens gebruiken we de find() functie om de juiste waarde te zoeken in de XML.
from bs4 import BeautifulSoup
soup = BeautifulSoup(publication_xml, 'xml')
title = soup.find('TITLE').get_text(strip=True)
descr = soup.find('SHORT_DESCR').get_text(strip=True)
contractor = soup.find('ADDRESS_CONTRACTOR').find('OFFICIALNAME').get_text(strip=True)
value=soup.find('AWARDED_CONTRACT').find('VAL_TOTAL')
title='Vervangen ontvangstkelder RWZI Nieuwveer'
descr='De opdracht betreft zeer grofstoffelijk, door middel van een bouwteam, een volledig herontwerp en optimalisatie van het ontvangstwerk op RWZI Nieuwveer...'
contractor='EQUANS Zuid-Nederland B.V.'
value=12250000.00
Documenten van een publicatie ophalen
Via de TNS kunnen ook documenten bij een publicatie worden opgehaald. Zie onderstaande code blok voor een voorbeeld.
Aanbestedingen die lopen via derde partijen, zoals Mercell, bevatten geen documenten in de TenderNed API.
PUBLICATIE_ID = 310654
pub_docs = requests.get(f"https://www.tenderned.nl/papi/tenderned-rs-tns/v2/publicaties/{PUBLICATIE_ID}/documenten").json()
for document in pub_docs["documenten"]:
doc_naam = document["documentNaam"]
doc_url = document["links"]['download']['href']
print(f"{doc_naam}: {doc_url}")
TN429741 - SF02 Aankondiging van een opdracht 20230920143650: /papi/tenderned-rs-tns/v2/publicaties/310654/documenten/9943458/content
Selectieleidraad - Inspecties civiele kunstwerken: /papi/tenderned-rs-tns/v2/publicaties/310654/documenten/9943394/content
Bijlage Y SROI bouwblokken juli 2023 DEFINITIEF: /papi/tenderned-rs-tns/v2/publicaties/310654/documenten/9917551/content
Bijlage D Standaardafwijkingen Haarlemmermeer op DNR 2011-versie 2021: /papi/tenderned-rs-tns/v2/publicaties/310654/documenten/9917550/content
Bijlage C Verklaring bekwaamheid derde - 2021: /papi/tenderned-rs-tns/v2/publicaties/310654/documenten/9917549/content
Bijlage B Model Referentieproject 2023-434: /papi/tenderned-rs-tns/v2/publicaties/310654/documenten/9917548/content
Bijlage A UEA: /papi/tenderned-rs-tns/v2/publicaties/310654/documenten/9917547/content
Toepassen in de praktijk
Met bovenstaand code is de basis gelegd voor het gebruik van de TenderNed API. Hier moet verder op worden gebouwd om aan de data behoefte van het aanbestedingsteam te voldoen. Een praktijk voorbeeld is bijvoorbeeld het analyseren van actieve aanbestedende diensten in een subset van de markt. AKIDA heeft een voorbeeld ontwikkeld hoe dit bereikt kan worden met de TenderNed API. Deze code is beschikbaar op Bitbucket.
Conclusie
Door de kracht van de TenderNed API te benutten en data centraal te stellen in het inschrijvingsproces, zet je als opdrachtnemer een goede stap richting succesvol aanbesteden. De mogelijkheid om real-time publicaties en bijbehorende documenten op te halen, biedt een bron van waardevolle informatie. Met deze informatie kan beter en sneller bepaald worden welke opdrachten goed bij jouw onderneming passen. Door informatie uit verschillende bronnen te combineren, zoals de TenderNed API, is het mogelijk om je inschrijving te verfijnen en strategisch af te stemmen op de vereisten van de aanbesteding. Het resultaat? Een aanzienlijk vergrote kans om als winnende partij uit de bus te komen.