DEV Community

Noble Ronin
Noble Ronin

Posted on

EU Public Tenders Have a Free JSON API — Every Notice, Buyer and Deadline Without Scraping

EU Public Tenders Have a Free JSON API

If you need EU public procurement data — who's buying what, from which government body, for how much, closing when — you do not need a scraper, and you do not need to pay one of the half-dozen "TED scraper" tools on the market. The EU's own TED (Tenders Electronic Daily) journal exposes all of it as clean JSON through an official, keyless v3 search API.

No sign-up. No API key. No token. Just a POST request.

The endpoint

POST https://api.ted.europa.eu/v3/notices/search
Enter fullscreen mode Exit fullscreen mode

Anonymous access — search and retrieval require no authentication at all (only submitting notices does).

Pull the newest notices

curl -X POST 'https://api.ted.europa.eu/v3/notices/search' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": "FT~\"cloud computing\" SORT BY publication-date DESC",
    "fields": ["publication-number", "notice-title", "buyer-name", "buyer-country", "deadline"],
    "limit": 10,
    "scope": "ACTIVE",
    "paginationMode": "ITERATION"
  }'
Enter fullscreen mode Exit fullscreen mode

query uses TED's expert-search syntax: FT~"..." for full-text, field filters like buyer-country=DEU or PD>=20260101 (publication date), combined with AND/OR, and SORT BY publication-date DESC to get live opportunities instead of the 2016 backlog. fields is an explicit allowlist — ask for exactly the eForms fields you want back (notice-title is always included even if you forget it).

What comes back

Each notice in the notices array is keyed by the same eForms field names you requested — notice-title, buyer-name, classification-cpv (procurement category codes), total-value / total-value-cur, deadline, links. Multilingual fields like the title arrive as an object keyed by language ({"eng": [...], "fra": [...]}) rather than a plain string — grab eng when present, fall back to whatever language is there.

Filter by country, value, category

# German buyers, AI-related, published this year
curl -X POST 'https://api.ted.europa.eu/v3/notices/search' \
  -H 'Content-Type: application/json' \
  -d '{"query": "FT~\"artificial intelligence\" AND buyer-country=DEU AND PD>=20260101 SORT BY publication-date DESC", "fields": ["publication-number","notice-title","buyer-name","total-value","deadline"], "limit": 50, "scope": "ACTIVE"}'
Enter fullscreen mode Exit fullscreen mode

Every EU tender notice as structured JSON

Page through results

Set paginationMode: "ITERATION" and bump page (or follow the pagination token TED returns) while limit stays at or under 100 per call. scope: "ACTIVE" returns currently-open notices; use "ALL" to search the full historical archive (480,000+ notices back to the mid-2010s).

The one gotcha

Field names are the eForms names (notice-title, classification-cpv, buyer-country) — not the old two-letter TED codes from the legacy API. If you copy a query from a pre-2023 blog post, expect it to 404 or return nothing; the schema changed with the eForms rollout.

That's the whole thing: one POST endpoint, an expert-search query string, and a field allowlist — no key, no proxy, no anti-bot to fight.


If you'd rather skip the pagination and the multilingual-field unwrapping, the EU Tenders Scraper on Apify wraps exactly this endpoint — keyword or expert query in, flat rows out (buyer, country, CPV, value, deadline, direct link).

📌 Full field reference + copy-paste query cheatsheet: github.com/noble-ronin/ted-tenders-api

Top comments (0)