Every public tender above the EU thresholds is published on TED (Tenders Electronic Daily), and TED has an official, free search API. Paid alert services charge hundreds of euros a year for what is essentially a saved query. Here's the DIY version.
The query
TED's search API (https://docs.ted.europa.eu/api/latest/search.html) takes an "expert query", e.g. IT services (CPV 72000000) from German or Austrian buyers published today:
import requests, datetime
q = "classification-cpv IN (72000000) AND buyer-country IN (DEU AUT) AND publication-date=" + datetime.date.today().strftime("%Y%m%d")
r = requests.post("https://api.ted.europa.eu/v3/notices/search", json={
"query": q, "fields": ["publication-number", "notice-title", "buyer-name", "deadline-receipt-tender-date-lot"], "limit": 100})
for n in r.json()["notices"]:
print(n["publication-number"], n.get("notice-title"))
Turning it into alerts
- Store the publication numbers you've already sent (a small JSON file or a sheet).
- Run the script daily (cron, GitHub Actions) and send only new notices to email/Slack.
- Link each notice as
https://ted.europa.eu/en/notice/-/detail/<publication-number>.
Gotchas
- Field names are multilingual objects; pick your language and fall back to the original.
- Values and winners live in different fields for contract notices vs award notices.
- Paging: use the
iterationNextToken/page parameters, and keep queries narrow.
TED data is EU open data and can be reused, including commercially, with attribution.
Disclosure: I maintain a hosted version, TED Tenders Scraper on Apify, that flattens all of this into one row per notice with an "only new" alert mode ($2.50 per 1,000 notices). The snippet above is enough for a single saved search. If you'd rather get a ready Excel every Monday with all open IT tenders across Europe (English titles included), I also publish EU IT Tenders & Grants Weekly.
Top comments (1)
Providing a DIY blueprint for TED API monitoring is a fantastic service to the community. You are completely right—paying hundreds of euros annually for basic saved queries and cron jobs is an unnecessary tax on small agencies and indie developers.
Your technical breakdown highlights some very real production challenges when interacting with EU open data: