TED API: how to export EU public tenders to CSV
TED (Tenders Electronic Daily) is where every EU public tender above the EU thresholds is published. It has an official search API that needs no key. This guide shows how to query it by country, CPV code and date, and how to get the results into a CSV. Every example below was run on 3 November 2026.
1. The endpoint
POST https://api.ted.europa.eu/v3/notices/search with a JSON body:
curl -s https://api.ted.europa.eu/v3/notices/search \
-H 'Content-Type: application/json' \
-d '{"query": "buyer-country=PRT AND classification-cpv=72* AND publication-date>=20261027",
"fields": ["publication-number", "notice-title", "buyer-name", "deadline-receipt-tender-date-lot"],
"limit": 100, "page": 1}'
On 3 November 2026 this returned 34 IT-services notices from Portuguese buyers published since 27 October (for example notice 742060-2026, Município de Cascais). The response took 0.4 s.
2. The query language
buyer-country=PRTuses ISO 3166-1 alpha-3 codes (PRT, ESP, FRA, DEU…).classification-cpv=72*matches a CPV prefix: 72 = IT services, 45 = construction, 33 = medical equipment, 90 = cleaning and environmental services.publication-date>=20261027takes dates asYYYYMMDD.- Combine conditions with
ANDandOR, and group them with parentheses:(buyer-country=PRT OR buyer-country=ESP). title-proc~"cloud"does a text search in the procedure title.
3. Pagination and limits
limitcan be at most 250. With 300 the API answers400 SEARCH_EXCEEDS_MAX_LIMIT.- Use
"page": 2, 3…and stop when a page returns fewer notices thanlimit.totalNoticeCountgives the total. - TED’s fair-use policy: at most 700 HTTP requests per minute and 600 notice downloads in 6 minutes per IP. A weekly export for one country uses a handful of requests.
4. Gotchas
- Multilingual fields.
buyer-nameandnotice-titlecome back keyed by language, sometimes as a list ({"por": ["…"]}) and sometimes as plain text ({"por": "…"}). Handle both.notice-titleincludes translations into every EU language and the first key is not the original: pick the language you want (engis always there). - Notice types. Results mix contract notices, award notices and prior information notices. Filter on
notice-type(values starting withcnare calls for competition) if you only want open tenders. - Values. Many notices have no estimated value. Expect empty fields, not zeros.
5. From JSON to CSV (Python)
import csv, httpx
body = {"query": "buyer-country=PRT AND classification-cpv=72* AND publication-date>=20261027",
"fields": ["publication-number", "publication-date", "notice-title", "buyer-name"], "limit": 250, "page": 1}
def first(v, lang="eng"): # {"eng": "…"} or {"por": ["…"]} or a plain value
if isinstance(v, dict):
v = v.get(lang) or next(iter(v.values()), "")
if isinstance(v, list):
v = v[0] if v else ""
return v or ""
rows = httpx.post("https://api.ted.europa.eu/v3/notices/search", json=body, timeout=60).json()["notices"]
with open("ted.csv", "w", newline="", encoding="utf-8") as f:
w = csv.writer(f); w.writerow(["number", "date", "title", "buyer"])
for n in rows:
w.writerow([n["publication-number"], n.get("publication-date", "")[:10], first(n.get("notice-title")), first(n.get("buyer-name"))])
6. Without code
To skip pagination, the multilingual fields and the scheduling, the EU Public Tenders Scraper (TED) on Apify runs the same official API with filters for countries, CPV codes, keywords, dates and minimum value. It exports to CSV, Excel or JSON and can run on a schedule. You pay per notice returned.
FAQ
Do I need an API key? Not for searching published notices. Keys from the TED Developer Portal are only needed for the eSender (publishing) APIs.
Can I reuse the data commercially? Yes. TED notices can be freely reused for commercial or non-commercial purposes under Commission Decision 2011/833/EU. Credit TED as the source.
How fresh is it? TED publishes new notices every working day (Tuesday to Saturday editions).
Source: TED, Publications Office of the European Union. Examples tested on 2026-11-03.